Skip to content

feat(commands): establish Telegram projection contract - #97169

Open
andrexibiza wants to merge 1 commit into
NousResearch:mainfrom
andrexibiza:commands/pr8-telegram-projection
Open

andrexibiza wants to merge 1 commit into
NousResearch:mainfrom
andrexibiza:commands/pr8-telegram-projection

Conversation

@andrexibiza

@andrexibiza andrexibiza commented Aug 28, 2026 •

Copy link
Copy Markdown

What does this PR do?

PR8 establishes the Telegram projection boundary for the unified slash-command architecture in #96692.

Telegram currently has three platform-specific concerns that must not become a second command authority:

  1. the Bot API exposes a bounded native command menu with stricter naming rules than Hermes command identity;
  2. Telegram may deliver /command@bot args, while the command plane must authorize and execute the same canonical command as /command args;
  3. native command registration is remote state, so a successful write is not sufficient proof that the intended menu actually settled.

This PR isolates those concerns behind three bounded modules. The canonical command catalog remains the semantic authority; Telegram receives an immutable projection of that catalog, normalizes Telegram-specific syntax back to canonical identity, and reconciles native menu state with exact ordered read-back before settlement.

The approach is intentionally dependency-light and independently landable. Current main does not yet expose the merged PR1/PR2 catalog/dispatcher ABIs, so PR8 consumes the catalog object/JSON shape without defining a competing schema or invocation/result contract. When #97143 and #97153 land, the Telegram adapter can compose this seam directly rather than absorbing more command semantics into the existing adapter.

Invariants

  • One semantic authority: Telegram projects catalog state; it does not define command identity or execution semantics.
  • Stable identity survives projection: non-blank command_id is authoritative; canonical name is the explicit current-v1 compatibility fallback.
  • Native omission is not semantic omission: commands excluded by Telegram's native limits or native-name rules remain resolvable through typed command input.
  • Addressing is syntax, not identity: /command@HermesBot args and /command args settle to the same canonical command when the bot target matches.
  • Unknown slash-shaped input does not become prompt text: command attempts remain typed unknown/invalid outcomes rather than silently crossing into model input.
  • Collisions fail closed: duplicate stable IDs, typed tokens, aliases, or sanitized native names cannot select authority by incidental catalog order.
  • Remote mutation requires proof: reconciliation advances state only after the exact ordered native payload is observed after a write.
  • Scope is part of settlement: a receipt from one Telegram command scope cannot authorize NOOP in another.

Deliberate non-goals

  • No edits to plugins/platforms/telegram/adapter.py in this slice.
  • No edits to hermes_cli/commands.py.
  • No duplicate CommandCatalog, CommandInvocation, or CommandResult ABI.
  • No behavior change at production call sites until the catalog/dispatcher slices land and the adapter composes this seam.
  • No expansion of an existing godfile; all six added files remain well below the 2,000-line ceiling.

Related Issue

Part of #96692 — this PR is PR8 of the unified slash-command decomposition and must not close the parent architecture issue by itself.

Interlocks:

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • hermes_cli/telegram_command_projection.py
    • Adds an immutable Telegram projection over one exact catalog snapshot.
    • Preserves catalog order while separating typed bindings from the bounded native Bot API payload.
    • Produces explicit HIDDEN, NATIVE_NAME_INVALID, and NATIVE_LIMIT omissions.
    • Sanitizes native Telegram names without weakening canonical typed resolution.
    • Rejects duplicate stable identities, typed-token collisions, and sanitized native-name collisions.
    • Carries catalog revision plus a deterministic projection fingerprint.
  • hermes_cli/telegram_command_normalization.py
    • Classifies Telegram text into typed NOT_COMMAND, KNOWN_COMMAND, UNKNOWN_COMMAND, NOT_FOR_THIS_BOT, and INVALID_COMMAND outcomes.
    • Normalizes /command@bot args and /command args to the same canonical command identity for the addressed bot.
    • Preserves raw arguments while producing canonical dispatcher input.
    • Keeps slash-prefixed paths/code out of command handling and prevents unknown command attempts from falling through as ordinary prompt text.
  • hermes_cli/telegram_menu_reconciliation.py
    • Adds deterministic NOOP, ADOPT, and SET planning for one Telegram command scope.
    • Detects catalog revision changes and remote drift.
    • Requires post-write read-back for SET plans.
    • Produces a settlement only when the observed ordered payload exactly matches the desired projection.
    • Rejects cross-scope settlement reuse.
  • tests/hermes_cli/test_telegram_command_projection.py
    • Characterizes stable IDs, PR1-shaped catalog compatibility, order, visibility, aliases, sanitization, native limits, immutability, and collision refusal.
  • tests/hermes_cli/test_telegram_command_normalization.py
    • Characterizes addressed/unaddressed equivalence, foreign-bot refusal, unknown command typing, path/code non-command classification, and typed fallback for native-menu omissions.
  • tests/hermes_cli/test_telegram_menu_reconciliation.py
    • Characterizes adoption, no-op, remote drift, revision change, exact read-back settlement, and scope isolation.

Exact object and footprint

  • Base: 9978706e9303dbf990d90e744b131361449d73b9
  • Head: 83f67367f80bcd48aaa734fbb14907f8954b3f85
  • Tree: 7188455480e071a0aafd3d6b5e87b7cf40915937
  • Commit topology: 1 commit, 1 ahead / 0 behind the pinned base
  • Diff: 6 added files, 1,426 additions, 0 deletions
  • Largest changed file: 527 lines
  • Existing godfiles modified: 0
  • Live code + open-PR FILE-LIST scan: no competing owner found for these six paths

Exact blob identities:

Path Blob SHA
hermes_cli/telegram_command_projection.py 897ff75623b2b99a1e7dc0c29512e1d9562e9c1a
hermes_cli/telegram_command_normalization.py 8b3616e9a3893613a197ad59f811e7177db47fca
hermes_cli/telegram_menu_reconciliation.py b3af37d4c709c6261c1be9eb3fe84d4ddcb0632f
tests/hermes_cli/test_telegram_command_projection.py 4cffb4e17f29a4741733d166ce4e800803ad39e3
tests/hermes_cli/test_telegram_command_normalization.py 0dae01a42f52f528e1a804a524df4ede3ca2a855
tests/hermes_cli/test_telegram_menu_reconciliation.py 0440522406fef959e175a88e57db496e3f0a7aad

How to Test

  1. Run the focused PR8 characterization suite:

    PYTHONPATH=. pytest -q \
      tests/hermes_cli/test_telegram_command_projection.py \
      tests/hermes_cli/test_telegram_command_normalization.py \
      tests/hermes_cli/test_telegram_menu_reconciliation.py

    Expected receipt: 26 passed.

  2. Run repository Python validation against the exact head. Hosted CI already executed the full Python test matrix, E2E suite, Ruff enforcement, Ruff + ty differential, Windows footgun gate, macOS-only tests, Windows-only tests, supply-chain checks, attribution checks, and common-ancestor checks successfully.

  3. Verify exact-head packaging/system acceptance:

  4. Characterization points worth checking explicitly:

    • /status@HermesBot Mixed CASE --Flag and /status Mixed CASE --Flag produce the same command identity and canonical input.
    • A command omitted from the native menu because of the Bot API command limit remains a typed known command.
    • foo-bar / foo_bar native-name collisions fail closed instead of depending on catalog order.
    • A successful native-menu write without exact read-back cannot produce a settlement.
    • A settlement for one scope cannot authorize NOOP in another scope.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: GitHub-hosted Linux, macOS, and Windows; Docker amd64/arm64; Nix flake acceptance

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A — N/A: behavior is defined by bounded module docstrings and characterization tests; no user-facing command behavior is wired in this slice
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A — N/A: no configuration keys added or changed
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A — N/A: no contributor workflow or repository instruction contract changed
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A — exact-head Windows and macOS jobs are green; logic is platform-independent
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A — N/A: no tool schema or tool behavior changed

Screenshots / Logs

No UI surface is changed in PR8, so screenshots are not applicable.

Focused characterization receipt:

PYTHONPATH=. pytest -q \
  tests/hermes_cli/test_telegram_command_projection.py \
  tests/hermes_cli/test_telegram_command_normalization.py \
  tests/hermes_cli/test_telegram_menu_reconciliation.py

26 passed

Hosted acceptance for the exact submitted head 83f67367f80bcd48aaa734fbb14907f8954b3f85:

Acceptance authority Result Receipt
Repository CI ✅ Success run 33174052138
Docker amd64 + arm64 ✅ Success run 33174051342
Nix flake check ✅ Success run 33174051419

Every commit in the submitted PR topology is green.

@alt-glitch alt-glitch added type/feature New feature or request comp/cli CLI entry point, hermes_cli/, setup wizard platform/telegram Telegram bot adapter P3 Low — cosmetic, nice to have labels Aug 28, 2026
@andrexibiza
andrexibiza force-pushed the commands/pr8-telegram-projection branch from c209d9c to 83f6736 Compare August 28, 2026 13:42
@Enough1122

Copy link
Copy Markdown

AI code review — automated review for reference; please use your judgment.

Overall: Establishes Telegram projection contract (PR-8 under #96692) — deterministic, revision-aware, test-heavy.

What it does

  • New hermes_cli/telegram_command_projection.py (527 lines) builds an immutable Telegram menu projection from a catalog snapshot: name sanitization, native visibility, native limits (TELEGRAM_BOT_API_MAX_COMMANDS), fingerprint.
  • New hermes_cli/telegram_command_normalization.py (141 lines) normalizes /command@bot with TelegramCommandAttemptStatus vs catalog/dispatcher identity.
  • New hermes_cli/telegram_menu_reconciliation.py (195 lines) does revision-aware native-menu reconciliation + exact settlement (TelegramMenuReconciliationAction, Settlement, VerificationStatus).
  • Tests test_telegram_command_projection, test_telegram_command_normalization, test_telegram_menu_reconciliation pin sanitization, limits, fingerprint determinism, and settlement.

Non-blocking notes

  • _TELEGRAM_INVOCATION_RE allows A-Za-z0-9_- after first char — verify bot username handling doesn't accept trailing _/- which Telegram rejects; regex is permissive but projection sanitization may later reject, so double-check error path is user-visible.
  • Projection is purely deterministic fingerprint — if catalog ordering changes, fingerprint changes and triggers reconciliation; that's intended, but ensure catalog snapshot ordering is stable (sorted by command_id) to avoid spurious menu updates.

No runtime wiring in this PR (bounded seam only) — correct narrow-waist approach.

Non-blocking — please use your judgment.

Copy link
Copy Markdown
Author

Producer exact-object closure receipt for PR8 (no self-review).

Re-verified live on exact submitted head 83f67367f80bcd48aaa734fbb14907f8954b3f85: one surviving commit, 6 added files, PR open/non-draft/mergeable. The latest hosted acceptance is fully green on that exact object: CI 33176653845 ✅, Docker 33176653106 ✅, Nix 33176653073 ✅. These newer successful runs supersede the older green run IDs recorded in the PR body; they do not change the submitted object.

Landing-edge cross-check: live main@e60983a69730c058ce772829df3273aee6de3889 is 79 commits beyond the PR8 construction pin 9978706e9303dbf990d90e744b131361449d73b9. The compare interval contains none of PR8's six paths (hermes_cli/telegram_command_projection.py, hermes_cli/telegram_command_normalization.py, hermes_cli/telegram_menu_reconciliation.py, or the three corresponding characterization tests), so there is no current file-level landing collision on this slice.

Every surviving PR commit is therefore hosted-green and the producer-side execution/landing-edge gate is current. I am not submitting a review on my own code; independent acceptance remains separate from this producer receipt.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have platform/telegram Telegram bot adapter type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants