Skip to content

Lead the ca Manage tree with agents instead of projects - #1067

Merged
codyde merged 3 commits into
railway/ca-manage-reset-refresh-authfrom
railway/agent-first-manage-tree
Aug 11, 2026
Merged

Lead the ca Manage tree with agents instead of projects#1067
codyde merged 3 commits into
railway/ca-manage-reset-refresh-authfrom
railway/agent-first-manage-tree

Conversation

@codyde

@codyde codyde commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator

What

Reworks the railway ca Manage screen's left tree from project-first to agent-first. Same layout, same panes — only the tree changes.

Before: workspace > project > environment > agent > session, five levels with agents at depth 3 behind two expand clicks, even though myCloudAgents already fetched everything at startup.

After:

╭ cloud agents ────────────────╮
│▾ data-pipeline               │   ← group: env with agents, always open
│  ● builder                   │   ← agents at depth 1, status glyphs
│    ↳ happy-otter             │   ← sessions still nested beneath
│  ○ scraper                   │
│▾ data-pipeline/staging       │   ← env named only when it says something
│  ○ helper                    │
│────────────────────────────  │
│▾ other projects  (2)         │   ← collapsible browse/create tail
│  ▸ shiny-app  (default)      │
│  ▸ playground                │
╰──────────────────────────────╯

How

  • Every environment with agents becomes an always-expanded top-level group (RowKind::Group), labelled project (or project/env when the env isn't production and the project has several). Groups sort by liveliness (running first), then default project, then name; within a group agents sort running → starting → sleeping.
  • Sessions keep today's behavior: nested under their agent, expand-on-highlight, lazy fetch.
  • Agent-less environments live under a collapsible "other projects" tail — default project first and undimmed, auto-open on an empty account (with a no cloud agents yet — n creates one hint), auto-folded once groups exist, sticky once toggled. Projects whose production has agents but whose staging is empty appear in both places, so every environment stays reachable for n / t / r.
  • Workspace rows appear in the tail only when the account has more than one workspace; on group headers the workspace shows as a dim note instead of a level.
  • Refreshes (r, and the wake/sleep watch poll) no longer blank a loaded environment while the reply is in flight — groups stay put instead of flickering out every poll tick — and a failed refresh keeps the stale list with the error in the status line.
  • Cursor anchoring is by row identity, including across an environment being promoted into a group (or demoted back), so loads and re-sorts never move the selection.
  • No data-layer changes: RowKind::Agent/Session index tuples and the WorkspaceNode/ProjectNode/EnvNode model are untouched; this is a rework of the rows() flattener, expansion/keyboard/mouse handlers, and rendering.

Testing

  • 236 cloud_agent tests pass — 13 rewritten to the new semantics, 10 new (group labels/sorting, separator behavior, tail counts and toggling, refresh-keeps-groups, failed-refresh-keeps-agents, reachable empty envs, n fallback from the tail header, cursor-follows-promotion, hint-state accuracy).
  • An adversarial review pass over the diff surfaced 3 real bugs (group flicker during watch polls, unreachable empty envs, premature "no agents yet" hint) and 2 UX gaps — all fixed in this branch with regression tests.
  • cargo fmt clean; clippy warning count identical to master (48, none in this module). The 3 auth_sim failures in the full suite fail identically on unmodified master (environment-dependent).

@codyde codyde added the release/minor Author minor release label Aug 11, 2026 — with Railway App
codyde added 3 commits August 11, 2026 05:24
Scrolling was clamped to one screenful — a documented workaround for
vt100 0.15's view composition underflowing past the screen height.
vt100 0.16 fixes that, and ratatui 0.30 (via ratatui-core) drops the
exact unicode-width pin that blocked the upgrade.

Bump both, migrate the moved Parser::set_size/set_scrollback calls to
Screen, drop the one-page ceilings in scroll_by and resize, and pin the
behavior with tests: full-depth scroll, multi-notch wheel walks, deep
offsets across resizes, churn (output + scroll + reshape interleaved),
retention-limit clamping, and a full-frame render from deep history.
Opt+] already cycles forward through open session panes; this adds the
reverse chord. Opt+[ is recognized where the terminal can express it
unambiguously: as a real ALT event under the kitty keyboard protocol
(which the TUI already enables), or as the composed curly double quote
macOS sends when Option is not mapped to Meta.

Under legacy Option-as-Meta, Opt+[ is the two bytes ESC [ — identical to
the CSI prefix every arrow key starts with — so it never surfaces as a
key event there. The chord goes dead in those terminals but can never
misfire or steal a cursor key.

Also updates the footer hint to advertise both directions.
The Manage screen is about cloud agents, but they rendered at depth 3 of a
workspace > project > environment > agent > session tree — two container
levels to expand before reaching the thing the screen exists to show, with
the environment level almost always a single-child passthrough.

Invert the presentation: every environment that has agents is promoted to an
always-expanded top-level group, labelled with its project (plus /env when
the environment isn't production and the project has several). Agents render
directly beneath with their status glyphs, sessions still nested under their
agent. Groups sort by liveliness — anything running floats up — then default
project, then name; the cursor is anchored by row identity so re-sorts never
move the selection.

Projects with agent-less environments wait in a collapsible "other projects"
tail, default project first and undimmed. The tail opens itself while there
are no agents to show (so a fresh account still gets the browse tree, behind
a hint) and folds away once groups exist; toggling it by hand sticks. Every
environment stays reachable there for n, t, and r — including empty ones in
projects whose other environments have agents.

Refreshes no longer blank a loaded environment while the reply is in flight,
so groups stay put through the wake/sleep watch polls, and a failed refresh
keeps the stale list with the error in the status line instead of hiding
agents that exist. The data model and RowKind index tuples are unchanged —
this is a rework of the rows() flattener, the expansion handlers, and the
rendering; myCloudAgents already delivered everything at startup.
@codyde
codyde force-pushed the railway/agent-first-manage-tree branch from 88f4cb4 to 3adbda5 Compare August 11, 2026 05:29
@codyde codyde removed the release/minor Author minor release label Aug 11, 2026
@codyde codyde added the release/minor Author minor release label Aug 11, 2026 — with Railway App
@codyde
codyde changed the base branch from master to railway/opt-bracket-back August 11, 2026 05:30
Base automatically changed from railway/opt-bracket-back to railway/ca-manage-reset-refresh-auth August 11, 2026 05:34
@codyde
codyde merged commit 50c0d67 into railway/ca-manage-reset-refresh-auth Aug 11, 2026
11 checks passed
@codyde
codyde deleted the railway/agent-first-manage-tree branch August 11, 2026 05:34
codyde added a commit that referenced this pull request Aug 11, 2026
* Unlock full scrollback depth in railway ca session panes

Scrolling was clamped to one screenful — a documented workaround for
vt100 0.15's view composition underflowing past the screen height.
vt100 0.16 fixes that, and ratatui 0.30 (via ratatui-core) drops the
exact unicode-width pin that blocked the upgrade.

Bump both, migrate the moved Parser::set_size/set_scrollback calls to
Screen, drop the one-page ceilings in scroll_by and resize, and pin the
behavior with tests: full-depth scroll, multi-notch wheel walks, deep
offsets across resizes, churn (output + scroll + reshape interleaved),
retention-limit clamping, and a full-frame render from deep history.

* feat(ca): add Opt+[ to cycle back to the previous session

Opt+] already cycles forward through open session panes; this adds the
reverse chord. Opt+[ is recognized where the terminal can express it
unambiguously: as a real ALT event under the kitty keyboard protocol
(which the TUI already enables), or as the composed curly double quote
macOS sends when Option is not mapped to Meta.

Under legacy Option-as-Meta, Opt+[ is the two bytes ESC [ — identical to
the CSI prefix every arrow key starts with — so it never surfaces as a
key event there. The chord goes dead in those terminals but can never
misfire or steal a cursor key.

Also updates the footer hint to advertise both directions.

* Lead the ca Manage tree with agents instead of projects

The Manage screen is about cloud agents, but they rendered at depth 3 of a
workspace > project > environment > agent > session tree — two container
levels to expand before reaching the thing the screen exists to show, with
the environment level almost always a single-child passthrough.

Invert the presentation: every environment that has agents is promoted to an
always-expanded top-level group, labelled with its project (plus /env when
the environment isn't production and the project has several). Agents render
directly beneath with their status glyphs, sessions still nested under their
agent. Groups sort by liveliness — anything running floats up — then default
project, then name; the cursor is anchored by row identity so re-sorts never
move the selection.

Projects with agent-less environments wait in a collapsible "other projects"
tail, default project first and undimmed. The tail opens itself while there
are no agents to show (so a fresh account still gets the browse tree, behind
a hint) and folds away once groups exist; toggling it by hand sticks. Every
environment stays reachable there for n, t, and r — including empty ones in
projects whose other environments have agents.

Refreshes no longer blank a loaded environment while the reply is in flight,
so groups stay put through the wake/sleep watch polls, and a failed refresh
keeps the stale list with the error in the status line instead of hiding
agents that exist. The data model and RowKind index tuples are unchanged —
this is a rework of the rows() flattener, the expansion handlers, and the
rendering; myCloudAgents already delivered everything at startup.
codyde added a commit that referenced this pull request Aug 11, 2026
* Add railway ca manage, clear cached auth on refresh, and setup reset

`railway ca manage` jumps the TUI straight to the manage screen, skipping
the front-door menu. `--refresh-auth` now clears the local Claude
setup-token cache before re-minting, instead of only skipping the
remote reuse check (a stale/revoked cached token previously never got
replaced). `railway ca setup --reset`, and a "Reset to default" choice
in the interactive prompts, clear saved cloud agent preferences and the
cached token together.

* Unlock full scrollback depth in railway ca session panes (#1065)

Scrolling was clamped to one screenful — a documented workaround for
vt100 0.15's view composition underflowing past the screen height.
vt100 0.16 fixes that, and ratatui 0.30 (via ratatui-core) drops the
exact unicode-width pin that blocked the upgrade.

Bump both, migrate the moved Parser::set_size/set_scrollback calls to
Screen, drop the one-page ceilings in scroll_by and resize, and pin the
behavior with tests: full-depth scroll, multi-notch wheel walks, deep
offsets across resizes, churn (output + scroll + reshape interleaved),
retention-limit clamping, and a full-frame render from deep history.

* feat(ca): add Opt+[ to cycle back to the previous session (#1066)

* Unlock full scrollback depth in railway ca session panes

Scrolling was clamped to one screenful — a documented workaround for
vt100 0.15's view composition underflowing past the screen height.
vt100 0.16 fixes that, and ratatui 0.30 (via ratatui-core) drops the
exact unicode-width pin that blocked the upgrade.

Bump both, migrate the moved Parser::set_size/set_scrollback calls to
Screen, drop the one-page ceilings in scroll_by and resize, and pin the
behavior with tests: full-depth scroll, multi-notch wheel walks, deep
offsets across resizes, churn (output + scroll + reshape interleaved),
retention-limit clamping, and a full-frame render from deep history.

* feat(ca): add Opt+[ to cycle back to the previous session

Opt+] already cycles forward through open session panes; this adds the
reverse chord. Opt+[ is recognized where the terminal can express it
unambiguously: as a real ALT event under the kitty keyboard protocol
(which the TUI already enables), or as the composed curly double quote
macOS sends when Option is not mapped to Meta.

Under legacy Option-as-Meta, Opt+[ is the two bytes ESC [ — identical to
the CSI prefix every arrow key starts with — so it never surfaces as a
key event there. The chord goes dead in those terminals but can never
misfire or steal a cursor key.

Also updates the footer hint to advertise both directions.

* Lead the ca Manage tree with agents instead of projects (#1067)

* Unlock full scrollback depth in railway ca session panes

Scrolling was clamped to one screenful — a documented workaround for
vt100 0.15's view composition underflowing past the screen height.
vt100 0.16 fixes that, and ratatui 0.30 (via ratatui-core) drops the
exact unicode-width pin that blocked the upgrade.

Bump both, migrate the moved Parser::set_size/set_scrollback calls to
Screen, drop the one-page ceilings in scroll_by and resize, and pin the
behavior with tests: full-depth scroll, multi-notch wheel walks, deep
offsets across resizes, churn (output + scroll + reshape interleaved),
retention-limit clamping, and a full-frame render from deep history.

* feat(ca): add Opt+[ to cycle back to the previous session

Opt+] already cycles forward through open session panes; this adds the
reverse chord. Opt+[ is recognized where the terminal can express it
unambiguously: as a real ALT event under the kitty keyboard protocol
(which the TUI already enables), or as the composed curly double quote
macOS sends when Option is not mapped to Meta.

Under legacy Option-as-Meta, Opt+[ is the two bytes ESC [ — identical to
the CSI prefix every arrow key starts with — so it never surfaces as a
key event there. The chord goes dead in those terminals but can never
misfire or steal a cursor key.

Also updates the footer hint to advertise both directions.

* Lead the ca Manage tree with agents instead of projects

The Manage screen is about cloud agents, but they rendered at depth 3 of a
workspace > project > environment > agent > session tree — two container
levels to expand before reaching the thing the screen exists to show, with
the environment level almost always a single-child passthrough.

Invert the presentation: every environment that has agents is promoted to an
always-expanded top-level group, labelled with its project (plus /env when
the environment isn't production and the project has several). Agents render
directly beneath with their status glyphs, sessions still nested under their
agent. Groups sort by liveliness — anything running floats up — then default
project, then name; the cursor is anchored by row identity so re-sorts never
move the selection.

Projects with agent-less environments wait in a collapsible "other projects"
tail, default project first and undimmed. The tail opens itself while there
are no agents to show (so a fresh account still gets the browse tree, behind
a hint) and folds away once groups exist; toggling it by hand sticks. Every
environment stays reachable there for n, t, and r — including empty ones in
projects whose other environments have agents.

Refreshes no longer blank a loaded environment while the reply is in flight,
so groups stay put through the wake/sleep watch polls, and a failed refresh
keeps the stale list with the error in the status line instead of hiding
agents that exist. The data model and RowKind index tuples are unchanged —
this is a rework of the rows() flattener, the expansion handlers, and the
rendering; myCloudAgents already delivered everything at startup.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release/minor Author minor release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant