Skip to content

fix(secops): confirm on Telegram when an inline answer lands - #167

Merged
oscarvalenzuelab merged 2 commits into
mainfrom
fix/secops-inline-answer-ack
Sep 9, 2026
Merged

fix(secops): confirm on Telegram when an inline answer lands#167
oscarvalenzuelab merged 2 commits into
mainfrom
fix/secops-inline-answer-ack

Conversation

@oscarvalenzuelab

Copy link
Copy Markdown
Collaborator

Answering a BLOCKED secops question produced no confirmation when the
session was still alive to receive the answer.

What the logs showed

Five questions went out on the 2026-09-09 sweep. Four were answered
inline; every one of them did real work:

Repo Result of the answer
ai-miner merged 7 Dependabot PRs
kenos-orchestrator merged 6
prompt-injection-benchmark merged 5
aiproxyguard-promptest merged 2

20 PRs merged, and not one SEND frame went back to the operator.
The bridge log between the first answer (07:22) and the end of the
sweep contains delivering ANSWER four times and no outbound message.

Why

Two paths reach a resumed session, and only one of them reports.

  • Late answer — the question outlived the session, the reply lands
    in pending_resumes, and the sweeper in cli.py sends
    ✅ Resume succeeded on <repo> per session. This has always worked.
  • Inline answer — the session was still parked in transport.ask,
    so it resumed in-process inside run_secops_all. That loop appended
    the result and moved to the next repo. Nothing was sent.

The only completion message on the inline path is the sweep-wide
✅ Scheduled secops sweep done: N/M ok, which fires after every repo
has been swept. That sweep ran 06:00 → past 07:54 across ~90 repos, so
the operator's feedback for a 07:22 answer was a bare count, hours
later, naming no repo.

The change

After the BLOCKED loop exits, report the outcome for the repo the
operator actually answered — success summary, the new question if it
re-blocked, or the error. Same three shapes the pending_resumes
sweeper already sends, so both paths now read identically in Telegram.

Two constraints shaped it:

  • Guarded on rounds > 0. Most of a 90-repo sweep finds nothing to
    decide. Acking those turns this into ~90 notifications a day, which
    is how an operator learns to ignore the channel.
  • Best-effort send. A dead bridge socket must not discard work the
    agent already completed or abort the remaining repos, so the send is
    wrapped and logged as secops.answer_ack.send_failed.

Verification

Four tests in TestSecopsInlineAnswerAck, covering the ack, the
re-block, the silence guard, and a failing socket.

Reverting secops.py alone fails exactly the two that assert the new
messages, and passes the other two:

FAILED test_successful_resume_sends_summary_to_operator
FAILED test_reblocked_resume_reports_the_new_question
2 failed, 2 passed

Full suite: 932 passed. ruff clean. mypy reports 21 errors, all 21
also present on main and none in the touched file.

Answering a BLOCKED secops question while the session is still alive
produced no feedback. The only completion message is the sweep-wide
summary, which fires once every repo has been swept — on a 90-repo
sweep that is hours after the reply, so answering felt like the bot
had ignored it.

The late-answer path (pending_resumes sweeper) already sends a
per-session result. Give the inline path the same treatment: after
the BLOCKED loop exits, report the outcome — merged summary,
re-blocked question, or error — for the repo the operator answered.

Guarded on rounds > 0 so the repos that never asked anything stay
silent; a daily ack from all 90 is how operators learn to ignore the
channel. The send is best-effort: a dead bridge socket must not
discard work the agent already completed or abort the rest of sweep.
@oscarvalenzuelab
oscarvalenzuelab merged commit 982d196 into main Sep 9, 2026
3 checks passed
@oscarvalenzuelab
oscarvalenzuelab deleted the fix/secops-inline-answer-ack branch September 9, 2026 15:16
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