Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added docs/media/tui-lock-v2/120x40/offline.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/media/tui-lock-v2/120x40/rate-limit.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/media/tui-lock-v2/40x12/offline.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/media/tui-lock-v2/40x12/rate-limit.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions docs/media/tui-lock-v2/SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ categorised rows + tip/nav footer, slash autocomplete above the composer, effort
radios under `/model`, token counter top-right, footer shortcut strip) and
re-skinned to the Cortex chrome. **No runtime code changes ship with this pack.**

- Boards: [`index.md`](index.md) — 82 boards at 120×40, 36 of them also at 40×12 (118 PNGs).
- Boards: [`index.md`](index.md) — 84 boards at 120×40, 38 of them also at 40×12 (122 PNGs).
- Grids: `txt/<size>/<board>.txt` — the exact character grid of every board (diff a
`MockTerminal` capture against these).
- Renderer: `tools/render_lock_v2.py` + `tools/boards.py` (Python 3 + Pillow, IBM Plex Mono
Expand Down Expand Up @@ -414,7 +414,7 @@ Narrow: no bars, `used / total pct%`.
| settings-appearance / mouse / row-hover / search / theme-submenu | `settings-appearance`, `settings-mouse`, `settings-row-hover`, `settings-search`, `settings-theme-submenu` |
| mode chips (Shift+Tab) | `mode-agent`, `mode-plan`, `mode-ask`, `mode-bash` |
| permissions / mcp / plugins / usage-quota / sandbox / cloud | `permission-prompt`, `permission-prompt-hover`, `permissions-picker`, `mcp-servers`, `mcp-drop`, `plugins`, `usage`, `quota-exhausted`, `sandbox`, `sandbox-deny`, `cloud-handoff` |
| diagnostics red/amber · interrupt/stopped | `diagnostics`, `interrupt-stopped`, `error-unavailable` |
| diagnostics red/amber · interrupt/stopped | `diagnostics`, `interrupt-stopped`, `error-unavailable`, `offline`, `rate-limit` |
| markdown table · diff hunk · code fence | `md-table`, `diff-hunk`, `edit-collapsed`, `code-fence`, `tool-tiles`, `tool-tiles-collapsed`, `shell-running` |
| login / first-run | `login`, `login-waiting`, `login-success`, `login-error`, `first-run-tips` |
| compact chat (ref 5) | `compact-chat` |
Expand All @@ -425,7 +425,7 @@ Narrow (40×12) set: `welcome-cortex`, `welcome-agent`, `first-run-tips`, `sessi
`tokens-topright`, `compact-chat`, `slash-palette`, `goal-chip-active`, `goal-chip-paused`, `goal-chip-done`,
`goal-chip-budget`, `goal-chip-blocked`, `slash-model-typed`, `model-list`, `model-effort-high`,
`settings-appearance`, `settings-mouse`, `settings-row-hover`, `settings-theme-submenu`, `mode-plan`, `mode-ask`,
`permission-prompt`, `mcp-servers`, `usage`, `diagnostics`, `interrupt-stopped`, `diff-hunk`, `login`, `shortcuts-overlay`.
`permission-prompt`, `mcp-servers`, `usage`, `diagnostics`, `interrupt-stopped`, `offline`, `rate-limit`, `diff-hunk`, `login`, `shortcuts-overlay`.

---

Expand Down
4 changes: 3 additions & 1 deletion docs/media/tui-lock-v2/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ Regenerate: `python3 tools/render_lock_v2.py --index` (fetches IBM Plex Mono on
| `diagnostics` | Diagnostics tile — error red, warn amber | [120x40](120x40/diagnostics.png) | [40x12](40x12/diagnostics.png) |
| `interrupt-stopped` | Esc / Ctrl+c — `× Stopped` | [120x40](120x40/interrupt-stopped.png) | [40x12](40x12/interrupt-stopped.png) |
| `error-unavailable` | API down — product-facing error | [120x40](120x40/error-unavailable.png) | — |
| `offline` | Network unreachable — held composer, distinct from API-down | [120x40](120x40/offline.png) | [40x12](40x12/offline.png) |
| `rate-limit` | HTTP 429 rate limited — retry-after, distinct from quota | [120x40](120x40/rate-limit.png) | [40x12](40x12/rate-limit.png) |
| `tool-tiles` | Grouped tool calls expanded — Read / Grep / Shell | [120x40](120x40/tool-tiles.png) | — |
| `tool-tiles-collapsed` | Grouped tool calls collapsed | [120x40](120x40/tool-tiles-collapsed.png) | — |
| `shell-running` | Live Shell tile with output | [120x40](120x40/shell-running.png) | — |
Expand All @@ -113,4 +115,4 @@ Regenerate: `python3 tools/render_lock_v2.py --index` (fetches IBM Plex Mono on
| `config-tree` | `/config` read-only key tree | [120x40](120x40/config-tree.png) | — |
| `btw` | `/btw` side note during a running turn | [120x40](120x40/btw.png) | — |

**82** boards at 120x40 · **36** at 40x12 · 118 PNGs.
**84** boards at 120x40 · **38** at 40x12 · 122 PNGs.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions docs/media/tui-lock-v2/runtime/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ is banner green `#1F4945`; historical violet `#A78BFA` is not the lock.
Designer boards (pixel target) live in `docs/media/tui-lock-v2/{40x12,120x40}/`.
These runtime frames are what Designer cli signs off against.

SPEC §7: **82** boards at 120×40 and **36** at 40×12. Each filename is one
SPEC §7: **84** boards at 120×40 and **38** at 40×12. Each filename is one
distinct live state — no two PNGs share a sha256. Includes `/goal` composer
chips (`goal-chip-*`) and slash palette with `/goal` after `/plan`.
chips (`goal-chip-*`) plus distinct `offline` and `rate-limit` diagnostics.
34 changes: 34 additions & 0 deletions docs/media/tui-lock-v2/tools/boards.py
Original file line number Diff line number Diff line change
Expand Up @@ -1380,6 +1380,38 @@ def board_error_unavailable(s, c):
footer(s, c, [("Enter", "retry"), ("Ctrl+x", "shortcuts")])


def board_offline(s, c):
header(s, c)
hold = "Waiting for network" if c.narrow else "Waiting for network — your work is saved"
top = composer(s, c, placeholder=hold, focused=False, caret=False)
f = Flow(s, c, limit=top - 1)
f.user("keep going on this Cortex session", "03:18 PM")
f.line([("×", S_ERR), (" You're offline", S_ERR)])
body = (
"Reconnect — your work is saved."
if c.narrow
else "Reconnect when the network is back — your work is saved in this session."
)
f.dim(body, indent=2)
footer(s, c, [("Enter", "retry"), ("Ctrl+x", "shortcuts")])


def board_rate_limit(s, c):
header(s, c)
hold = "Held until the rate limit resets" if c.narrow else "Add a follow-up — held until the rate limit resets"
top = composer(s, c, placeholder=hold, focused=False, caret=False)
f = Flow(s, c, limit=top - 1)
f.user("send another follow-up on Cortex Mini 1", "03:22 PM")
f.line([("×", S_ERR), (" Rate limited", S_ERR)])
body = (
"Too many requests — try again in 2m."
if c.narrow
else "Too many requests — try again in 2m (Retry-After: 120s). Follow-ups stay held until the rate limit resets."
)
f.dim(body, indent=2)
footer(s, c, [("Enter", "retry"), ("/usage", "details")])


def board_tool_tiles(s, c):
header(s, c)
top = composer(s, c)
Expand Down Expand Up @@ -1856,6 +1888,8 @@ def board_btw(s, c):
("diagnostics", board_diagnostics, True, "E", "Diagnostics tile — error red, warn amber"),
("interrupt-stopped", board_interrupt_stopped, True, "E", "Esc / Ctrl+c — `× Stopped`"),
("error-unavailable", board_error_unavailable, False, "E", "API down — product-facing error"),
("offline", board_offline, True, "E", "Network unreachable — held composer, distinct from API-down"),
("rate-limit", board_rate_limit, True, "E", "HTTP 429 rate limited — retry-after, distinct from quota"),
("tool-tiles", board_tool_tiles, False, "E", "Grouped tool calls expanded — Read / Grep / Shell"),
("tool-tiles-collapsed", board_tool_tiles_collapsed, False, "E", "Grouped tool calls collapsed"),
("shell-running", board_shell_running, False, "E", "Live Shell tile with output"),
Expand Down
40 changes: 40 additions & 0 deletions docs/media/tui-lock-v2/txt/120x40/offline.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
14K / 500K

> keep going on this Cortex session 03:18 PM

× You're offline
Reconnect when the network is back — your work is saved in this session.





























╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ > Waiting for network — your work is saved │
╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯

Enter:retry | Ctrl+x:shortcuts
40 changes: 40 additions & 0 deletions docs/media/tui-lock-v2/txt/120x40/rate-limit.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
14K / 500K

> send another follow-up on Cortex Mini 1 03:22 PM

× Rate limited
Too many requests — try again in 2m (Retry-After: 120s). Follow-ups stay held until the rate limit resets.





























╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ > Add a follow-up — held until the rate limit resets │
╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯

Enter:retry | /usage:details
12 changes: 12 additions & 0 deletions docs/media/tui-lock-v2/txt/40x12/offline.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
14K / 500K

> keep going on this Cortex session

× You're offline
Reconnect — your work is saved.

╭─ Agent ────────────────────────────╮
│ > Waiting for network │
╰─────────── Cortex Mini 1 (medium) ─╯

Enter:retry | Ctrl+x:shortcuts
12 changes: 12 additions & 0 deletions docs/media/tui-lock-v2/txt/40x12/rate-limit.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
14K / 500K

> send another follow-up on Cortex…

× Rate limited
Too many requests — try again in…

╭─ Agent ────────────────────────────╮
│ > Held until the rate limit resets │
╰─────────── Cortex Mini 1 (medium) ─╯

Enter:retry | /usage:details
9 changes: 5 additions & 4 deletions scripts/render-tui-lock-v2.sh
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ for spec in 40x12 120x40; do
python3 scripts/ansi-frames-to-gif.py --frames "$frames" --png-only "$pngs"
done

unique_pngs "$output_dir/40x12" 36
unique_pngs "$output_dir/120x40" 82
unique_pngs "$output_dir/40x12" 38
unique_pngs "$output_dir/120x40" 84

python3 - "$output_dir" <<'PY'
from pathlib import Path
Expand Down Expand Up @@ -100,8 +100,9 @@ is banner green `#1F4945`; historical violet `#A78BFA` is not the lock.
Designer boards (pixel target) live in `docs/media/tui-lock-v2/{40x12,120x40}/`.
These runtime frames are what Designer cli signs off against.

SPEC §7: **82** boards at 120×40 and **36** at 40×12. Each filename is one
distinct live state — no two PNGs share a sha256.
SPEC §7: **84** boards at 120×40 and **38** at 40×12. Each filename is one
distinct live state — no two PNGs share a sha256. Includes `/goal` composer
chips (`goal-chip-*`) plus distinct `offline` and `rate-limit` diagnostics.
EOF

echo "Wrote runtime captures to $output_dir"
6 changes: 6 additions & 0 deletions src/cortex-tui/src/app/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,10 @@ pub struct AppState {
pub update_info: Option<cortex_update::UpdateInfo>,
/// Agent quota is exhausted — follow-ups stay in the composer until it resets.
pub quota_held: bool,
/// Network is unreachable — follow-ups stay in the composer until reconnect.
pub offline_held: bool,
/// HTTP 429 rate limit — follow-ups stay in the composer until Retry-After.
pub rate_limit_held: bool,
/// Launched via the `agent` binary / alias.
pub agent_entrypoint: bool,
/// Token counter used / window.
Expand Down Expand Up @@ -342,6 +346,8 @@ impl AppState {
update_status: UpdateStatus::default(),
update_info: None,
quota_held: false,
offline_held: false,
rate_limit_held: false,
agent_entrypoint: false,
tokens_used: 0,
context_window: 500_000,
Expand Down
1 change: 1 addition & 0 deletions src/cortex-tui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ pub mod lock_v2;
mod lock_v2_boards;
mod lock_v2_goal;
mod lock_v2_ids;
mod lock_v2_network;
mod lock_v2_scenes;
pub mod readme_hero;
pub mod readme_hero_boards;
Expand Down
4 changes: 2 additions & 2 deletions src/cortex-tui/src/lock_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,8 @@ mod tests {

#[test]
fn lock_v2_wide_count_is_spec() {
assert_eq!(LOCK_V2_WIDE_IDS.len(), 82);
assert_eq!(LOCK_V2_NARROW_IDS.len(), 36);
assert_eq!(LOCK_V2_WIDE_IDS.len(), 84);
assert_eq!(LOCK_V2_NARROW_IDS.len(), 38);
}

#[test]
Expand Down
2 changes: 2 additions & 0 deletions src/cortex-tui/src/lock_v2_boards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::interactive::builders::{
};
use crate::lock_v2::PRODUCT_ERROR;
use crate::lock_v2_goal::{apply_goal_chip_scene, show_goal_in_narrow_palette};
use crate::lock_v2_network::apply_offline_rate_limit_scene;
use crate::lock_v2_scenes::*;
use crate::modal::mcp_manager::{McpServerInfo, McpStatus};
use crate::session::SessionSummary;
Expand Down Expand Up @@ -806,6 +807,7 @@ Tell me what you'd like to do.",
Message::user("/btw keep the composer dual-hairline").with_timestamp("09:51 AM"),
);
}
id if apply_offline_rate_limit_scene(id, &mut state) => {}
id if apply_goal_chip_scene(id, &mut state) => {}
other => panic!("unknown lock v2 scene {other}"),
}
Expand Down
8 changes: 6 additions & 2 deletions src/cortex-tui/src/lock_v2_ids.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Lock v2 scene id lists. Split out of [`crate::lock_v2`] so adding `/goal`
//! boards does not grow that file past the source-policy line-count baseline.

/// Narrow (40×12) SPEC §7 set — 36 boards.
/// Narrow (40×12) SPEC §7 set — 38 boards.
pub const LOCK_V2_NARROW_IDS: &[&str] = &[
"welcome-cortex",
"welcome-agent",
Expand Down Expand Up @@ -36,12 +36,14 @@ pub const LOCK_V2_NARROW_IDS: &[&str] = &[
"usage",
"diagnostics",
"interrupt-stopped",
"offline",
"rate-limit",
"diff-hunk",
"login",
"shortcuts-overlay",
];

/// Wide (120×40) SPEC §7 set — 82 boards.
/// Wide (120×40) SPEC §7 set — 84 boards.
pub const LOCK_V2_WIDE_IDS: &[&str] = &[
"welcome-cortex",
"welcome-agent",
Expand Down Expand Up @@ -101,6 +103,8 @@ pub const LOCK_V2_WIDE_IDS: &[&str] = &[
"diagnostics",
"interrupt-stopped",
"error-unavailable",
"offline",
"rate-limit",
"tool-tiles",
"tool-tiles-collapsed",
"shell-running",
Expand Down
Loading