| 1 | # Layer 5.1: User Command Registry And Loading Boundary — Evidence Summary |
| 2 | |
| 3 | **EPIC-002**: Staged command-boundary refactor (Hmbown/CodeWhale#2870) |
| 4 | |
| 5 | **FEAT-010**: Layer 5.1 — User Command Registry And Loading Boundary |
| 6 | |
| 7 | **Status**: ✅ Verified on production/test commit |
| 8 | |
| 9 | **Date**: 2026-07-21 |
| 10 | |
| 11 | ## Provenance And Correction |
| 12 | |
| 13 | Paulo Aboim Pinto's exact evidence commit from PR #4046, |
| 14 | `75e08e5c67f555b5cda8511742c824bb74bb6c1d`, remains in this integration's |
| 15 | ancestry. That document correctly identified the dedicated registry boundary, |
| 16 | hidden-command behavior, and runtime `allowed-tools` propagation, but its claim |
| 17 | that the written Layer 5.1 contract was already complete was too broad. |
| 18 | |
| 19 | Paulo's follow-up audit on #2870 identified the missing `name`, `usage`, and |
| 20 | `arguments` frontmatter fields and the missing explicit proof that a malformed |
| 21 | file does not block a valid sibling. The production-and-test follow-up |
| 22 | `2717843394050ff1b4f651f931e3894432ace8f8` implements and verifies that written |
| 23 | contract. This revision corrects the claim while preserving the original commit |
| 24 | and authorship as the provenance record. |
| 25 | |
| 26 | ## Acceptance Criteria Verification |
| 27 | |
| 28 | | Criterion | Status | Evidence | |
| 29 | |-----------|--------|----------| |
| 30 | | User commands load through a dedicated boundary separate from built-ins | Implemented | `commands::execute()` calls `user_registry::try_dispatch()` before the built-in registry; `UserCommandRegistry` owns user metadata and errors. | |
| 31 | | Parse `name`, `description`, `usage`, `arguments`, `hidden`, and `allowed-tools` | Implemented | `registry_loads_markdown_metadata`, `frontmatter_name_replaces_filename_canonical_name`, and `parser_preserves_layer_5_1_frontmatter_fields`. | |
| 32 | | Invalid frontmatter is recoverable per file and does not block valid commands | Implemented | `malformed_file_is_recoverable_and_valid_sibling_still_dispatches`; malformed losing duplicates are isolated by `malformed_losing_name_override_does_not_poison_valid_winner`. | |
| 33 | | Hidden commands dispatch directly but are filtered from palette and slash completion | Implemented | `hidden_user_commands_still_dispatch_directly`, `hidden_frontmatter_name_override_suppresses_shadowed_builtin`, and `hidden_name_override_filters_shadowed_builtin_from_slash_completion`. | |
| 34 | | `allowed-tools` reaches runtime dispatch, including explicit-empty deny-all | Implemented | `dispatch_uses_frontmatter_name_arguments_and_allowed_tools` and `empty_allowed_tools_frontmatter_blocks_all_tools`. | |
| 35 | | Reload reflects command-file changes | Implemented | `registry_reloads_when_existing_command_file_changes`. | |
| 36 | | Name, alias, palette, completion, and dispatch override behavior is deterministic | Implemented | Frontmatter-name, directory-precedence, canonical/alias collision, palette, completion, and dispatch tests in `user_registry.rs`, `command_palette.rs`, `widgets/mod.rs`, and `ui/tests.rs`. | |
| 37 | |
| 38 | ## Final Contract |
| 39 | |
| 40 | - The normalized filename is the default canonical command name. |
| 41 | - A valid frontmatter `name` replaces the filename default. The filename is not |
| 42 | an implicit alias; retain it explicitly with `alias` or `aliases` when needed. |
| 43 | - Directory precedence is resolved first. Within a directory, normalized |
| 44 | filenames are ordered. Distinct files that resolve to the same canonical |
| 45 | name use first-wins order and record a recoverable error for each loser. |
| 46 | - An alias cannot replace any canonical user-command name. Duplicate aliases |
| 47 | also use first-wins order. |
| 48 | - A malformed winning command reports its error on direct dispatch and never |
| 49 | falls through to a built-in. A malformed losing duplicate cannot poison a |
| 50 | valid winner, and malformed siblings cannot block valid commands. |
| 51 | - Palette and completion presentation use non-empty `usage`, then legacy |
| 52 | `argument-hint`, then `arguments`. These are presentation/input hints, not |
| 53 | runtime validation. |
| 54 | - Existing template behavior is unchanged: `$ARGUMENTS` receives the complete |
| 55 | argument tail and `$1`, `$2`, and later positionals use whitespace splitting. |
| 56 | - Hidden commands still shadow built-ins and dispatch directly, but do not |
| 57 | appear in palette or slash completion. |
| 58 | - `allowed-tools` continues to normalize tool names into runtime state; an |
| 59 | explicitly empty value remains `Some(Vec::new())`, blocking every tool. |
| 60 | |
| 61 | The public version of this contract is recorded in |
| 62 | `docs/architecture/command-dispatch.md`. |
| 63 | |
| 64 | ## Verification Receipts |
| 65 | |
| 66 | These commands ran serially against the shared target with incremental |
| 67 | compilation disabled and one build job. Every focused test command emitted the |
| 68 | same macOS linker warning that `__eh_frame` exceeded the compact-unwind table's |
| 69 | 16 MB encoding limit; the warning did not fail linking or any test. |
| 70 | |
| 71 | | Command | Result | |
| 72 | |---------|--------| |
| 73 | | `CARGO_TARGET_DIR=/Volumes/VIXinSSD/CW/codewhale/target CARGO_INCREMENTAL=0 CARGO_BUILD_JOBS=1 cargo test -p codewhale-tui --bin codewhale-tui --locked user_registry --jobs 1 -- --test-threads=1` | ✅ PASS — 25 passed, 0 failed, 7812 filtered out | |
| 74 | | `CARGO_TARGET_DIR=/Volumes/VIXinSSD/CW/codewhale/target CARGO_INCREMENTAL=0 CARGO_BUILD_JOBS=1 cargo test -p codewhale-tui --bin codewhale-tui --locked user_commands --jobs 1 -- --test-threads=1` | ✅ PASS — 25 passed, 0 failed, 7812 filtered out | |
| 75 | | `CARGO_TARGET_DIR=/Volumes/VIXinSSD/CW/codewhale/target CARGO_INCREMENTAL=0 CARGO_BUILD_JOBS=1 cargo test -p codewhale-tui --bin codewhale-tui --locked command_palette --jobs 1 -- --test-threads=1` | ✅ PASS — 27 passed, 0 failed, 7810 filtered out | |
| 76 | | `CARGO_TARGET_DIR=/Volumes/VIXinSSD/CW/codewhale/target CARGO_INCREMENTAL=0 CARGO_BUILD_JOBS=1 cargo test -p codewhale-tui --bin codewhale-tui --locked slash_completion --jobs 1 -- --test-threads=1` | ✅ PASS — 22 passed, 0 failed, 7815 filtered out | |
| 77 | | `CARGO_TARGET_DIR=/Volumes/VIXinSSD/CW/codewhale/target CARGO_INCREMENTAL=0 CARGO_BUILD_JOBS=1 cargo test -p codewhale-tui --bin codewhale-tui --locked apply_slash_menu_selection --jobs 1 -- --test-threads=1` | ✅ PASS — 5 passed, 0 failed, 7832 filtered out | |
| 78 | | `CARGO_TARGET_DIR=/Volumes/VIXinSSD/CW/codewhale/target CARGO_INCREMENTAL=0 CARGO_BUILD_JOBS=1 cargo check -p codewhale-tui --bin codewhale-tui --locked --jobs 1` | ✅ PASS | |
| 79 | | `CARGO_TARGET_DIR=/Volumes/VIXinSSD/CW/codewhale/target CARGO_INCREMENTAL=0 CARGO_BUILD_JOBS=1 cargo fmt --all -- --check` | ✅ PASS | |
| 80 | | `git diff --check` | ✅ PASS | |
| 81 |