Skip to content

chore: release 0.1.60 - #246

Merged
pallaoro merged 16 commits into
mainfrom
something-is-not-making-the-change
Sep 8, 2026
Merged

pallaoro merged 16 commits into
mainfrom
something-is-not-making-the-change

Conversation

@pallaoro

@pallaoro pallaoro commented Sep 8, 2026

Copy link
Copy Markdown
Member

Version bump only (apps/desktop/package.json + bun.lock). Ships what has landed on main since v0.1.59.

In this release

Note for boxes: settings sync needs the box on this release too. The desktop installs it on a box that is behind; until then the settings page names the box as not yet synced.

Selecting an old task and resuming it reopened whichever task in the repo
ran last. OpenCode scopes a session by its path RELATIVE to the project and
counts every git worktree of a repo as one project, so that path is "" for
every worktree root and they all share one continuation scope: `--continue`
returns the newest conversation in ANY of them. Worse than a confusing
transcript, a resumed session adopts its own recorded directory, so the
agent's tools were pointed at the other task's checkout.

Ateam never had an id to resume by. OpenCode mints its own, so
agent_sessions.agent_session_id was null for every OpenCode tab and both
resume paths (a restored tab, and "resume last conversation" for a task
with nothing stranded) fell through to `--continue`.

So pick the id here instead: `opencode session list --format json` lists
the project's root sessions with the directory each belongs to, and the
newest one for THIS worktree is the conversation the user asked for. It is
recorded as the session's agent_session_id, so later restores go straight
to `--session <id>` without the scan. Claude is untouched: it files
transcripts by cwd, so its `--continue` is already worktree-scoped.

A scan that cannot run keeps the old `--continue` behaviour, because an
imperfect resume beats silently starting a new conversation over one the
user asked to come back to. A scan that runs and finds nothing starts
fresh, which is the honest answer for a worktree with no conversation yet.

Deliberately the CLI and not the SQLite store that session search already
reads: a store that moved must fail loudly here rather than answer "no
sessions", and OpenCode is mid-migration to a v2 store while
`session list --format json` has been documented and unchanged since it
landed. Both readers now point at each other.
The name became required, so a create form that opens on the prompt asks you
to fill a field you cannot see the cursor in. Focus follows what the form is
for: a new loop starts on the name, an existing one already has one and opens
on the prompt, like the composer.

Focus is set from a ref rather than autoFocus, because the choice is
conditional and keyed on the loop's id, so a re-render never yanks the cursor
out of what you are typing.
…rminal

The toggle only decides whether the terminal shares the pane with a view
that covers it. With neither the editor nor Changes open the terminal is
full width regardless, so the button sat there inert, and an active-looking
control that does nothing reads as a bug in the thing it points at.

Gated on mainViewOpen rather than editorOpen: the terminal docks beside the
Changes view too, where the toggle still works.
…t is on

Two toolbar fixes:

- "Open worktree in your editor" now appears with the editor rather than in
  every task's toolbar. It belongs to the same gesture as the editor itself,
  so it shows up when that is on.
- The terminal-sidebar toggle paints its docked pane when the sidebar is
  showing, so the on-state is legible without relying on the active tint
  alone. lucide has no solid panel variant, so PanelRightFilled repeats its
  geometry exactly and only adds the fill: the icon must not appear to move
  when it toggles.

Verified by rendering both states at 16, 32 and 96px.
Agents need a browser, and the one that is useful is the one you are already
signed into: a fresh browser meets a login wall on its first useful step.
This hands the task to your own Chrome on this Mac, which the TaskWindow
extension then drives, so every session it holds is already there.

Client-native like "Open worktree in your editor", and for the same reason:
a browser is a desktop app, not something the engine can launch. Unlike the
editor there is no Remote-SSH equivalent, so a task on a box says so rather
than silently raising this Mac's Chrome and showing the wrong machine's
pages; a box gets its own headed Chrome (docs/browser-box.md), not built yet.

It sits after the editor and the editor's own controls, so each app keeps
its controls beside it.

Verified in the dev app: the button raises Chrome, and with the editor open
the row reads VS Code, sidebar, open-externally, Chrome.
User preferences move out of the engine's SQLite and into a hand-editable
~/.ateam/settings.json, with a settings page to edit them (gear beside the
sidebar toggle, ⌘, in the app menu).

Why a file: the `settings` table was live for exactly two values the ENGINE
writes about its own machine (hookPort, loginPath), and no production code had
ever written a preference column, so every user's defaults were untouched and
the move costs no migration. A file is what a developer expects (Cursor,
Claude Code, Herdr all converged on one), it can be read, grepped, diffed and
symlinked from a dotfiles repo, and it separates the two kinds of state the
way VS Code does between settings.json and workspace storage. The preference
columns stay, marked deprecated: dropping one is a table rebuild in SQLite.

One schema, one path, two readers, after Herdr's client/server split:
`client.*` is read by the desktop on the Mac running it, `engine.*` by
whichever engine runs the work, so a box reads its own file and a font can
never become a property of a box. Only keys with a reader exist: the four
engine values that were already read (default agent for headless jobs, merge
and update strategy, delete-remote-branch), and one client value wired here
(download updates automatically, which the updater now honours).

The file layer versions itself, writes atomically (tmp + rename), keeps
unknown keys, and sets a broken file aside as `.bad` with a warning the page
shows rather than a silent fallback. `settings:get`/`update` reach whichever
engine is selected, so the page says which machine's file it is showing.

The page is data-driven: every row is an entry in ROWS (title, description,
where it lives, control), which is what makes ⌘F search across sections
possible and keeps a new setting to one entry.

Verified in the dev app: the page renders from the real file, a toggle
round-trips to disk and back, search narrows rows and disables empty
sections; 471 tests pass, 8 of them new for the file layer.
…r toggle

The nav is the page's tabs, not an index into one long scroll: picking a
section shows that section and nothing else. A search still looks across
every section, since one confined to the section you happen to be on would
miss the row you want; its results stand in for the section view while it is
typed, grouped by where each row lives, and picking a section clears it.

Verified in the dev app: General alone on open, Git alone after picking it,
a search crossing sections, and picking a section clearing the search.
With `client.syncEngineSettingsToBoxes` (on by default) this Mac's `engine.*`
is the source of truth: pushed to every box the moment it connects and again
on every change, so a fresh box inherits your choices and a disposable one
never has to be configured. Boxes still read their own FILE, so a loop
ticking with no desktop attached keeps working; the mirror is what makes that
true. Off, each machine keeps its own and the page edits whichever
environment is selected, labelled as such. `client.*` never syncs.

The settings channels are the one call the host does not route by task or by
the selected environment: with sync on they go to this Mac and an update fans
out, so the page always edits the file that wins.

The page reports the LAST real push per box, never "connected" as "synced".
A push that fails (an engine older than settings sync, the ordinary case
until the next release lands on a box) is named with its reason, and never
fails the connect or the edit.

Verified in the dev app against two live boxes: both run a released engine
without settings:update, the pushes failed, and the page said so with the
reason rather than claiming sync.
…ng-the-change

# Conflicts:
#	apps/desktop/src/renderer/src/App.tsx
#	docs/online-ateam.md
@pallaoro
pallaoro merged commit 0dd20b0 into main Sep 8, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant