test(04-03): the four CS landmines + the CR1-CR15 /cari gate suite

- commands.test.mjs: commandSources gains commands/cari.ts; CS4 documents
  the SECOND inline-keyboard carve (venue card allowed, reply keyboard
  still banned in commands/); CS5 menu becomes help/privacy/cari; CS5b's
  future-stub ban narrows to /pergi_ke (reserved for Phase 5, D-01); CS6
  registers cari+search in the alias set
- cari.test.mjs NEW: CR1-CR15 — payload shapes captured through the real
  createBot + fake baseFetch (getMe included), plus source-introspection
  gates with the stripComments helper: venue fields, OPEN URL = configured
  origin + plain slug id, NO-CRYPTO law (D-11), one-message alternates,
  callback_data discipline, honest refusal, 128-char cap, always-answer,
  category-only logging (D-15), bilingual copy, registration script, swap
  semantics, hostile-id drop
- register-commands.mjs: menu list gains cari (two fetch calls unchanged)
- [Rule 1] location-fallback.ts: the message handler now passes non-location
  messages through (next) — it matched EVERY message and silently starved
  all downstream message-stage handlers, so /cari never fired through the
  real factory; caught by the fake-transport suite
- suites: bot 65/65 (15 CR + 9 CS + all prior), web 33/33, search 57/57,
  bot:typecheck green
This commit is contained in:
araharah-executor
2026-10-24 01:21:10 +08:00
parent 13e5073261
commit 5dcef0e2bb
5 changed files with 490 additions and 24 deletions
+3 -2
View File
@@ -7,7 +7,8 @@
* 2. default + language_code "ms" — Malay descriptions for ms users
*
* D-03: the menu lists ONLY commands that exist in this phase (/help,
* /privacy) — no stub entries reserved for future commands. There are
* /privacy, /cari) — no stub entries reserved for future commands (the
* Phase-5 navigation command stays reserved and unregistered). There are
* exactly two fetch calls below, one per scope.
*
* D-05 (single copy source): the descriptions are not inline here — they
@@ -58,7 +59,7 @@ if (!token) {
/** Extract the `/cmd — description` entries from a locale's helpMenu. */
function menuFor(locale) {
const lines = strings[locale].helpMenu.split("\n");
return ["help", "privacy"].map((command) => {
return ["help", "privacy", "cari"].map((command) => {
const marker = `/${command} — `;
const line = lines.find((l) => l.startsWith(marker));
if (line === undefined) {