Skip to content

feat: Zaplex 1.0 Release Candidate - #144

Open
iret77 wants to merge 137 commits into
mainfrom
release/v1.0
Open

feat: Zaplex 1.0 Release Candidate#144
iret77 wants to merge 137 commits into
mainfrom
release/v1.0

Conversation

@iret77

@iret77 iret77 commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Zusammenfassung

  • integriert den vollständigen Zaplex-1.0-RC-Stand für die offenen V1-Issues
  • härtet SFTP/SSH, Agent-Sitzungen, Cockpit, Themes, Workspaces und CLI-Bildanhänge
  • ergänzt Version 1.0.0, Release-Gates, Live-SFTP-Prüfung und den signierten Test-DMG-Workflow

Vorab-Verifikation

  • script/check-v1-release-readiness --self-test
  • script/check-v1-release-readiness --phase-a
  • git diff --check
  • neue Rust-Dateien mit rustfmt --check
  • Geheimnis-Dateinamen und bekannte Secret-Muster geprüft

Runtime-, Live-SFTP- und Build-Evidenz folgen ausschließlich über GitHub Actions. Die Issues werden erst nach erfolgreicher RC-Abnahme geschlossen.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

iret77 and others added 30 commits July 12, 2026 16:15
Establish app/src/ui_components/modal_frame.rs as the single source of truth
for modal chrome: the one scrim, the geometry band (radius 10 / width 440·480 /
padding 24 / title typography) and reusable frame builders — modal_card,
modal_overlay (unified backdrop-dismiss policy), modal_header and the shared
close ✕ (ActionButton + Icon::X) plus its CloseButtonTheme.

cockpit::style::{MODAL_RADIUS, modal_scrim} now re-export from modal_frame so
the cockpit's existing consumers keep working unchanged. Foundation for the WS1
migrations (spawn card, attention inbox, enum card, tab-config dialogs).

RC master plan WS1 (kills the token/scrim divergence behind M1–M9, V1–V2).
cargo check --bin zaplex --locked: green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ared frame

Both cockpit modals were fully hand-rolled overlays (own scrim, card chrome,
header and — for the inbox — a local CloseButtonTheme), the audit's flagship
M2/M3 foreign bodies. They now render through the shared modal_frame:

- modal_overlay: one centered scrim. The inbox (read-only) opts into
  click-outside dismiss; the Spawn-Karte (unsaved launch config) opts out — the
  two arms of the one dismiss policy. Fixes M3 (inbox had no backdrop dismiss).
- modal_card: one padding/background/radius/border/shadow recipe for both.
- modal_header: one title · subtitle · close ✕. The Spawn-Karte now carries the
  same corner ✕ as every other modal (added a close_button view; Option-typed so
  the pure unit-test literals keep constructing without a ViewContext).
- The inbox's local CloseButtonTheme moved into modal_frame (shared).

cockpit::style no longer re-exports MODAL_RADIUS/modal_scrim (no consumers left;
the cockpit reads them from modal_frame directly). Dead imports pruned.

RC master plan WS1 (M2, M3, and the V1/V2 divergence for cockpit modals).
cargo check --bin zaplex --locked: green, no new warnings.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ontract

Bring the generic Modal<T> (11 dialogs incl. params / new-worktree / session-
config wrappers) onto the one geometry + scrim: corner radius 8 → 10 (matching
modal_frame::MODAL_RADIUS) and the scrim tone from pure black to the shared
18/18/18 veil, with the alpha still caller-controllable (session-config keeps
its opt-out at opacity 0). One radius, one scrim tone across the generic dialog
path — kills the V1/V2 divergence for Modal-based dialogs.

RC master plan WS1. cargo check --bin zaplex --locked: green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ontract

- session_config_modal: the header now uses the shared modal_header (title ·
  subtitle · ✕) and the ✕ moved out of a separately-positioned corner overlay
  into the header row; retired the bespoke FormattedTextElement header + Stack
  overlay. Kills M5.
- new_worktree_modal: replaced the hand-rolled title + ESC-badge + ✕ header with
  modal_header; dropped the ESC badge (Esc still closes). Kills M6.
- enum_creation_dialog: aligned the card geometry to the contract (radius 8→10,
  border 2px→1px); it stays inside the workflow modal's blur veil so it takes
  the shared tokens without its own scrim/shadow. Addresses M8 geometry.
- Pruned the now-dead imports/consts these changes left behind.

RC master plan WS1. cargo check --bin zaplex --locked: green, no new warnings.
Note: English literals in these headers are intentionally kept for now — WS2
translates them once, in this final structure.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
params_modal used the same bespoke title + ESC-badge + ✕ header as the
new-worktree modal (audit M7/#4). Replaced it with the shared modal_header
(title · close ✕); dropped the ESC badge (Esc still closes via the wrapping
Modal). Pruned the imports/tokens it left dead.

With this the whole tab-config modal family (session-config, new-worktree,
params) plus the two cockpit modals and the enum shell share one header/close
grammar and one geometry. cargo check --bin zaplex --locked: green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Two independent read-only reviews (codex + grok) over the WS1 diff — no blockers.
Applied the two [should-fix] items:

- modal_overlay now wraps every modal card in a Dismiss with
  prevent_interaction_with_other_elements(), so a stray backdrop click can no
  longer reach a control in the workspace behind an open modal. Read-only modals
  still dismiss on that click (Some(action)); unsaved-input modals absorb it
  (None → no-op on_dismiss). Fixes the click-through both reviewers flagged.
- modal_header subtitle switched from Text::new_inline to soft-wrapping
  Text::new, so the long session-config subtitle wraps beside the ✕ instead of
  clipping.

Also fixed two stale comments grok caught (new_worktree header const doc, the
Modal::new(None,…) comment still mentioning the removed ESC badge).

The inbox card now using theme.background() (was a fixed dark PhenomenonStyle
surface) is the intended unification with the Spawn-Karte — theme-aware, one card
recipe — not a regression.

cargo check --bin zaplex --locked: green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the remaining chrome/action glyphs with icons::* font glyphs; the
deliberate status vocabulary (● ✋ ◦) stays.

- New shared helper cockpit::style::icon_word_verb (icon + trailing word, the
  icon-pass form of a labeled text verb; muted→accent on hover, same contract as
  verb_button).
- Sidebar review verb ◈ → Icon::Eye (panel.rs), now matching the adjacent
  favorite ★ icon on the row (kills IC2's text-glyph-next-to-icon mix).
- Dashboard-pane verbs: ◈ review → Eye, ◇ log → History, ⑂ fork / ⑂ +worktree →
  GitBranch (pane.rs).
- SSH host-persistence mark ⚡ → Icon::Lightning (ssh_manager/panel.rs).
- warp.ftl (en+de): stripped the embedded glyphs from cockpit-session-fork/
  fork-worktree/transcript and cockpit-spawn-card-freest(-named); reworded the
  ssh-tree-empty string to drop the 📁 emoji. (Kills IC1, IC4.)
- Terminal Zaplexify signature: dropped the ⚡ (branding stays as bold-cyan text).
- Swept the last ⚡◈◇⑂ out of doc comments so the acceptance check is clean.

Acceptance: rg '⚡|◈|◇|⑂' app/src → 0. cargo check --bin zaplex --locked: green.
Note: the non-listed compact verb glyphs (✓ ↻ ⎙ ⬈ ⚙ ⌫ ▸) intentionally remain a
text vocabulary per the plan's WS3 scope.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…e pane

CockpitPaneView::handle_pane_header_overflow_menu_action ended in
unimplemented!() — a panic, not a missing/disabled menu, if the framework ever
routed a header-overflow action here. The pane exposes no overflow-menu actions
(PaneHeaderOverflowMenuAction = ()), so the correct floor is a no-op, never a
crash. Kills the Class-A panic path (audit #15 / C2).

cargo check --bin zaplex --locked: green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
WS3 icon pass complete (codex-reviewed). WS5: the Class-A panic fixed; MCP/inbox/
C4 documented as needing runtime verification or (WS4-style) approval. WS2 fully
scoped but intentionally not started (avoid a half-translated locale). WS4 flagged
as needing the lost spec re-established + owner approval before any code.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Translate the primary-surface literals in the WS1-restructured dialogs, now that
their structure is final:
- session_config_modal: title + both subtitles → session-config-modal-*
- new_worktree_modal: title, select-repo/branch labels, autogenerate checkbox,
  name label + placeholder, invalid-name error → new-worktree-* (retired the
  const INVALID_BRANCH_NAME_ERROR)
- spawn_card: remote-dir editor placeholder → cockpit-spawn-card-remote-dir-placeholder

Added EN keys + German values in warp.ftl; also filled two DE gaps that fell
back to English: session-config-get-warping and
workspace-left-panel-ssh-manager-connecting (I4).

cargo check --bin zaplex --locked: green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The sidebar's always-visible metric copy was hard-coded English format! literals
(the audit's I1 — German locale with English fleet copy). Routed through warp.ftl:
today/cost line, ● active / ● waiting / ◌ running session lines, 5h/wk reset
lines, the host needs-me badge, the account-count (proper Fluent plural), the
5h·wk cost summary, and the ⤢ Dashboard button. Status glyphs ● ◌ ↻ ⤢ stay in
the strings (kept vocabulary); the English words are now translated (aktiv/
wartend/laufend, heute, Wo, Konto/Konten).

cargo check --bin zaplex --locked: green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…/WS4 partial)

- Re-create the lost 2026-07-11-cockpit-sidebar-redesign.md (WS4's opening step):
  the converged B2/B3/B4/D1+C2 decisions (two flat zone-cards, worktree/branch
  session identity, fixed metric line, provider≠plan + Codex plan_tier data fix,
  5h+week meters, click→detail-in-pane, binding hover=colour-only rule) plus the
  §12 supaterm learnings. Notes what WS1–3 already landed. Explicit approval gate:
  no sidebar code until the owner signs off (UI/UX concept-first rule).
- Ledger: WS2 marked partial (two highest-value primary surfaces done — sidebar
  runtime strings + migrated dialogs — remainder documented); WS4 marked
  spec-restored/awaiting-approval.

Docs only, no code. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- native_modal: the 'Don't show again.' checkbox label → native-modal-dont-show-again
- ai_page: the 'Show/Hide agent tips' and 'Show/Hide "Use Agent" footer'
  command-palette pairs, the 'Resets { $time }' paragraph, and the
  'Context window (tokens)' label → settings-ai-*

EN keys + German values added. cargo check --bin zaplex --locked: green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The commit/push/PR dialog (I2/#6, high-traffic) routed through warp.ftl:
- user_facing_git_error: return type &'static str → String, all 10 mapped error
  messages → git-dialog-error-*
- dialog titles (commit/publish/push/create-pr), Branch + Changes labels, the
  file/files count (proper Fluent plural), Commit-and-push/publish buttons, the
  commit/pushed/published toasts, Include-unstaged, Included-commits,
  default-branch fallback, Loading… → common-loading.

EN keys + German values added (informal du/dich tone). Dropped an unused
git-dialog-open-pr key ('Open PR' turned out to be comment-only).

Deferred (documented, own small follow-up): the 5 strings behind &'static str
APIs — the transient set_loading labels (Committing/Publishing/Pushing/Creating)
and the confirm-tooltip 'Enter a commit message'; translating them needs
set_loading + confirm_tooltip signature changes (String instead of &'static str).

cargo check --bin zaplex --locked: green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
scripts/check-i18n-literals.sh flags string literals in Text/Span render
constructors on the primary surfaces WS2 has fully localized (session_config,
new_worktree, native_modal), so they can't silently regress to hard-coded copy.
Deliberately scoped; extend FILES as more surfaces land. Wire into CI later.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ns noted

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Nits only: proper German typographic quotes „Use Agent" and
'Zurücksetzung: { $time }'. No arg/key/plural issues found in the WS2 pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…to plan_tier)

The Codex account builder set plan_tier = auth_mode ('chatgpt' / 'apikey'), which
is *how* you authenticate, not a subscription plan — so the sidebar rendered
'Codex · chatgpt' (the provider name in the plan slot). Codex exposes no plan
claim yet, so plan_tier is now honestly None. This is the data-model half of the
sidebar redesign's provider≠plan rule (WS4 S2); the two fixed provider/plan slots
land with the sidebar render (S3–S4). Updated the codex account test accordingly.

cargo check --bin zaplex --locked: green; targeted zaplex_cockpit codex tests pass
(the one failing codex_sessions '/tmp/proj' path test is a pre-existing env issue,
not this change).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…uild is the remainder

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…tte)

The redesign's tokens step. Add the shared visual vocabulary the Hosts and
AI-Accounts zone-cards render through, before the surface rebuilds (S3/S4):

- Contrast-tested heat palette (supaterm L1): `relative_luminance` +
  `contrast_ratio` (WCAG), two tuned tables (bright-on-dark / darker-on-light)
  and `heat_coloru_on(level, bg)` that returns whichever variant has the higher
  actual contrast against the surface — so a status dot / meter fill stays
  legible on either theme and never picks the worse variant on a mid-tone
  surface (codex review). `heat_coloru(level)` keeps its exact dark-theme output.
- `status_dot_coloru(state)` — status carried by colour, not a chrome glyph
  (spec §2.3): waiting = attention amber, working = ok green, idle = muted.
- `zone_card()` — the one flat zone-card builder: `surface_1`, 0.5px hairline
  border, radius 12, no shadow (spec §2.1). Plus `CARD_RADIUS`/`CARD_BORDER`
  and `METRIC_COL_WIDTH` for the fixed right metric column (spec §2.3).
- Unit tests assert every heat band clears WCAG 3:1 on both theme backgrounds.

Tokens only — no render surface consumes them yet (S3/S4 do). green:
`cargo check --bin zaplex --locked` + the 3 new style tests. codex + grok
reviewed read-only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Session identity in the redesigned sidebar is the worktree/branch, not the model
(spec §2.2) — this is what disambiguates several parallel Opus agents on one repo.
The data spine must carry it. Data-model only; the render consumes it in S3.

- `SessionSnapshot` gains `branch` / `worktree: Option<String>` (`#[serde(default)]`
  so older serialized snapshots still deserialize).
- `project.rs`: `ResolvedProject` gains the two fields, resolved by
  `resolve_worktree_identity()` reading Git plumbing directly (no subprocess):
  the branch from the **per-worktree** `HEAD` (a linked worktree reads its own
  gitdir under `worktrees/<name>`, not the shared common dir, so two worktrees
  of one repo report distinct branches), and the linked-worktree name from a
  `.git` *file*'s `gitdir:`. Detached HEAD / non-repo → `None` (never fabricated).
- Both producers (`sessions.rs`, `codex_sessions.rs`) populate the fields.
- Cross-host: proto fields 13/14 (`worktree`/`branch`), empty-string ⇔ `None`
  in both directions (`agent_session.rs`), symmetric with `effort` — an older
  daemon that omits them still decodes cleanly.
- Tests: new project_tests for per-worktree branch, linked-worktree name, and
  detached HEAD; proto round-trip + client_tests exercise the wire fields.

green: `cargo check --bin zaplex --locked`; `cargo test -p zaplex_cockpit`
(144 pass; the 3 pre-existing `/tmp/proj` failures are host env pollution — a
stray `/tmp/.git` makes `git_root` walk out of the hardcoded fixtures; they
assert `project_root`, untouched here); `cargo test -p remote_server` (74 pass).
codex + grok reviewed read-only (both LGTM).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The sidebar's Hosts half rebuilt as one flat object model (spec §2.1–2.3, §3):

- Two-zone layout: the Hosts object tree now leads in a flat `zone_card`
  (surface_1, hairline border, radius 12, no shadow); the AI-Accounts section
  follows below (S4 folds it into its own card).
- Fixed right metric column: each session is one fixed line
  `Dot · Branch · [provider Model·effort ctx%]`, with the metric cluster in a
  constant-width `ConstrainedBox` and the branch label `Shrinkable` — so the
  metrics never shift horizontally as the label grows (the jump defect the owner
  vetoed). Provider icon leads the cluster (`provider_icon`, muted).
- Status is a leading colour dot only (no chrome glyph): the host header dot
  inherits the worst child state (waiting ▸ working ▸ idle), so a host that needs
  you reads amber without opening it.
- Session identity = worktree/branch, never the model (`session_identity_label`:
  name → branch → worktree → project—dir) — this disambiguates parallel agents.
- D1+C2 density: waiting rows are always shown; the calm running/idle rows fold
  behind a per-host "N running · M idle — show" toggle (state keyed by stable
  host identity, retained + cleaned across reconciles; the summary omits a
  zero part). New FTL keys (en+de).
- Hover recolors only — no layout-shifting reveal (spec §2.7).

green: `cargo check --bin zaplex --locked`; i18n literal guard clean. codex +
grok reviewed read-only (both LGTM).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The sidebar's accounts half rebuilt to match the redesign (spec §2.1, §2.4–2.5):

- One flat AI-Accounts zone-card holding the fleet header + a flat block per
  account; per-card heavy chrome is gone — emphasis is content + spacing, and a
  block only gains a subtle fill on hover (colour, never layout — spec §2.7).
- Provider icon leads each card (spec §2.5).
- Provider · Plan as two fixed slots (spec §2.4): `provider_label` names the
  provider, and a "—" fills the plan slot when the tier is unknown, so the plan
  can never silently read as the provider (the S2 Codex `plan_tier` fix backs it).
- Both meters, not one merged headline (spec §2.5): a 5h and a week heat bar per
  card, replacing the single binding-window bar.
- Fleet total in the header is today · week (sum across accounts), not 5h · week.
- New FTL keys `cockpit-card-provider-plan` / `cockpit-card-plan-none` (en+de);
  `cockpit-header-cost-summary` retargeted to today·week.

green: `cargo check --bin zaplex --locked`; i18n literal guard clean. codex +
grok reviewed read-only (both LGTM).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Click → stable selection → detail in the pane; the sidebar stays a glance
surface (spec §2.6):

- `CockpitModel` gains a `selected_account` (the account key): `select_account`
  toggles it (a second click de-selects) and emits `Updated` only on change, so
  both the sidebar highlight and the pane focus refresh with no notify loop. The
  selection is cleared when the account vanishes (`apply`) and on disable
  (`clear_for_disabled` — its early-return now also checks `selected_account`, so
  a late click from a stale card can't leave a dangling selection; codex review).
- Sidebar account block: click selects the account and opens the pane; a selected
  block carries a stable `surface`-level fill, hover a lighter one — background
  only, never layout (spec §2.7).
- Reset countdowns removed from the sidebar card — they live only in the
  dashboard pane now (spec §2.6). The pane already renders them.
- Pane: the selected account card is lifted onto a stronger surface so the eye
  lands on the card the user clicked (background only, no reflow).

Session-row clicks keep attaching (a session's "detail" is its live terminal).

green: `cargo check --bin zaplex --locked`; i18n guard clean. codex + grok
reviewed read-only (codex's clear-on-disable edge case fixed; grok LGTM).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…tate)

The redesign's polish pass (spec §6, supaterm §12):

- L2: a host that folds to a one-line summary under the inverse-complexity law
  now keeps the loudest colour — its summary reads amber when it still needs you
  (needs_me > 0), so attention survives every collapse level instead of going
  muted the moment the host folds.
- Empty state: the Hosts card no longer vanishes when there are no live agents
  and no registered hosts. `render_conductor` always renders the card now — a
  calm "No agents or hosts yet" hint above the always-present "+ Add host" root
  — so a fresh sidebar guides the user instead of showing nothing. New FTL key
  `cockpit-conductor-empty` (en+de).

Deliberately deferred to their own tracked design items (spec §3): the fixed-size
peek popover (L3, #115) and the plan-list-primary pane surface (L4, #114) are
separate features, not sidebar-layout polish.

green: `cargo check --bin zaplex --locked`; i18n guard clean. codex + grok
reviewed read-only (both LGTM). Completes WS4 (S1–S6) of the RC master plan.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…c str holdouts)

WS2 left five git-dialog strings in English because they sat behind `&'static str`
APIs that a `t!` (→ `String`) couldn't feed. The button API was never the real
blocker — `ActionButton::set_label` already takes `impl Into<Cow<'static, str>>`
and `set_tooltip` `Option<impl Into<String>>`. Only the dialog's own wrapper
signatures were static. Widened locally:

- `GitDialog::set_loading` takes `String`; `commit::confirm_tooltip` returns
  `Option<String>`.
- The five strings now come from Fluent (en+de): the loading labels
  Committing / Publishing / Pushing / Creating and the "Enter a commit message"
  confirm tooltip (`git-dialog-loading-*`, `git-dialog-commit-need-message`).

Closes WS2 remaining item (b). green: `cargo check --bin zaplex --locked`; i18n
literal guard clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ax) root)

Clicking the file-manager toggle on an SSH pane (e.g. devhost) hard-crashed the
app (SIGABRT). `SftpBrowserView::render` rooted in a bare
`Flex(MainAxisSize::Max)`, and `PaneView` mounts every child view as a
`Shrinkable` flex child — so the view root was measured with an infinite main
axis and tripped the flex `debug_assert` (fast/debug DMG). The remote pane hits
the "Connecting…" branch first, which is why it reproduced on SSH.

Wrap both render roots (the not-connected branch and the connected body) in a
tight `Container`, the same remedy `CodeView` uses. Found by adversarial review.

green: `cargo check --bin zaplex --locked`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…nfig_dir pin)

Clicking a remote agent session in the cockpit opened a pane that tried to
connect but nothing came up. The remote resume ran `codex resume <id>` under the
host's DEFAULT login, so a plexed session living under a non-default CODEX_HOME /
CLAUDE_CONFIG_DIR on the host was never found — a silent dead pane.

Thread the session's account config dir through so the resume pins it:

- `SessionSnapshot` gains `config_dir: Option<String>` (the host-side account
  dir); `Account::config_dir_pin()` is the single source (non-default accounts
  only → `Some`, default → `None`), used by BOTH the local snapshot builder
  (`build_snapshot`) AND the remote daemon inventory (`collect_agent_sessions`) —
  the daemon path bypassed the stamping and would have wired `None`, caught by
  adversarial review.
- Proto field 15 `config_dir`, empty ⇔ `None` (older daemons still decode).
- `attach_fleet_session` passes the session's `config_dir` to
  `resume_command_pinned`, so the remote resume becomes
  `CODEX_HOME=<host-path> codex resume <id>` (path replayed verbatim in the
  daemon `startup_command`, never canonicalized locally). The local adopt path is
  unchanged (still resolves via `config_dir_for_session`).

Needs runtime verification on a real remote host (devhost). green:
`cargo check --bin zaplex --locked`; `cargo test -p remote_server` (74);
`cargo test -p zaplex_cockpit` (144; the 3 `/tmp/proj` failures are pre-existing
host `/tmp/.git` env pollution). codex + grok reviewed (grok found the daemon
bypass; fixed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ttered headers

Addresses the RC-DMG UI feedback:

- Favorite star: replace the two-star sparkle (`Icon::Stars`, read as an AI
  glyph) with the conventional single star — a new `Star`/`StarFilled` icon pair
  (stroked outline / filled SVG). Favorited = filled gold (`ui_yellow_color`),
  not-favorited = hollow outline muted, hover cross-hints. Conventional and
  legible.
- Tooltips on the icon-only affordances: the favorite star, ⋯ manage-host, the
  review (eye) verb, and the dashboard button now carry hover tooltips via a new
  `icon_verb_button_tooltip` helper (a hover-gated floating `Tooltip` overlay —
  respects the no-layout-shift rule). A bare clickable glyph without a label is
  no longer undiscoverable.
- Decluttered the sidebar zone-card headers (they overflowed the narrow rail):
  the AI-Accounts header is now `[N accounts] … [today $X] [⤢]` — the title
  flexes/truncates first so the number never clips, the week total moved to the
  card/pane (no repeat), and the dashboard pill shrank to a tooltip'd icon. The
  Hosts card title is a clean section label ("Hosts").

green: `cargo check --bin zaplex --locked`; i18n literal guard clean. codex +
grok reviewed (LGTM). Finer premium polish to iterate on the DMG.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
iret77 added 30 commits July 24, 2026 00:00
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