|
| 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`. |
0 commit comments