diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index f24fcf0..f057409 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -11,7 +11,7 @@ "name": "telegram-dev", "displayName": "Telegram Dev", "description": "Telegram development, split by the API each surface actually speaks. telegram-bots covers the official HTTP Bot API \u2014 update_id as the only idempotency key, the allowed_updates default that drops three types in silence, the webhook secret header, rate limits as a design constraint, and Telegram Stars with its ten-second pre-checkout window. telegram-userbots covers MTProto and Telethon \u2014 the session file as a credential equal to the password, FloodWaitError as the API working rather than failing, and the account-ban risk a bot token does not carry. telegram-miniapps covers initData verification, the algorithm shipped as a runnable fixture, and the SDK package whose name moved.", - "version": "0.2.1", + "version": "0.2.2", "author": { "name": "ssheleg", "url": "https://x.com/sshlg93" diff --git a/CHANGELOG.md b/CHANGELOG.md index 87da507..d097881 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,24 @@ +## v0.2.2 — «добавь Telegram-бота» reaches the bot skill + +The 2026-10-08 family routing audit found that a request written with the inflected or +Latin-script name of a bot — «добавь Telegram-бота» — loaded no skill at all. The +`telegram-bots` description carried «телеграм бот» with a space and nothing else, and +a match on words cannot see one form inside another. + +- **`telegram-bots` now names «Telegram-бот», «Telegram-бота» and «телеграм-бота» in + its first sentence,** beside "Telegram bot". They lead rather than join the trigger + list at the end, because harness listings cut long descriptions and the cut falls + well before the `Triggers -` clause. The description is 958 characters, inside the + 970 house limit. +- **The trigger corpus gains `q13`** («добавь Telegram-бота в проект», should trigger), + held out in the validation split. It is data for the next measured run, not a result: + `test/evals/RESULTS.md` still records no model runs. +- **The house-limit plant now derives its padding.** It appended a fixed run of words, + which at 905 characters landed between 970 and 1024; at 958 it overshot the 1024 cap, + and `npm run test:negatives` reported the plant BROKEN because the validator refused + it for the cap rather than the house limit. The plant now computes the length that + lands midway between the two limits, so the next description edit cannot silence it. + ## v0.2.1 — the README names both ways to reach a skill Hygiene from the 2026-09-13 family audit (HK-11). The install section showed four diff --git a/SKILL-CARD.md b/SKILL-CARD.md index bb75fe1..6f55808 100644 --- a/SKILL-CARD.md +++ b/SKILL-CARD.md @@ -5,7 +5,7 @@ | Field | Value | |---|---| | Pack | `telegram-dev` | -| Version | `0.2.1` | +| Version | `0.2.2` | | Skills | `telegram-bots`, `telegram-userbots`, `telegram-miniapps` | | License | MIT | | Source | https://github.com/ssheleg/telegram-dev | diff --git a/package.json b/package.json index 775ece0..a87e89e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@ssheleg/telegram-dev", - "version": "0.2.1", + "version": "0.2.2", "description": "Three skills for building on Telegram, separated by which API each one speaks: the official HTTP Bot API for bots, MTProto (Telethon) for user accounts, and Mini Apps for the web layer whose whole security model is one signed blob.", "bin": { "telegram-dev": "bin/telegram-dev.js" diff --git a/plugins/telegram-dev/.claude-plugin/plugin.json b/plugins/telegram-dev/.claude-plugin/plugin.json index e8721f9..9c5d1cb 100644 --- a/plugins/telegram-dev/.claude-plugin/plugin.json +++ b/plugins/telegram-dev/.claude-plugin/plugin.json @@ -3,7 +3,7 @@ "name": "telegram-dev", "displayName": "Telegram Dev", "description": "Telegram development, split by the API each surface actually speaks. telegram-bots covers the official HTTP Bot API \u2014 update_id as the only idempotency key, the allowed_updates default that drops three types in silence, the webhook secret header, rate limits as a design constraint, and Telegram Stars with its ten-second pre-checkout window. telegram-userbots covers MTProto and Telethon \u2014 the session file as a credential equal to the password, FloodWaitError as the API working rather than failing, and the account-ban risk a bot token does not carry. telegram-miniapps covers initData verification, the algorithm shipped as a runnable fixture, and the SDK package whose name moved.", - "version": "0.2.1", + "version": "0.2.2", "author": { "name": "ssheleg", "url": "https://x.com/sshlg93" diff --git a/plugins/telegram-dev/skills/telegram-bots/SKILL.md b/plugins/telegram-dev/skills/telegram-bots/SKILL.md index 6a33073..ec4cc05 100644 --- a/plugins/telegram-dev/skills/telegram-bots/SKILL.md +++ b/plugins/telegram-dev/skills/telegram-bots/SKILL.md @@ -1,8 +1,9 @@ --- name: telegram-bots description: >- - Use when building or auditing a Telegram bot on the official HTTP Bot API: - receiving updates by polling or webhook, deduplicating them, keyboards and + Use when building, adding or auditing a Telegram bot (Telegram-бот, + Telegram-бота, телеграм-бота) on the official HTTP Bot API: receiving + updates by polling or webhook, deduplicating them, keyboards and inline mode, Telegram Stars payments, files, rate limits, and the seam where an update becomes a row in your own database. Covers the pinned API version, update_id as the only idempotency key, the allowed_updates default that drops diff --git a/test/evals/triggers.json b/test/evals/triggers.json index d5c5027..6dc5e90 100644 --- a/test/evals/triggers.json +++ b/test/evals/triggers.json @@ -16,7 +16,8 @@ "q06", "q10", "q11", - "q12" + "q12", + "q13" ] }, "queries": [ @@ -103,6 +104,13 @@ "query": "Build the same workflow as a Slack bot", "should_trigger": false, "why": "Telegram is not the platform" + }, + { + "id": "q13", + "lang": "ru", + "query": "добавь Telegram-бота в проект", + "should_trigger": true, + "why": "inflected Latin-script form; the 2026-10-08 routing audit found it reached no skill" } ] } diff --git a/test/validate.py b/test/validate.py index b43c48b..29af022 100644 --- a/test/validate.py +++ b/test/validate.py @@ -443,11 +443,27 @@ def check_routed_triggers_still_advertised(): # ------------------------------------------------------------------- self-test +def _pad_description_past_house(text: str) -> str: + """Grow the description to land BETWEEN the house limit and the spec cap. + + Derived, never written: a literal run of padding words planted the house-limit + defect only while the description stayed short. At 958 characters the same + padding overshot 1024 and the plant reported the cap instead of the house limit + (found at v0.2.2), so the length to add is computed from the description itself. + """ + m = re.match(r"^---\n(.*?)\n---\n", text, re.S) + desc = scalar(m.group(1), "description") if m else None + if not desc or len(desc) >= DESC_HOUSE: + return text # nothing to plant — reported BROKEN as "changed nothing" + need = (DESC_HOUSE + DESC_MAX) // 2 - len(desc) - 1 # -1: the joining space + filler = ("padding " * (need // 8 + 2))[:need].rstrip() or "p" + filler += "x" * (need - len(filler)) + return text.replace("license: MIT", f" {filler}\nlicense: MIT", 1) + + PLANTS = ( ("a description over the house limit", "plugins/telegram-dev/skills/telegram-bots/SKILL.md", - lambda t: t.replace("license: MIT", " padding padding padding padding padding padding " - "padding padding padding padding padding padding padding padding\n" - "license: MIT", 1), "past the"), + _pad_description_past_house, "past the"), ("a front-matter name that does not match the directory", "plugins/telegram-dev/skills/telegram-bots/SKILL.md", lambda t: t.replace("name: telegram-bots", "name: telegram-bot", 1), "must equal the directory"),