mulmoterminal 5.1.0 → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/common/agentTitle.ts +23 -0
  2. package/common/keymap.ts +28 -3
  3. package/dist/assets/{AllPackages-B1YCJRYB-CJ5MwIcw.js → AllPackages-B1YCJRYB-Byv5Y2l8.js} +1 -1
  4. package/dist/assets/{BaseConfiguration-B6s_tKOW-DCQzFOtA.js → BaseConfiguration-B6s_tKOW-D-gjoRXo.js} +1 -1
  5. package/dist/assets/{Element-BMI7Nj5w-OqxmP4DD.js → Element-BMI7Nj5w-pmadKN44.js} +1 -1
  6. package/dist/assets/{Entities-C8p_0jCn-lah_hpVy.js → Entities-C8p_0jCn-DOze-aLz.js} +1 -1
  7. package/dist/assets/{FunctionList-YWk54TCy-B8miBPbX.js → FunctionList-YWk54TCy-ChT_85FS.js} +1 -1
  8. package/dist/assets/{InputJax-C5dj-ntL-BTCbon6p.js → InputJax-C5dj-ntL-QDnGDgyA.js} +1 -1
  9. package/dist/assets/{MathItem-YJvQL-XJ-7r4PX5ZP.js → MathItem-YJvQL-XJ-C1WmSlqG.js} +1 -1
  10. package/dist/assets/{MmlFactory-DSoKkE7s-Ce7KrGXH.js → MmlFactory-DSoKkE7s-BSods9g3.js} +1 -1
  11. package/dist/assets/{Options-oARQeeuT-buJ7F9SM.js → Options-oARQeeuT-BezHG2DV.js} +1 -1
  12. package/dist/assets/{OutputJax-DfUZNNCu-CDHJwABC.js → OutputJax-DfUZNNCu-CiGZyFkj.js} +1 -1
  13. package/dist/assets/{PrioritizedList-6lun1Xqd-C-DILou5.js → PrioritizedList-6lun1Xqd-1YFOP2UD.js} +1 -1
  14. package/dist/assets/{Styles-5NmwS-3M-C_HoV7lD.js → Styles-5NmwS-3M-CckuzfVu.js} +1 -1
  15. package/dist/assets/{TeXAtom-B5ni9myz-d1ASA31g.js → TeXAtom-B5ni9myz-czpsshhI.js} +1 -1
  16. package/dist/assets/{abnfDiagram-VCTEODGH-BGhi-oVb-BpKjoem1.js → abnfDiagram-VCTEODGH-BGhi-oVb-CxSD522K.js} +1 -1
  17. package/dist/assets/{arc-CK5ru50N-CUQm4Xup.js → arc-CK5ru50N-DKCl2r1T.js} +1 -1
  18. package/dist/assets/architecture-7GRP2DOG-otSkCkT5-YabtMIbr.js +1 -0
  19. package/dist/assets/{architectureDiagram-5GKGNRK7-ELuPYMlf-BVwy3nL5.js → architectureDiagram-5GKGNRK7-ELuPYMlf-Dopud1bd.js} +1 -1
  20. package/dist/assets/{assistive-mml-CdU3rUpx-9WJyil9U.js → assistive-mml-CdU3rUpx-CBXDqBb7.js} +1 -1
  21. package/dist/assets/{blockDiagram-I7D4REHJ-BZ7-OGWQ-DJ_yoJeo.js → blockDiagram-I7D4REHJ-BZ7-OGWQ-o5hOntDX.js} +1 -1
  22. package/dist/assets/{c4Diagram-7LVT6UL2-DCovPZ_4-HHYXxtp2.js → c4Diagram-7LVT6UL2-DCovPZ_4-DmxXKUN2.js} +1 -1
  23. package/dist/assets/channel-Bmu_OOc6-LXxQltDk.js +1 -0
  24. package/dist/assets/{chunk-4HAMMTFA-DqpzLmar-DJ1-BAEE.js → chunk-4HAMMTFA-DqpzLmar-DiA8EWSJ.js} +1 -1
  25. package/dist/assets/{chunk-75Z2AOVW-CT5TYzp5-BqVlAXHK.js → chunk-75Z2AOVW-CT5TYzp5-lldrjFxV.js} +1 -1
  26. package/dist/assets/{chunk-DU6HZSFF-BVf-rtdf-j0iAsvSt.js → chunk-DU6HZSFF-BVf-rtdf-CwUL1NFa.js} +1 -1
  27. package/dist/assets/{chunk-F27PBJKO-rP8pUsk3-isUMsRCA.js → chunk-F27PBJKO-rP8pUsk3-CzNXy7AU.js} +1 -1
  28. package/dist/assets/{chunk-IMKFNOWR-D_IT0r3G-_E5dx4qo.js → chunk-IMKFNOWR-D_IT0r3G-B9KUwB52.js} +1 -1
  29. package/dist/assets/{chunk-POPQ4Y6H-C5YURnHe-CVHH07lj.js → chunk-POPQ4Y6H-C5YURnHe-BSqsqkgY.js} +1 -1
  30. package/dist/assets/{chunk-SHT3W25Y-CfF0J8Qh-BJkXPGFU.js → chunk-SHT3W25Y-CfF0J8Qh-5fHXXkh7.js} +1 -1
  31. package/dist/assets/{chunk-SVP7TREG-CTZbRIbX-qfNTuIIF.js → chunk-SVP7TREG-CTZbRIbX-CWrs29Kz.js} +1 -1
  32. package/dist/assets/{chunk-TICWLB2K-DP1lYmZm-CTOUiTGz.js → chunk-TICWLB2K-DP1lYmZm-DDcA7wX4.js} +1 -1
  33. package/dist/assets/{chunk-XXDRQBXY-vg0kfC73-Y6mHTBlA.js → chunk-XXDRQBXY-vg0kfC73-B9m3UCLq.js} +1 -1
  34. package/dist/assets/classDiagram-ZZMXUADV-BDQOAOBf-BUvThf0-.js +1 -0
  35. package/dist/assets/classDiagram-v2-VYDZK3BY-CwPXtzoF-BUvThf0-.js +1 -0
  36. package/dist/assets/{cose-bilkent-JH36ORCC-qIiD3RGD-PigsuAIN.js → cose-bilkent-JH36ORCC-qIiD3RGD-8iqUd8fN.js} +1 -1
  37. package/dist/assets/cynefin-OW5HDTMX-Xr6IPdZG-BzdrGHCp.js +1 -0
  38. package/dist/assets/{cynefinDiagram-5FMLGOSQ-BZrUCS-v-73Ok3dUi.js → cynefinDiagram-5FMLGOSQ-BZrUCS-v-BjGdpO1b.js} +1 -1
  39. package/dist/assets/{dagre-C2SZ8h4o-DCI8Jkuz.js → dagre-C2SZ8h4o-Bv8J8VUz.js} +1 -1
  40. package/dist/assets/{dagre-GXQ25YYZ-CQcLM4na-Da-Tzkmd.js → dagre-GXQ25YYZ-CQcLM4na-BEUkvakq.js} +1 -1
  41. package/dist/assets/{diagram-S7CK7UJ4-BdmcmUQh-DS8N1X76.js → diagram-S7CK7UJ4-BdmcmUQh-C17Q-TTS.js} +1 -1
  42. package/dist/assets/{diagram-UQ7AKVKN-BtvmEiYl-BAWFKiBy.js → diagram-UQ7AKVKN-BtvmEiYl-sOGBhdh3.js} +1 -1
  43. package/dist/assets/{diagram-VSXAHHWV-qEG6N0bV-CqGanGZ0.js → diagram-VSXAHHWV-qEG6N0bV-D-F3WtOn.js} +1 -1
  44. package/dist/assets/{diagram-VX7I27RA-BA8is49N-BBKhve38.js → diagram-VX7I27RA-BA8is49N-DDC2KnwX.js} +1 -1
  45. package/dist/assets/{diagram-Z3DM3KII-XPcU7IOQ-vJaJUnt0.js → diagram-Z3DM3KII-XPcU7IOQ-DnNwyEbY.js} +1 -1
  46. package/dist/assets/{dist-D46KN4ld.js → dist-B3WvX9Mu.js} +1 -1
  47. package/dist/assets/{dist-DiLqFBy5.js → dist-B_fklXwV.js} +1 -1
  48. package/dist/assets/{dist-D7NGFeA-.js → dist-BfgqBdfY.js} +1 -1
  49. package/dist/assets/{dist-pwyQmsBT.js → dist-CqavRLcS.js} +1 -1
  50. package/dist/assets/{dist-DeiyD9Ki-oiWVdSjc.js → dist-DeiyD9Ki-CTmQI5BY.js} +1 -1
  51. package/dist/assets/{ebnfDiagram-PWID7BFC-CTHIHdBS-D6YDD2tB.js → ebnfDiagram-PWID7BFC-CTHIHdBS-BUK0gvW3.js} +1 -1
  52. package/dist/assets/{erDiagram-RLTQ6QDP-DVpWTNZj-BZiEF7-i.js → erDiagram-RLTQ6QDP-DVpWTNZj-WczcFdQ5.js} +1 -1
  53. package/dist/assets/eventmodeling-NTZA5JFV-B7bRrpt_-izWjOGe8.js +1 -0
  54. package/dist/assets/flowDiagram-HODETNUW-r-3T5g30-D06E2Yur.js +1 -0
  55. package/dist/assets/{ganttDiagram-EL5Y4UJY-BfAgk15F-Ch_WOR7W.js → ganttDiagram-EL5Y4UJY-BfAgk15F-DTGMCrLj.js} +1 -1
  56. package/dist/assets/gitGraph-4MIJSDKK-BhzSx5wq-HItyG1D5.js +1 -0
  57. package/dist/assets/{gitGraphDiagram-WWUBYQGX-DEVVZ6wt-CJ-VvdQR.js → gitGraphDiagram-WWUBYQGX-DEVVZ6wt-HdaEqyjq.js} +1 -1
  58. package/dist/assets/{graphlib-BYLhHyYO-BTjvpy7p.js → graphlib-BYLhHyYO-DQGQ3Hua.js} +1 -1
  59. package/dist/assets/{html-Z7dGbczU-BENxCjXi.js → html-Z7dGbczU-CrSYt5SB.js} +1 -1
  60. package/dist/assets/{index-E1VZG-CI.js → index-CFCwHCAC.js} +311 -311
  61. package/dist/assets/index-ZQzSIgvD.css +1 -0
  62. package/dist/assets/info-A6RAGUB7-fR2SUJmJ-CCp3Pve-.js +1 -0
  63. package/dist/assets/{infoDiagram-27XIBGKW-CvHUhAHd-BfqRmAMB.js → infoDiagram-27XIBGKW-CvHUhAHd-Bqc9FCJv.js} +1 -1
  64. package/dist/assets/{ishikawaDiagram-5VMMS53U-CeqyKdwk-U5HvNjd2.js → ishikawaDiagram-5VMMS53U-CeqyKdwk-BTaokajf.js} +1 -1
  65. package/dist/assets/{journeyDiagram-3NMN7TZE-Jfi7MPDi-CXNqWNX0.js → journeyDiagram-3NMN7TZE-Jfi7MPDi-DG9WVFfp.js} +1 -1
  66. package/dist/assets/{kanban-definition-UXKFOSKX-yOrlojns-BChFjgpO.js → kanban-definition-UXKFOSKX-yOrlojns-B5-MNvAZ.js} +1 -1
  67. package/dist/assets/{lengths-CvmPfBid-yvmpRCGm.js → lengths-CvmPfBid-Ccc3uBwx.js} +1 -1
  68. package/dist/assets/{linear-jdmEy-qs-DsOG9ULI.js → linear-jdmEy-qs-BRxqk9pe.js} +1 -1
  69. package/dist/assets/{liteAdaptor-pH5MXTG0-vBxiFr54.js → liteAdaptor-pH5MXTG0-D2DVKbJh.js} +1 -1
  70. package/dist/assets/{mathjax-DVEo4UYj-Dto7C21K.js → mathjax-DVEo4UYj-z2lf4I_o.js} +1 -1
  71. package/dist/assets/{mermaid-parser.core-CzBW8Fof-Dl-G7kyI.js → mermaid-parser.core-CzBW8Fof-kR4f_D21.js} +2 -2
  72. package/dist/assets/{mermaid.core-Dv4uylek-Tf8AtUNE.js → mermaid.core-Dv4uylek-Ddm4KdK9.js} +4 -4
  73. package/dist/assets/{mindmap-definition-YA3MSWOX-DP_2R9Ga-DOL0Xu1y.js → mindmap-definition-YA3MSWOX-DP_2R9Ga-BamcFU30.js} +1 -1
  74. package/dist/assets/{mo-Xv_6CC7A-DleUYSfs.js → mo-Xv_6CC7A-C4qQoXD7.js} +1 -1
  75. package/dist/assets/packet-AYTQ26CC-B_oKR9KZ-P1h4UNRU.js +1 -0
  76. package/dist/assets/{pegDiagram-XKGWAZYB-BsBWryhi-DpFsv3mJ.js → pegDiagram-XKGWAZYB-BsBWryhi-BPOLi_DS.js} +1 -1
  77. package/dist/assets/pie-WAS4IAKB-D1ZXrN1W-BejuFjHy.js +1 -0
  78. package/dist/assets/{pieDiagram-E7YTZNPT-OugkS2pU-DyXeEqvO.js → pieDiagram-E7YTZNPT-OugkS2pU-BxJPZt-m.js} +1 -1
  79. package/dist/assets/{quadrantDiagram-AXDQQJYC-DXEAAaUE-bz8yh-V4.js → quadrantDiagram-AXDQQJYC-DXEAAaUE-CeLGIG_l.js} +1 -1
  80. package/dist/assets/radar-RG4KPBEZ-BmUgDkiH-Wu_t-Az-.js +1 -0
  81. package/dist/assets/railroad-74A4TZTK-6lEXVJo8-DJe4dT-U.js +1 -0
  82. package/dist/assets/railroad-abnf-HS5TGJTU-BG28Qiz1-M9sfPaQt.js +1 -0
  83. package/dist/assets/railroad-ebnf-LZEXJU2U-DzpHhtTH-C1RD0jlr.js +1 -0
  84. package/dist/assets/railroad-peg-WCYAUIDC-B2CHCTyG-CsDICDaK.js +1 -0
  85. package/dist/assets/{railroadDiagram-O6MQD6OU-BJys8O96-D6ZaI1pj.js → railroadDiagram-O6MQD6OU-BJys8O96-CXO-wle8.js} +1 -1
  86. package/dist/assets/{requirementDiagram-BXWQKSXE-BaDgCtM5-9Sgf11TA.js → requirementDiagram-BXWQKSXE-BaDgCtM5-Dt4Cfr6O.js} +1 -1
  87. package/dist/assets/{sankeyDiagram-P5KCCOFB-puZsr_vK-BVb6-HDd.js → sankeyDiagram-P5KCCOFB-puZsr_vK-CMC9fgwz.js} +1 -1
  88. package/dist/assets/{sequenceDiagram-WJ2MYXX4-D1ziEryC-Bi64E00J.js → sequenceDiagram-WJ2MYXX4-D1ziEryC-DB5eVRRY.js} +1 -1
  89. package/dist/assets/{src-CLC0ddSd-Fv1mJDwe.js → src-CLC0ddSd-ByF0JTrb.js} +1 -1
  90. package/dist/assets/{stateDiagram-D77RDMKH-HSEurT6h-m_zPx0BA.js → stateDiagram-D77RDMKH-HSEurT6h-BwSqvh1q.js} +1 -1
  91. package/dist/assets/stateDiagram-v2-MP3YSRHH-DnOa-Otc-DgFYwvfo.js +1 -0
  92. package/dist/assets/{svg-D_RYJvQC-Bat-_KK7.js → svg-D_RYJvQC-BPJwglJJ.js} +1 -1
  93. package/dist/assets/{swimlanes-42K2YHIH-umBsuvsI-DeFyNlra.js → swimlanes-42K2YHIH-umBsuvsI-BAnYSTii.js} +1 -1
  94. package/dist/assets/swimlanesDiagram-VR7AAH4N-ZLUyNmnU-CM3sLR6V.js +8 -0
  95. package/dist/assets/{tex-Dx2UJ3VU-CyrRnTbE.js → tex-Dx2UJ3VU-CCsHHGCD.js} +1 -1
  96. package/dist/assets/{timeline-definition-24CTP7MA-D9plt22Y-BDUElL6z.js → timeline-definition-24CTP7MA-D9plt22Y-BX4CiOEk.js} +1 -1
  97. package/dist/assets/treeView-Q6P3EWNA-BdvZ0_C5-Ce03QaRO.js +1 -0
  98. package/dist/assets/treemap-WGGIJYW6-CIJLPQlC-sLYXmnbr.js +1 -0
  99. package/dist/assets/{vennDiagram-4TSXK5OY-DZe7wY85-DdIxqotG.js → vennDiagram-4TSXK5OY-DZe7wY85-BRytU48n.js} +1 -1
  100. package/dist/assets/wardley-WFR3VGLG-CKqtFD8V-CR-W1Hkl.js +1 -0
  101. package/dist/assets/{wardleyDiagram-VM6X3IG4-DK9yytWx-C2ur_Ehx.js → wardleyDiagram-VM6X3IG4-DK9yytWx-DVNY3c-A.js} +1 -1
  102. package/dist/assets/{xychartDiagram-S5SC5T6Z-CLSO4Pc9-DIXtD358.js → xychartDiagram-S5SC5T6Z-CLSO4Pc9-XnrHm8Bf.js} +1 -1
  103. package/dist/index.html +2 -2
  104. package/package.json +1 -1
  105. package/server/agents/agent-session-title.ts +227 -0
  106. package/server/agents/antigravity-sessions.ts +12 -3
  107. package/server/agents/bounded-cache.ts +30 -0
  108. package/server/agents/codex-sessions.ts +5 -12
  109. package/server/agents/copilot-sessions.ts +21 -0
  110. package/server/agents/cursor-sessions.ts +49 -1
  111. package/server/agents/muse-session.ts +23 -1
  112. package/server/agents/sqlite-read.ts +19 -2
  113. package/server/config/keymap-check.ts +4 -2
  114. package/server/routes/session-routes.ts +35 -1
  115. package/server/skills/mulmoterminal-keys/SKILL.md +12 -2
  116. package/dist/assets/architecture-7GRP2DOG-otSkCkT5-B-KKZ_tn.js +0 -1
  117. package/dist/assets/channel-Bmu_OOc6-9G180IHe.js +0 -1
  118. package/dist/assets/classDiagram-ZZMXUADV-BDQOAOBf-AGd3RvXg.js +0 -1
  119. package/dist/assets/classDiagram-v2-VYDZK3BY-CwPXtzoF-AGd3RvXg.js +0 -1
  120. package/dist/assets/cynefin-OW5HDTMX-Xr6IPdZG-B9PG-U7U.js +0 -1
  121. package/dist/assets/eventmodeling-NTZA5JFV-B7bRrpt_-caW4hYF-.js +0 -1
  122. package/dist/assets/flowDiagram-HODETNUW-r-3T5g30-BjIGQ0gy.js +0 -1
  123. package/dist/assets/gitGraph-4MIJSDKK-BhzSx5wq-Cg664zXo.js +0 -1
  124. package/dist/assets/index-C87BKIYs.css +0 -1
  125. package/dist/assets/info-A6RAGUB7-fR2SUJmJ-ZA3BeGcN.js +0 -1
  126. package/dist/assets/packet-AYTQ26CC-B_oKR9KZ-tZL-TM0J.js +0 -1
  127. package/dist/assets/pie-WAS4IAKB-D1ZXrN1W-9Gdk_RuH.js +0 -1
  128. package/dist/assets/radar-RG4KPBEZ-BmUgDkiH-DsSqeCiO.js +0 -1
  129. package/dist/assets/railroad-74A4TZTK-6lEXVJo8-CtdQOZTi.js +0 -1
  130. package/dist/assets/railroad-abnf-HS5TGJTU-BG28Qiz1-nuv-Ibj8.js +0 -1
  131. package/dist/assets/railroad-ebnf-LZEXJU2U-DzpHhtTH-GbFob_0y.js +0 -1
  132. package/dist/assets/railroad-peg-WCYAUIDC-B2CHCTyG-DFvm6UEi.js +0 -1
  133. package/dist/assets/stateDiagram-v2-MP3YSRHH-DnOa-Otc-Olhbh80x.js +0 -1
  134. package/dist/assets/swimlanesDiagram-VR7AAH4N-ZLUyNmnU-Br2BzY66.js +0 -8
  135. package/dist/assets/treeView-Q6P3EWNA-BdvZ0_C5-C11-3lYw.js +0 -1
  136. package/dist/assets/treemap-WGGIJYW6-CIJLPQlC-d0_kiwn1.js +0 -1
  137. package/dist/assets/wardley-WFR3VGLG-CKqtFD8V-3gV1W5uy.js +0 -1
@@ -0,0 +1,23 @@
1
+ // The cap on what an agent's own store label may be, shipped to the roster.
2
+ //
3
+ // In `common/` because BOTH sides decide from it: the server cuts the title here, and the client has
4
+ // to know that a title of exactly this length may be a TRUNCATION of the prompt beneath it rather
5
+ // than the whole of it. Without that, the roster cannot tell "the summary is the entire prompt, cut
6
+ // by us" from "the summary is a shorter, different sentence that happens to start the same way", and
7
+ // suppressing the second hides a real opening (#2123, Codex round 4).
8
+ export const AGENT_TITLE_MAX = 200;
9
+
10
+ /** What an `agentTitle` IS, which the roster cannot work out from the string itself.
11
+ *
12
+ * Four agents answer with the person's OPENING PROMPT; two answer with a summary the agent wrote
13
+ * for itself. The difference decides whether a title that is exactly `AGENT_TITLE_MAX` long may be
14
+ * treated as our own truncation of the prompt beneath it — for an opening prompt it is, for an
15
+ * agent's own summary it may simply be a long sentence that happens to start the same way.
16
+ *
17
+ * Sent per response rather than derived on the client, so the two cannot drift: the server states
18
+ * what it just read. */
19
+ export type AgentTitleKind = "opening-prompt" | "agent-summary";
20
+
21
+ /** Which kind each agent's store answers with. copilot and muse write their own summary — and are
22
+ * also the two the reader never caches, because they REWRITE it as the conversation goes. */
23
+ export const agentTitleKind = (agent: string): AgentTitleKind => (agent === "copilot" || agent === "muse" ? "agent-summary" : "opening-prompt");
package/common/keymap.ts CHANGED
@@ -94,7 +94,8 @@ export type Keymap = Partial<Record<KeymapAction, string>> & { send?: SendBindin
94
94
 
95
95
  // A parsed binding. `key` is matched against `KeyboardEvent.key` exactly as the browser
96
96
  // reports it, so it is case-sensitive for printable characters ("a" and "A" differ, the
97
- // latter implying Shift).
97
+ // latter implying Shift) — except while Cmd is held on macOS, where the browser reports the
98
+ // UNSHIFTED character and an uppercase letter is unreachable (validateKeymap warns, #2125).
98
99
  export interface KeyBinding {
99
100
  key: string;
100
101
  shift: boolean;
@@ -227,11 +228,35 @@ export function validateKeymap(input: unknown): KeymapProblem[] {
227
228
  return [{ action, binding, reason: 'unparseable key binding — expected e.g. "PageDown" or "Shift+PageUp"', fatal: true }];
228
229
  }
229
230
  claim(parsed, { label: action, binding, rank: KEYMAP_ACTIONS.indexOf(action), kind: "action" });
230
- return [];
231
+ return unshiftedUnderCmdWarnings(action, binding, parsed);
231
232
  });
232
233
  return [...problems, ...duplicateWarnings(bound)];
233
234
  }
234
235
 
236
+ // A binding that says one keystroke and waits for another. While Cmd is held, a macOS browser puts
237
+ // the UNSHIFTED character in `KeyboardEvent.key` — Cmd+Shift+P arrives as `"p"` — so a binding
238
+ // written `"Cmd+Shift+P"` waits for a `"P"` that never comes, and nothing downstream can see the
239
+ // difference between that and a shortcut the user has not pressed yet (#2125).
240
+ //
241
+ // Safari and Chrome both do this and w3c/uievents#169 is still open, so it is the platform, not a
242
+ // bug to route around: matching stays case-sensitive (`"a"` and `"A"` are different keystrokes,
243
+ // pinned by the specs) and this only says so out loud.
244
+ //
245
+ // A WARNING, not an error: the deviation is macOS's, so a browser following the spec reports `"P"`
246
+ // and the identical entry is correct there — and the server cannot know which one will connect.
247
+ const UPPERCASE_ASCII_LETTER = /^[A-Z]$/;
248
+ const unshiftedUnderCmdWarnings = (action: string, binding: string, parsed: KeyBinding): KeymapProblem[] =>
249
+ parsed.meta && parsed.shift && UPPERCASE_ASCII_LETTER.test(parsed.key)
250
+ ? [
251
+ {
252
+ action,
253
+ binding,
254
+ reason: `never fires in a macOS browser — with Cmd held it reports the unshifted letter, so write the key lowercase ("${parsed.key.toLowerCase()}")`,
255
+ fatal: false,
256
+ },
257
+ ]
258
+ : [];
259
+
235
260
  interface Claim {
236
261
  label: string;
237
262
  binding: string;
@@ -262,7 +287,7 @@ function sendProblems(input: unknown, claim: (parsed: KeyBinding, entry: Claim)
262
287
  }
263
288
  // Ranked after every action, matching who actually wins (see the `bound` comment above).
264
289
  claim(parsed, { label, binding: entry.key, rank: KEYMAP_ACTIONS.length + i, kind: "send" });
265
- return [];
290
+ return unshiftedUnderCmdWarnings(label, entry.key, parsed);
266
291
  });
267
292
  }
268
293