返回 CodeWhale
layer-5-1-user-command-registry-evidence.md
根目录 / docs / evidence / layer-5-1-user-command-registry-evidence.md
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
81 lines MARKDOWN