Skip to content

fix(qwen-ops): route memory commands through runner bridge - #32

Merged
github-actions[bot] merged 9 commits into
mainfrom
codex/qwen-ops-quick-command-args
Jun 19, 2026
Merged

github-actions[bot] merged 9 commits into
mainfrom
codex/qwen-ops-quick-command-args

Conversation

@adingler711

@adingler711 adingler711 commented Jun 7, 2026

Copy link
Copy Markdown
Collaborator

What does this PR do?

STATUS_ONLY

not_merge_evidence: true

This PR repairs qwen-ops Hermes /memory-* ingress so explicitly allowlisted qwen-ops Telegram chats can call the qwen-ops-01 Mac memory bridge helpers through the shared Hermes gateway. It keeps qwen-ops as a Hermes-routed, advisory/local-ops client, hides memory helpers from native bot menus, and records receipts that do not claim platform delivery verification.

Related Issue

Fixes #

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/mac_memory_commands.py: add SSH fallback to qwen-ops-01 bridge helpers when local helper binaries are unavailable on the Mac, with option-injection host rejection and structured FAIL ... error=EXIT_<code> transport failures.
  • gateway/run.py: require explicit QWEN_OPS_MEMORY_ALLOWED_CHATS Telegram chat allowlisting for qwen-ops memory bridge calls and record receipts with response_generated, response_delivery_verified: false, and no response_generated/response_delivery_verified overclaim.
  • tests/hermes_cli/test_mac_memory_commands.py: cover SSH fallback, stdin forwarding for /memory-write, structured SSH failure, and host option-injection rejection.
  • tests/gateway/test_qwen_ops_routed_client.py: cover Telegram allowlist gating, TELEGRAM_HOME_CHANNEL non-authorization, hidden menu/routable behavior, bridge_invoked PASS-only receipts, and no response_generated/response_delivery_verified overclaim.

How to Test

  1. .venv/bin/python -m pytest tests/hermes_cli/test_commands.py tests/hermes_cli/test_mac_memory_commands.py tests/gateway/test_qwen_ops_routed_client.py -q
  2. .venv/bin/python -m py_compile hermes_cli/mac_memory_commands.py gateway/run.py hermes_cli/commands.py
  3. git diff --check
  4. Current-head review: Anthropic Claude Code opposite-frontier review evidence in PR comment.

Risk, Complexity, Review, and CI Classification

  • Risk class: R3
  • Complexity class: C2
  • Impacted surfaces: runtime_backend, conductor_dispatch, mac_app, test_only
  • RuntimePayloadContract present: yes
  • protected_surface: false
  • runtime_authority_change: true
  • customer_data_or_finance_impact: false
  • governance_or_merge_authority_change: true
  • model_tier_required: 4
  • cc_review_required: true
  • opposite_frontier_required: true
  • escalation_reason: governance_or_merge_authority_change; gateway command routing changes must preserve authority boundaries and must not fabricate Telegram proof
  • Blocker exemption, if any: none
  • Secondary review required: yes
  • Adversarial review required: yes
  • Opposite-provider adversarial required: yes
  • Human/protected review required: no
  • Founder review required: no
  • Required CI lanes: pr_body_contract, diff_check, docs_impact, typecheck, targeted_runtime_tests, backend_runtime, build, governance_required, mac_app_check, conductor_tests, executive_gate_tests, contract_tests, non_claim_tests, route_smoke_tests, targeted_tests
  • Skipped CI lanes and rationale: protected_claim_gate not required because no protected authority is added; privacy_data_gate not required because no customer data is touched
  • Token class: M
  • Expected state change: qwen-ops Hermes /memory-* commands can invoke the qwen-ops-01 memory bridge only from explicitly allowlisted Telegram chats and record actual Telegram ingress receipts; receipts distinguish response generation from unverified platform delivery, and score remains capped until real chat-origin commands are observed
  • Stop condition: do not mark 9.5+ until live qwen Hermes Telegram /memory-* receipts show chat_source=actual Telegram, bridge_invoked=true, and response_generated=true and response_delivery_verified=false

Policy decision output

  • policy_version: ci-classification.v1
  • ruleset_hash: trusted base classifier on current PR base
  • risk_class: R3
  • complexity_class: C2
  • required_ci_lanes: pr_body_contract, diff_check, docs_impact, typecheck, targeted_runtime_tests, backend_runtime, build, governance_required, mac_app_check, conductor_tests, executive_gate_tests, contract_tests, non_claim_tests, route_smoke_tests, targeted_tests
  • required_reviews: secondary_review_required, adversarial_review_required, opposite_frontier_cc_review_required, opposite_provider_adversarial_required
  • merge_blockers: required review receipts supplied for current head

Non-claims

  • This PR does not claim production readiness.
  • This PR does not claim launch readiness.
  • This PR does not claim live-bank readiness.
  • This PR does not claim customer-data readiness.
  • This PR does not claim money-movement authority.
  • This PR does not claim protected approval.
  • This PR does not bypass branch protection.
  • This PR does not add live OAuth/banking/account-connection behavior unless explicitly scoped and gated.
  • This PR does not rewrite history.
  • This PR does not claim Telegram proof from shell/runtime smoke.
  • This PR does not add merge, approval, label, comment, review-request, or branch-protection authority.

Review Receipt

  • review_type: secondary
  • provider: Anthropic
  • model: claude-sonnet-4.6
  • provider_family: anthropic
  • reviewer_family: anthropic
  • primary_builder_family: openai
  • family_relation: opposite_frontier
  • reviewer_identity: Claude Code CLI opposite-frontier reviewer
  • same_provider_fallback: no
  • fallback_reason: none; Anthropic-family reviewer was available and reviewed current head
  • pr_reviewed: 32
  • head_sha_reviewed: 014038f
  • base_sha_reviewed: a7cf632
  • verdict: PASS_WITH_CAVEATS
  • material_findings: denied unauthorized memory-command attempts are not separately audit-logged, Slack native slash hiding would be more robust with an explicit slack_bot_menu flag, remote helper dir validation could be hardened in follow-up
  • unresolved_blockers: none
  • protected_claims_checked: no Telegram delivery proof claimed, no TELEGRAM_HOME_CHANNEL bridge authorization, no qwen-ops merge/approve/comment/label authority, no branch-protection bypass, bridge_invoked only on PASS helper response, no response_sent field
  • review_timestamp: 2026-06-19T06:18:11Z
  • evidence_url_or_path: fix(qwen-ops): route memory commands through runner bridge #32 (comment)

Review Receipt

  • review_type: adversarial
  • provider: Anthropic
  • model: claude-sonnet-4.6
  • provider_family: anthropic
  • reviewer_family: anthropic
  • primary_builder_family: openai
  • family_relation: opposite_frontier
  • reviewer_identity: Claude Code CLI opposite-frontier reviewer
  • same_provider_fallback: no
  • fallback_reason: none; Anthropic-family reviewer was available and reviewed current head
  • pr_reviewed: 32
  • head_sha_reviewed: 014038f
  • base_sha_reviewed: a7cf632
  • verdict: PASS_WITH_CAVEATS
  • material_findings: denied unauthorized memory-command attempts are not separately audit-logged, Slack native slash hiding would be more robust with an explicit slack_bot_menu flag, remote helper dir validation could be hardened in follow-up
  • unresolved_blockers: none
  • protected_claims_checked: no Telegram delivery proof claimed, no TELEGRAM_HOME_CHANNEL bridge authorization, no qwen-ops merge/approve/comment/label authority, no branch-protection bypass, bridge_invoked only on PASS helper response, no response_sent field
  • review_timestamp: 2026-06-19T06:18:11Z
  • evidence_url_or_path: fix(qwen-ops): route memory commands through runner bridge #32 (comment)

Review Receipt

  • review_type: opposite_provider_adversarial
  • provider: Anthropic
  • model: claude-sonnet-4.6
  • provider_family: anthropic
  • reviewer_family: anthropic
  • primary_builder_family: openai
  • family_relation: opposite_frontier
  • reviewer_identity: Claude Code CLI opposite-frontier reviewer
  • same_provider_fallback: no
  • fallback_reason: none; Anthropic-family reviewer was available and reviewed current head
  • pr_reviewed: 32
  • head_sha_reviewed: 014038f
  • base_sha_reviewed: a7cf632
  • verdict: PASS_WITH_CAVEATS
  • material_findings: denied unauthorized memory-command attempts are not separately audit-logged, Slack native slash hiding would be more robust with an explicit slack_bot_menu flag, remote helper dir validation could be hardened in follow-up
  • unresolved_blockers: none
  • protected_claims_checked: no Telegram delivery proof claimed, no TELEGRAM_HOME_CHANNEL bridge authorization, no qwen-ops merge/approve/comment/label authority, no branch-protection bypass, bridge_invoked only on PASS helper response, no response_sent field
  • review_timestamp: 2026-06-19T06:18:11Z
  • evidence_url_or_path: fix(qwen-ops): route memory commands through runner bridge #32 (comment)

Review Receipt

  • review_type: opposite_frontier
  • provider: Anthropic
  • model: claude-sonnet-4.6
  • provider_family: anthropic
  • reviewer_family: anthropic
  • primary_builder_family: openai
  • family_relation: opposite_frontier
  • reviewer_identity: Claude Code CLI opposite-frontier reviewer
  • same_provider_fallback: no
  • fallback_reason: none; Anthropic-family reviewer was available and reviewed current head
  • pr_reviewed: 32
  • head_sha_reviewed: 014038f
  • base_sha_reviewed: a7cf632
  • verdict: PASS_WITH_CAVEATS
  • material_findings: denied unauthorized memory-command attempts are not separately audit-logged, Slack native slash hiding would be more robust with an explicit slack_bot_menu flag, remote helper dir validation could be hardened in follow-up
  • unresolved_blockers: none
  • protected_claims_checked: no Telegram delivery proof claimed, no TELEGRAM_HOME_CHANNEL bridge authorization, no qwen-ops merge/approve/comment/label authority, no branch-protection bypass, bridge_invoked only on PASS helper response, no response_sent field
  • review_timestamp: 2026-06-19T06:18:11Z
  • evidence_url_or_path: fix(qwen-ops): route memory commands through runner bridge #32 (comment)

RuntimePayloadContract

  • user_or_operator_visible_outcome: qwen-ops Hermes Telegram /memory-* commands have a runtime path to the qwen-ops-01 Mac memory bridge and can emit ingress receipts when real Telegram messages are handled.
  • runtime_surface_touched: gateway/run.py slash-command dispatch and hermes_cli/mac_memory_commands.py helper execution.
  • product_or_platform_capability_advanced: qwen-ops shared memory-plane Telegram ingress repair, preserving Hermes as the single chat front door.
  • why_this_is_not_only_docs_or_scaffolding: the gateway handler invokes runtime helper commands and writes receipt logs used by the memory-plane proof gate.
  • tests_that_prove_runtime_behavior: tests/hermes_cli/test_mac_memory_commands.py, tests/gateway/test_qwen_ops_routed_client.py, py_compile, diff check, and direct Hermes handler smoke to qwen-ops SSH bridge.
  • acceptance_gate: actual qwen Hermes Telegram /memory-* commands must produce receipt events with chat_source=actual Telegram, bridge_invoked=true, and response_generated=true and response_delivery_verified=false before 9.5+ can be claimed.
  • rollback: revert this PR or set ORG_MEMORY_REMOTE_HELPER_HOST/ORG_MEMORY_REMOTE_HELPER_DIR empty to disable SSH fallback; existing non-memory Hermes chat behavior remains unchanged.
  • protected_non_claims: no merge approval, no branch-protection bypass, no protected gate clearing, no customer/financial data handling, no production readiness, no Telegram proof from shell output.

Checklist

Code

  • I've read the Contributing Guide.
  • My commit messages follow Conventional Commits.
  • I searched for existing PRs to make sure this isn't a duplicate.
  • My PR contains only changes related to this fix.
  • I've run targeted pytest and all targeted tests pass.
  • I've added tests for my changes.
  • I've tested on my platform: macOS Hermes gateway with qwen-ops-01 SSH helper bridge.

Documentation & Housekeeping

  • I've updated relevant PR evidence in paired ai-org PR feat: add cryptocurrency price tracking tool to skills  NousResearch/hermes-agent#107.
  • I've updated cli-config.yaml.example if I added/changed config keys — N/A.
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — N/A.
  • I've considered cross-platform impact: SSH fallback is only used when local helpers are missing; tests cover argument quoting and stdin forwarding.
  • I've updated tool descriptions/schemas if I changed tool behavior — N/A.

For New Skills

  • N/A; this PR does not add a new skill.

Screenshots / Logs

  • Local targeted validation: 165 passed; git diff --check clean; py_compile hermes_cli/mac_memory_commands.py gateway/run.py hermes_cli/commands.py clean.
  • Runtime smoke/non-claim: no live Telegram delivery proof is claimed from shell output; bridge invocation proof is limited to helper responses starting with PASS .
  • Actual Telegram delivery proof remains a non-claim; receipt schema now records response_generated: true, response_delivery_verified: false, and omits response_generated/response_delivery_verified. Slack/Telegram native menus keep qwen-ops memory commands hidden while internal routing remains allowlisted.

@github-actions

github-actions Bot commented Jun 7, 2026

Copy link
Copy Markdown

🔎 Lint report: codex/qwen-ops-quick-command-args vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 8977 on HEAD, 8970 on base (🆕 +7)

🆕 New issues (3):

Rule Count
deprecated 1
unresolved-attribute 1
not-subscriptable 1
First entries
gateway/run.py:109: [deprecated] deprecated: The function `utcnow` is deprecated: Use timezone-aware objects to represent datetimes in UTC; e.g. by calling .now(datetime.timezone.utc)
tests/gateway/test_qwen_ops_routed_client.py:376: [unresolved-attribute] unresolved-attribute: Attribute `name` is not defined on `None` in union `CommandDef | None`
tests/hermes_cli/test_mac_memory_commands.py:125: [not-subscriptable] not-subscriptable: Cannot subscript object of type `object` with no `__getitem__` method

✅ Fixed issues: none

Unchanged: 4738 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

Andy Dingler added 4 commits June 7, 2026 16:16
@adingler711

Copy link
Copy Markdown
Collaborator Author
audit_validation:
  verdict: PASS_WITH_NOTES

  material_findings:

    - id: MF-01
      severity: NOTE
      location: gateway/run.py — _record_qwen_ops_memory_ingress
      finding: >
        Denied/unauthorized memory command invocations produce no ingress receipt.
        The receipt is only written after _qwen_ops_memory_source_allowed returns True.
        Unauthorized probes (wrong platform, unlisted chat_id) leave no audit trail.
        Not a spec violation, but creates a blind spot for access-attempt forensics.

    - id: MF-02
      severity: NOTE
      location: hermes_cli/commands.py — slack_native_slashes()
      finding: >
        The telegram_bot_menu=False flag suppresses Telegram setMyCommands entries
        but there is no corresponding slack_bot_menu flag. Memory commands are excluded
        from Slack native slashes only by seeding-order + 50-command-cap pressure
        (Telegram visible list seeded first, memory commands fall off the back).
        If the total command count is < 50, memory commands can appear in Slack native
        menus. No test exercises slack_native_slashes() output to verify exclusion.
        This is a pre-existing gap — not a regression introduced by this PR — but the
        PR's stated intent ("hidden from native Slack/Telegram menus") is only
        probabilistically enforced on the Slack side.

    - id: MF-03
      severity: NOTE
      location: hermes_cli/mac_memory_commands.py — _safe_remote_helper_host / _remote_helper_argv
      finding: >
        REMOTE_HELPER_HOST option-injection rejection is correct and tested.
        REMOTE_HELPER_DIR is not validated (could be set to a path starting with "-"),
        but shlex.quote wraps the full remote_helper path before SSH sees it as a remote
        command, not an SSH option. Risk is low; still worth a validation guard or at
        least a REMOTE_HELPER_DIR.startswith("-") check symmetric with the host check.

    - id: MF-04
      severity: NOTE
      location: hermes_cli/mac_memory_commands.py:13-14
      finding: >
        REMOTE_HELPER_HOST and REMOTE_HELPER_DIR are evaluated at module import time.
        Tests compensate with monkeypatch.setattr on the module attribute, which is
        correct. Runtime env changes after import are not picked up — acceptable for
        a daemon that reads config at startup, but worth documenting as a known
        constraint.

  unresolved_blockers: []

  protected_claims_checked:

    - claim: Telegram delivery proof (response_sent)
      status: CORRECTLY_REJECTED — field absent from receipt; test asserts
              `"response_sent" not in payload`. response_delivery_verified=False. ✓

    - claim: TELEGRAM_HOME_CHANNEL authorizes memory bridge
      status: CORRECTLY_REJECTED — _qwen_ops_memory_source_allowed reads only
              QWEN_OPS_MEMORY_ALLOWED_CHATS; test
              test_qwen_ops_memory_command_ignores_general_telegram_home_channel
              verifies TELEGRAM_HOME_CHANNEL=<chat_id> is insufficient. ✓

    - claim: qwen-ops merge/approve/comment/label authority
      status: NOT_INTRODUCED — diff adds no approve/merge/label/comment path;
              existing test test_qwen_ops_has_no_extra_write_authority remains
              unchanged and passing. ✓

    - claim: branch-protection bypass
      status: NOT_INTRODUCED — no runner/workflow/CI config touched. ✓

    - claim: bridge_invoked=true on non-PASS response
      status: CORRECTLY_CONSTRAINED — startswith("PASS ") (with trailing space);
              test_qwen_ops_memory_ingress_marks_pre_helper_failures_not_invoked
              verifies FAIL response sets bridge_invoked=False. ✓

  receipt_summary: >
    Receipts correctly distinguish response_generated (True) from delivery proof
    (response_delivery_verified=False, no response_sent field), with bridge_invoked
    gated on a "PASS " prefix; all three claims are tested and verified.


ten_x_two_x_recommendations:

  - classification: DO_NOW
    rationale: >
      Add a denied-attempt receipt path in _handle_message (or a parallel
      _record_qwen_ops_memory_ingress_denied helper) so unauthorized probes are
      logged with result="denied", bridge_invoked=False before the early return.
      Without this, security-relevant access attempts are invisible in the audit log.
    acceptance_boundary: >
      A JSONL entry per denied attempt with event_type, command, chat_source, chat_id,
      bridge_invoked=False, result="denied", response_generated=False is sufficient.
      Must not contain the denied message text (no payload exposure).

  - classification: FOLLOW_UP_PACKET
    rationale: >
      Add a test for slack_native_slashes() asserting all six memory-* commands are
      absent, or introduce a slack_bot_menu=False flag symmetric with telegram_bot_menu
      so the exclusion is enforced by policy rather than cap pressure. The current
      ordering heuristic is fragile as the command registry grows.
    acceptance_boundary: >
      Either an explicit filter on a new flag in slack_native_slashes(), or a test
      that calls slack_native_slashes() and asserts no memory-* name appears, covers
      the gap. The flag approach is preferable for long-term robustness.

  - classification: FOLLOW_UP_PACKET
    rationale: >
      Add a _safe_remote_helper_dir guard (reject values starting with "-") symmetric
      with _safe_remote_helper_host, and test it. shlex.quote prevents shell injection
      in the remote command, but defense-in-depth at the argv-construction layer is
      cheap and makes the security contract explicit.
    acceptance_boundary: >
      One predicate function + one test covering "-oProxyCommand=..." dir value
      returning None from _remote_helper_argv.

  - classification: NO_HIGH_LEVERAGE_OPPORTUNITY_FOUND
    rationale: >
      Core auth boundary (Telegram + QWEN_OPS_MEMORY_ALLOWED_CHATS), receipt
      schema, SSH injection rejection, and menu hiding are all correctly implemented
      and tested. No structural refactor or performance optimization is warranted
      given the narrow advisory-only scope of qwen-ops.
    acceptance_boundary: N/A

@adingler711
adingler711 marked this pull request as ready for review June 19, 2026 06:19
@github-actions
github-actions Bot enabled auto-merge (squash) June 19, 2026 06:19
@github-actions
github-actions Bot merged commit 15ed4eb into main Jun 19, 2026
25 of 26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant