fix(em): flag/star dead-case-label bug + help discoverability#493
Merged
Conversation
…1+2) Per SPEC-em-ux-refactor-2026-07-07.md, from this session's ADHD-UX audit of em. P0 fix: em()'s dispatch case statement had "star|flag)" bound to _em_star in one section AND "flag|fl)" bound to _em_flag in another, earlier section. Since zsh case matches top-down, `em flag` always resolved to _em_flag (one-way add) and never reached _em_star's toggle logic -- the "flag" alias on the star arm was dead code. Fixed the routing so each command name maps to exactly one function; also removed a harmless duplicate `move|mv)` label. _em_star extended to accept multiple IDs (toggling each independently against one consistent folder snapshot) to match flag/unflag's existing batch capability. Added tests/test-em-flag-star.zsh: routing regression tests (flag/star/ unflag each hit a distinct function), multi-ID parity tests, and a grep-based dead-code guard that specifically detects the same case-label word bound to two different handlers (not just any repeated word -- verified against a false positive on legitimate multi-word aliases). Verified the guard actually catches this exact bug class via a planted- defect positive control (reintroduced the old duplicate label, confirmed the guard fails with the right message, restored the fix). Phase 2: added `em help <topic>` (inbox/compose/organize/manage/safety/ ai/search) so users aren't stuck scanning a ~90-line dump for one thing; no-arg `em help` output is unchanged. Documented the existing 3-tier confirmation system ([y/N/e] / type "yes" / type folder name) in the SAFETY section as an intentional design, not an incidental discovery. Updated MASTER-DISPATCHER-GUIDE.md and the man page to match, including fixing a duplicate `em move` reference row and a stale "em flag is an alias for em star" note that mirrored the same underlying bug. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This was referenced Jul 7, 2026
Merged
Data-Wise
added a commit
that referenced
this pull request
Jul 7, 2026
…dd em undo + recent-folders (Phase 3) (#497) em move <ID> <folder> was broken in production: _em_move and its adapter _em_hml_move were each defined twice in email-dispatcher.zsh/em-himalaya.zsh, and zsh's last-definition-wins semantics meant the two LIVE definitions were incompatible with each other — the live _em_move called _em_hml_move with the numeric message ID in the source-folder position. Every move would attempt to move a message from a folder named after its own ID. Same failure class as the flag/star case-duplicate bug fixed earlier this session (PR #493), this time a duplicate function definition rather than a duplicate case label. Caught by tests/test-em-move-restore.zsh, which was never wired into tests/run-all.sh (orphaned, like test-em-ai-switch.zsh was) — it now fails 3/8 -> passes 8/8 against the fixed source and is registered. Kept the multi-ID interface (em move <FOLDER> <ID>...) since it matches em move --help, MASTER-DISPATCHER-GUIDE.md, and the orphaned test file. Corrected the same stale <ID>-first interface across QUICK-REFERENCE.md, MASTER-DISPATCHER-GUIDE.md, REFCARD-EMAIL-DISPATCHER.md (which had both a stale and a correct em move row), EMAIL-DISPATCHER-GUIDE.md, EMAIL-COOKBOOK.md, and man/man1/em.1 — plus a leftover "em flag = alias for em star" line the Phase 1+2 docs sweep missed. Phase 3 (docs/specs/SPEC-em-ux-refactor-2026-07-07.md): - em undo: single-step undo of the last star/flag/unflag/move (1hr window, no stack), built on lib/em-cache.zsh's existing get/set API - em move --recent <ID>...: quick-pick target folder from last 3 destinations, no fzf required - Centralized ALIASES section in em help (single source of truth instead of scattered per-command mentions) Tests: tests/test-em-undo.zsh (16 new tests), tests/test-em-move-restore.zsh (8/8, newly registered), tests/test-em-help-guards.zsh (undo help coverage). Full suite: 80 passed, 0 failed, 1 skipped. mkdocs build --strict clean. Man-page guard: 12/12. Claude-Session: https://claude.ai/code/session_01JnVugoVjTHRK41krTTMi8L Co-authored-by: Test User <test@example.com> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements Phase 1+2 of
docs/specs/SPEC-em-ux-refactor-2026-07-07.md, from this session's ADHD-UX audit ofem.P0 fix — dead-code bug:
em()'s dispatchcasestatement hadstar|flag)bound to_em_starin the ORGANIZE section ANDflag|fl)bound to_em_flagearlier in the MANAGE section. Since zshcasematches top-down,em flagalways resolved to_em_flag(one-way add) and never reached_em_star's toggle logic — theflagalias on thestararm was unreachable dead code. Fixed so each command name maps to exactly one function; also removed a harmless duplicatemove|mv)label._em_starextended to accept multiple IDs (toggling each independently against one consistent folder snapshot) to matchflag/unflag's existing batch capability.Phase 2 — discoverability: added
em help <topic>(inbox/compose/organize/manage/safety/ai/search) so users aren't stuck scanning a ~90-line dump for one thing; no-argem helpoutput is unchanged. Documented the existing 3-tier confirmation system ([y/N/e]/ type"yes"/ type folder name) in the SAFETY section as an intentional design. UpdatedMASTER-DISPATCHER-GUIDE.mdand the man page, including fixing a duplicateem movereference row and a stale "em flagis an alias forem star" note that mirrored the same underlying bug.Test plan
tests/test-em-flag-star.zsh— 6/6 pass: routing regression (flag/star/unflag each hit a distinct function), multi-ID parity, and a grep-based dead-code guard.word 'flag' bound to both '_em_flag' and '_em_star', restored the fix, confirmed 6/6 green again. (Note: the routing tests alone do NOT catch this bug — zsh's top-down case matching meansem flagbehaves identically whether or not the duplicate label is present. Only the dead-code guard specifically detects it, which is why it's its own dedicated test.)em flag 42andem star 42 43route to distinct mocked functions with correct args;em help organize,em help safety,em help badtopic(error path) all verified live../tests/run-all.sh— 78 passed, 0 failed, 0 timeout, 1 skipped (expected —e2e-em-dispatcherskips when the external tool is absent, same baseline as before this PR, +1 for the new suite).mkdocs build --strict— clean, run twice (before and after the man-page/CHANGELOG pass).tests/test-manpage-version-sync.zsh— 12/12 clean.🤖 Generated with Claude Code