Skip to content

Commit 3c1a002

Browse files
echobtcursoragent
authored andcommitted
docs(audit): cortex cli 100% tui+mcp audit and lock board index
Co-authored-by: Mathis <echobt@users.noreply.github.com>
1 parent 3035361 commit 3c1a002

3 files changed

Lines changed: 710 additions & 0 deletions

File tree

design/cli-lock-board-index.md

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
# Cortex CLI — lock board index (state → source → test → verifier tool)
2+
3+
Companion to [`docs/audits/CORTEX_CLI_100_AUDIT_2026-09-08.md`](../docs/audits/CORTEX_CLI_100_AUDIT_2026-09-08.md).
4+
Generated from the id lists in the tree at `3035361` (`v0.1.10`):
5+
`lock_scene_ids()` in `src/cortex-tui/src/lock_proof.rs:53-131`,
6+
`is_lock_board()` in `src/cortex-tui/src/lock_boards.rs:44-99`,
7+
`LOCK_V2_WIDE_IDS` / `LOCK_V2_NARROW_IDS` in `src/cortex-tui/src/lock_v2.rs:33-147`.
8+
9+
Current Designer lock: **v2** (77 wide / 31 narrow), green focus `#1F4945`.
10+
The committed PNGs of every pack are still the historical violet render
11+
(see audit §1); the ids and tests below are the truth the verifier reads.
12+
13+
Verifier tool names are the ones specified in audit §6 (`lock.render`,
14+
`lock.palette_audit`, `lock.diff_txt`, `tui.*`, `login.run`, `api.*`,
15+
`mcp.*`). "Flow" refers to audit §8.
16+
17+
## Cross-pack tests (run over every id at 40×12 and 120×40)
18+
19+
| Test (`cargo test -p cortex-tui`) | Pack | What it proves |
20+
|---|---|---|
21+
| `lock_proof::tests::banner_green_is_reserved_for_selection_and_focused_composer` | v1 | accent `#1F4945` only on focus glyphs, always on a `#F5F5F5` backing |
22+
| `lock_proof::tests::selection_rows_are_banner_green_on_the_selection_bar_never_inverted` | v1 | no accent background; selection bar `#262626` |
23+
| `lock_proof::tests::green_is_reserved_for_checks_and_diff_additions` | v1 | `#4ADE80` only on `` / `+` |
24+
| `lock_proof::tests::every_edit_plus_count_is_green` | v1 | `+N` on Edit/Write/commit rows is diff green |
25+
| `lock_proof::tests::red_and_amber_stay_on_diagnostics` | v1 | red/amber only on error scenes / diff deletions |
26+
| `lock_proof::tests::banned_colors_never_painted` | v1 | mint/navy/brand-green banned — **still permits `#221A38`** (audit P0-3) |
27+
| `lock_proof::tests::composer_is_framed_by_hairlines_in_every_session_state` | v1 | composer `>` accent + block cursor in every composer scene |
28+
| `lock_proof::tests::distinct_states_render_distinct_frames` | v1 | only the 4 documented aliases share a frame |
29+
| `lock_proof::tests::no_smashed_tokens_anywhere` | v1 | wrapped copy never breaks tokens |
30+
| `lock_proof::tests::no_rounded_frame_glyphs_anywhere` | v1 | **asserts nothing** (audit P0-3) |
31+
| `lock_v2::tests::lock_v2_wide_count_is_spec` | v2 | 77 / 31 ids |
32+
| `lock_v2::tests::lock_v2_wide_frames_are_unique`, `lock_v2_narrow_frames_are_unique` | v2 | every id is a distinct frame |
33+
| `lock_v2::tests::slash_hover_is_not_banner_green_wash` | v2 | hover `#1A1A1A`; `#221A38` banned |
34+
| `style::tests::gray_chrome_palette_is_locked` (`cortex-core`) | palette | `ACCENT == #1F4945`, grays neutral, mint/cyan banned, gold retired |
35+
| `style::tests::banner_accent_has_accessible_focus_contrast` (`cortex-core`) | palette | contrast ≥ 4.5 on the focus backing |
36+
37+
Verifier equivalent: `lock.palette_audit{pack, width, height}`.
38+
39+
## Lock v1 — 72 ids (`docs/media/tui-lock/`)
40+
41+
Kinds: **painted** = `lock_boards.rs` painter (not the runtime view);
42+
**alias** = same painted board under a second id; **live** = real widget.
43+
44+
| Id | Kind | Specific test(s) | Verifier |
45+
|---|---|---|---|
46+
| `splash` | painted (`board_splash`) | `splash_has_session_chrome`, `empty_composer_blink_off_drops_the_block_and_keeps_placeholder_at_col0`, `splash_chrome::tests::*` | `lock.render v1 splash`; live equivalent = flow *Cold start* |
47+
| `typing` | painted | `lock_boards_02_09_product_copy` | `lock.render v1 typing`; live = `tui.type` |
48+
| `login_select` | live `LoginScreen` (option 2) | `login_is_a_numbered_picker_with_live_sub_states`, `runner::login_screen::tests::lock_select_option_moves_the_caret_and_bar` | `login.run{method:api_key}` |
49+
| `login_waiting` | live `LoginScreen` | `login_is_a_numbered_picker_with_live_sub_states`, `snapshot_auth_waiting_and_error` | `login.run{fixture:ok}` step 2 |
50+
| `login_success` | live `LoginScreen` | `login_success_check_is_the_only_green`, `snapshot_auth_success_and_failed` | `login.run{fixture:ok}` step 3 |
51+
| `login_error` | live `LoginScreen` (fed the product string) | `snapshot_auth_success_and_failed` | `login.run{fixture:unreachable}` — must produce the string from the real code path (audit P1-1) |
52+
| `palette` | painted (`board_palette`) | `slash_palette_rows_are_middot_or_banner_green_caret`, `palette_home_leads_with_lock_order` | `lock.render v1 palette`; live = flow *Slash* |
53+
| `palette_empty` | live `MinimalSessionView` | `live_states_keep_chrome_complete` | `tui.type "/zzzz"` |
54+
| `model_compact` | painted | `lock_boards_02_09_product_copy` | flow *Model* |
55+
| `model_full` | painted | `model_full_is_the_full_picker_at_every_size`, `search_fields_are_framed_by_hairlines_without_a_pricing_bar` | flow *Model* |
56+
| `mode` | painted | `pickers_are_numbered_with_dim_descriptions` | flow *Modes* |
57+
| `permissions` | painted | `pickers_are_numbered_with_dim_descriptions` | `tui.type "/permissions"` |
58+
| `working` | painted | `session_stays_interactive_while_running` | flow *Session run* |
59+
| `read` | painted | `tool_tile_dots_are_white`, `tool_tiles_one_card` | flow *Session run* |
60+
| `settings_hub` | painted | `settings_hub_is_lock_rows` | `tui.key F2` |
61+
| `settings_empty` | live `MinimalSessionView` | `live_states_keep_chrome_complete` | `tui.key F2``/``zzzz` |
62+
| `tool_tiles` | alias → `grep` | `tool_tiles_one_card` ||
63+
| `diagnostics` | painted | `diagnostics_severity_words_carry_the_only_color` | flow *Errors* |
64+
| `multi_diff` | painted | `lock_boards_11_20_product_copy` | `tui.type "/diff"` |
65+
| `compact` | alias → `compacted` | `compact_interrupt_clear_and_states_reflow` ||
66+
| `interrupt` | alias → `stopped` | `compact_interrupt_clear_and_states_reflow` ||
67+
| `clear` | alias → `clear_confirm` | `compact_interrupt_clear_and_states_reflow` ||
68+
| `session_empty` | live `MinimalSessionView` | `live_states_keep_chrome_complete`, `splash_has_session_chrome` (≠ splash) | `tui.start{resumed:true}` |
69+
| `session_loading` | live `MinimalSessionView` | `live_states_keep_chrome_complete` | flow *Session run* (first frame) |
70+
| `session_error` | live `MinimalSessionView` | `live_states_keep_chrome_complete` | flow *Errors* (503) |
71+
| `session_success` | live `MinimalSessionView` | `live_states_keep_chrome_complete`, `completed_turns_do_not_get_a_fake_check` | flow *Session run* (done) |
72+
| `shell` | painted | `green_is_reserved_for_checks_and_diff_additions` | flow *Session run* |
73+
| `permission` | painted | `pickers_are_numbered_with_dim_descriptions` | flow *Permission* — runtime widget differs (audit P1-2) |
74+
| `plan` | painted | `pickers_are_numbered_with_dim_descriptions` | `tui.key Shift+Tab` → plan → confirm |
75+
| `streaming` | painted | `lock_boards_21_30_product_copy` | flow *Session run* |
76+
| `resume` | painted | `search_fields_are_framed_by_hairlines_without_a_pricing_bar` | `tui.type "/resume"` |
77+
| `mcp` | painted | `green_is_reserved_for_checks_and_diff_additions` | flow *MCP* |
78+
| `usage` | painted | `lock_boards_21_30_product_copy` | `tui.type "/usage"` |
79+
| `quota` | painted | `red_and_amber_stay_on_diagnostics` | flow *Errors* (429) |
80+
| `sandbox` | painted | `green_is_reserved_for_checks_and_diff_additions` | `tui.type "/sandbox"` |
81+
| `cloud` | painted | `lock_boards_31_40_product_copy` | `tui.type "& …"` |
82+
| `sudo` | painted | `lock_boards_31_40_product_copy` | fixture: elevated Shell |
83+
| `ask` | painted (`┌ Ask — read-only ┐` chip, v1 chrome) | `mode_chips_are_kept` | flow *Modes* — runtime chip is `Ask · read-only` (audit §2.3) |
84+
| `files` | painted | `pickers_are_numbered_with_dim_descriptions` | `tui.type "@"` |
85+
| `queue` | painted (footer says `ctrl+x clear queue`, stale) | `every_edit_plus_count_is_green` | flow *Session run* (queue) |
86+
| `jobs` | painted | `green_is_reserved_for_checks_and_diff_additions` | `tui.type "/jobs"` |
87+
| `help` | painted | `lock_boards_41_50_product_copy` | `tui.type "/help"` |
88+
| `first_run` | painted | `first_run_tips_sit_on_the_charcoal_panel` | `tui.start{first_run:true}` |
89+
| `bash` | painted (`┌ Bash mode ┐` chip) | `mode_chips_are_kept` | `tui.type "!"` |
90+
| `config` | painted | `pickers_are_numbered_with_dim_descriptions` | `tui.type "/config"` |
91+
| `footer_max` | painted | `every_edit_plus_count_is_green`, `footer_is_model_left_hint_right_and_gray` | flow *Errors* (429 → MAX) |
92+
| `login` | live `LoginScreen` (option 1) | `login_is_a_numbered_picker_with_live_sub_states`, `snapshot_auth_select_method`, `snapshot_auth_narrow_and_wide` | `login.run` step 1 |
93+
| `thinking` | painted (dim metadata; PNG still gold) | `lock_boards_41_50_product_copy` | flow *Session run* |
94+
| `todos` | painted | `green_is_reserved_for_checks_and_diff_additions` | subagent fixture |
95+
| `question` | painted | `pickers_are_numbered_with_dim_descriptions` | question-tool fixture |
96+
| `skills` | painted | `search_fields_are_framed_by_hairlines_without_a_pricing_bar` | `tui.type "/skills"` |
97+
| `btw` | painted | `lock_boards_41_50_product_copy` | `tui.type "/btw …"` while running |
98+
| `stopped` | painted | `compact_interrupt_clear_and_states_reflow`, `red_and_amber_stay_on_diagnostics` | flow *Cancel* |
99+
| `compacted` | painted | `compact_interrupt_clear_and_states_reflow` | `tui.type "/compact"` |
100+
| `write` | painted | `every_edit_plus_count_is_green` | flow *Session run* |
101+
| `clear_confirm` | painted | `compact_interrupt_clear_and_states_reflow` | `tui.type "/clear"` |
102+
| `grep` | painted | `tool_tiles_one_card` | flow *Session run* |
103+
| `glob` | painted | `lock_boards_41_50_product_copy` | flow *Session run* |
104+
| `delete` | painted | `pickers_are_numbered_with_dim_descriptions` | `tui.type "/delete"` |
105+
| `list` | painted | `lock_boards_41_50_product_copy` | flow *Session run* |
106+
| `fetch` | painted | `lock_boards_41_50_product_copy` | flow *Session run* |
107+
| `mcp_call` | painted (plus-ASCII table) | `mcp_call_issue_list_is_a_plus_ascii_table` | flow *MCP* (`mcp.call`) |
108+
| `task` | painted | `green_is_reserved_for_checks_and_diff_additions` | subagent fixture |
109+
| `edit` | painted | `every_edit_plus_count_is_green` | flow *Session run* |
110+
| `md_table` | live `MinimalSessionView` | `md_table_is_a_gray_plus_ascii_grid` | fixture reply with a table |
111+
| `md_fence` | live `MinimalSessionView` | `md_fence_has_lang_tag_line_numbers_and_hairlines` | fixture reply with a fence |
112+
| `md_list` | live `MinimalSessionView` | `md_list_nests_bullets_and_checks_tasks` | fixture reply with lists |
113+
| `md_mixed` | live `MinimalSessionView` | `md_mixed_is_the_auto_format_proof` | fixture reply mixed |
114+
| `diff_hunk` | live `MinimalSessionView` | `diff_hunk_has_gutter_context_deletions_and_additions` | Edit tool fixture |
115+
| `diff_word` | live `MinimalSessionView` | `diff_word_tints_only_the_mutated_token` | Edit tool fixture |
116+
| `sandbox_deny` | painted | `red_and_amber_stay_on_diagnostics` | flow *Permission* (deny) |
117+
| `mcp_drop` | painted | `red_and_amber_stay_on_diagnostics`; runtime path: `runner::event_loop::tests::mcp_disconnect_without_user_stop_is_a_drop` | flow *MCP* (kill peer) |
118+
119+
## Lock v2 — 77 ids (`docs/media/tui-lock-v2/`), 31 also at 40×12
120+
121+
Kinds: **real** = production view/builder with a real `AppState`;
122+
**seed** = real view but the runtime-emitted line is inserted as
123+
`Message::system`; **synthetic** = `radios()` stand-in (audit P1-2 turns these
124+
into production state); **login** = `LoginScreen::lock_*`.
125+
126+
Every v2 id is covered by `lock_v2_wide_frames_are_unique` (and
127+
`lock_v2_narrow_frames_are_unique` when narrow = yes) and by
128+
`lock.diff_txt` against `docs/media/tui-lock-v2/txt/<size>/<id>.txt`.
129+
130+
| Id | Narrow | Kind | Specific test | Verifier / flow |
131+
|---|---|---|---|---|
132+
| `welcome-cortex` | yes | real | `welcome_paints_inky_and_token_counter`, `reported_collisions_are_distinct` | flow *Cold start* |
133+
| `welcome-agent` | yes | real | `agent_welcome_copy` | flow *Agent entry* |
134+
| `first-run-tips` | yes | real | `first_run_tips_are_visible` | `tui.start{first_run:true}` |
135+
| `session-empty` | yes | real | uniqueness | `tui.start{resumed:true}` |
136+
| `session-user-bars` | yes | real | `reported_collisions_are_distinct` | flow *Session run* |
137+
| `session-thought` || real | `user_bars_and_thought_metadata` | flow *Session run* |
138+
| `session-thought-expanded` || real | uniqueness | `tui.key F2` → Show thinking blocks |
139+
| `session-thinking-live` | yes | real | uniqueness | flow *Session run* (live) |
140+
| `session-assistant` | yes | real | `reported_collisions_are_distinct` | flow *Session run* |
141+
| `session-worked` || real | uniqueness | flow *Session run* (done) |
142+
| `session-optin` | yes | real | uniqueness | banner fixture (SPEC F5 pending) |
143+
| `session-optin-hover` || real | uniqueness | mouse fixture |
144+
| `composer-empty` | yes | real | `reported_collisions_are_distinct` | flow *Cold start* |
145+
| `composer-typing` | yes | real | uniqueness | `tui.type` |
146+
| `composer-typing-blink` || real | uniqueness | `tui.state.composer.caret_visible=false` |
147+
| `composer-hover` | yes | real | uniqueness | mouse fixture |
148+
| `composer-multiline` || real | uniqueness | `tui.key Alt+Enter` |
149+
| `footer-shortcuts` || real | `reported_collisions_are_distinct` | `tui.type` (footer strip) |
150+
| `footer-hover` || real | uniqueness | mouse fixture |
151+
| `tokens-topright` | yes | real | uniqueness | `api.turn` usage event |
152+
| `tokens-topright-warn` || real | uniqueness | fixture usage ≥ 90 % |
153+
| `compact-chat` | yes | real | uniqueness | `tui.type "/compact"` |
154+
| `slash-palette` | yes | real | `slash_hover_is_not_banner_green_wash` | flow *Slash* |
155+
| `slash-model-typed` | yes | real | uniqueness | flow *Slash* (`/mod`) |
156+
| `model-list` | yes | real (`build_model_selector`) | uniqueness | flow *Model* + `api.models` |
157+
| `model-list-hover` || real | uniqueness | mouse fixture |
158+
| `model-effort-high` | yes | real | `effort_order_is_high_medium_low` | flow *Model* (Tab) |
159+
| `model-effort-medium` || real | uniqueness | flow *Model* |
160+
| `model-effort-low` || real | uniqueness | flow *Model* |
161+
| `model-effort-hover` || real | uniqueness | mouse fixture |
162+
| `settings-appearance` | yes | real (`SettingsModalState`) | `settings_modal_has_appearance_and_search` | flow *Settings* |
163+
| `settings-mouse` | yes | real | uniqueness | flow *Settings* |
164+
| `settings-row-hover` | yes | real | `reported_collisions_are_distinct` | mouse fixture |
165+
| `settings-search` || real | uniqueness | flow *Settings* (`/ scro`) |
166+
| `settings-theme-submenu` | yes | real | uniqueness | flow *Settings* |
167+
| `mode-agent` || real | uniqueness | flow *Modes* |
168+
| `mode-plan` | yes | real | uniqueness | flow *Modes* |
169+
| `mode-ask` | yes | real | uniqueness | flow *Modes* |
170+
| `mode-bash` || real | uniqueness | `tui.type "!"` |
171+
| `permission-prompt` | yes | **synthetic** | uniqueness | flow *Permission* — must come from a real approval request (P1-2) |
172+
| `permission-prompt-hover` || **synthetic** | uniqueness | flow *Permission* + mouse |
173+
| `permissions-picker` || **synthetic** | uniqueness | `tui.type "/permissions"` (real builder) |
174+
| `mcp-servers` | yes | real (`build_mcp_selector`) | uniqueness | flow *MCP* (`mcp.probe`) |
175+
| `mcp-drop` || seed | runtime path `mcp_disconnect_without_user_stop_is_a_drop` | flow *MCP* (kill peer) |
176+
| `plugins` || **synthetic** | uniqueness | `tui.type "/plugins"` (real executor) |
177+
| `usage` | yes | **synthetic** | uniqueness | `tui.type "/usage"` (real `billing:usage` path) |
178+
| `quota-exhausted` || seed | runtime path `streaming.rs:514-523` | flow *Errors* (429) |
179+
| `sandbox` || **synthetic** | uniqueness | `tui.type "/sandbox"` (`build_sandbox_selector`) |
180+
| `sandbox-deny` || **synthetic** | uniqueness | flow *Permission* (deny) via `CortexError::SandboxDenied` |
181+
| `cloud-handoff` || seed | uniqueness | `tui.type "& …"` |
182+
| `diagnostics` | yes | seed | uniqueness | flow *Errors* (diagnostics tool) |
183+
| `interrupt-stopped` | yes | seed | runtime path `interrupt_records_stopped_once` | flow *Cancel* |
184+
| `error-unavailable` || real | uniqueness | flow *Errors* (503) |
185+
| `tool-tiles` || real | uniqueness | flow *Session run* (Group tool calls on) |
186+
| `tool-tiles-collapsed` || real | uniqueness | flow *Session run* |
187+
| `shell-running` || real | uniqueness | flow *Session run* (live Shell) |
188+
| `diff-hunk` | yes | real | uniqueness | Edit tool fixture |
189+
| `edit-collapsed` || real | uniqueness | `tui.key F2` → Collapsed edit blocks |
190+
| `md-table` || real | uniqueness | fixture reply with a table |
191+
| `code-fence` || real | uniqueness | fixture reply with a fence |
192+
| `login` | yes | login | `runner::login_screen::tests::*` | `login.run` step 1 |
193+
| `login-waiting` || login | `snapshot_auth_waiting_and_error` | `login.run{fixture:ok}` step 2 |
194+
| `login-success` || login | `login_success_check_is_the_only_green` | `login.run{fixture:ok}` step 3 |
195+
| `login-error` || login (fed product string) | `snapshot_auth_success_and_failed` | `login.run{fixture:unreachable}` (P1-1) |
196+
| `shortcuts-overlay` | yes | real | uniqueness | `tui.key Ctrl+x` |
197+
| `resume-picker` || real (`build_resume_picker`) | uniqueness | `tui.type "/resume"` |
198+
| `clear-confirm` || **synthetic** | uniqueness | `tui.type "/clear"` (real confirm) |
199+
| `plan-confirm` || **synthetic** | uniqueness | Plan → `Implement this plan?` (real) |
200+
| `queue` || real | uniqueness | flow *Session run* (Enter while running) |
201+
| `files-picker` || **synthetic** | uniqueness | `tui.type "@"` (real mention picker) |
202+
| `jobs` || **synthetic** | uniqueness | `tui.type "/jobs"` |
203+
| `skills` || real (`build_skills_selector`) | uniqueness | `tui.type "/skills"` |
204+
| `todos` || real (`SubagentTaskDisplay`) | uniqueness | subagent fixture |
205+
| `question` || **synthetic** | uniqueness | question-tool fixture (`QuestionPromptView`) |
206+
| `sudo` || **synthetic** | uniqueness | elevated Shell fixture |
207+
| `config-tree` || **synthetic** | uniqueness | `tui.type "/config"` |
208+
| `btw` || real | uniqueness | `tui.type "/btw …"` while running |
209+
210+
## Counts
211+
212+
| Pack | Ids | Sizes | Frames | Live / real | Painted or synthetic | PNGs in repo (all violet) |
213+
|---|---|---|---|---|---|---|
214+
| v1 | 72 | 40×12, 120×40 | 144 (+144 macOS composites) | 17 | 51 painted + 4 aliases | 65/72 files carry `#A78BFA` at each size |
215+
| v2 | 77 wide / 31 narrow | 120×40 / 40×12 | 108 | 63 (5 seeded) | 14 synthetic | runtime 73/77 + 30/31; designer boards 68/77 + 29/31 |
216+
217+
Regeneration commands (after audit P0-3 lands): `./scripts/render-tui-lock.sh`,
218+
`./scripts/render-tui-lock-v2.sh`, `python3 docs/media/tui-lock-v2/tools/render_lock_v2.py --index`.

docs/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ New here? Start with **[Getting started](guides/getting-started.md)**, then keep
6767
| [Local operations](guides/operations.md) | Alerts, error investigation, deployment comparison and profiling |
6868
| [Maintenance](guides/maintenance.md) | Ownership, labels, backlog triage and release review |
6969
| [Readiness remediation](guides/readiness-remediation.md) | Local validation snapshot and explicit remaining limits |
70+
| [CLI 100 % audit (2026-09-08)](audits/CORTEX_CLI_100_AUDIT_2026-09-08.md) | TUI + MCP audit against the product and Designer locks: gaps with evidence, verifier MCP spec, ordered fix PRs |
7071

7172
## Conventions used here
7273

0 commit comments

Comments
 (0)