feat: add Telegram process-event channel (adopted from upstream #2966) - #1
Merged
Conversation
Registers the captain's Telegram channel with the generic process-to-event runner so a captain message wakes firstmate within seconds instead of waiting up to five minutes for a check sweep. The adapter is deliberately thin: it owns Telegram's getUpdates long poll, the write-before-offset invariant that keeps a captain message from being lost, and token handling; ownership, durable capture, publication, and restart recovery stay with bin/fm-procevent.sh. The channel is never terminal on its own - only an explicit retire stops it.
The prior handoff-safety fixes checked whether an update id's inbox file already existed and then wrote it, which cannot be safe against state/telegram-watch.check.sh: that home-local script writes in place with no temp file and no rename, so its output can be observed mid-write, and a check-then-write gap can still race it. Replace that with an atomic claim: this adapter always writes its own complete, fsynced payload to a private temp file first, then hardlinks that finished file onto the shared <update_id>.json name. A successful hardlink is an exclusive, race-free claim. A failed one (name already taken) is resolved by parsing whatever is already there - a complete, well-formed payload for that update means another claimant (the legacy script or an earlier invocation of this adapter) already delivered it, so this poll no-ops without a second captain-visible wake; anything else means a claimant, most likely the legacy script, is still mid-write, and that update blocks the whole batch's offset advance exactly like a failed write, so an unadvanced retry gives the write time to finish. handled/ is checked first so an archived update is never recreated in the live inbox. This does not make true simultaneous overlap (both producers inside getUpdates for the same not-yet-advanced offset) free - the legacy script has no knowledge of this adapter and can still fire its own independent wake through the check sweep, which nothing here can suppress. Only ensuring no legacy invocation is genuinely in flight before arming (not merely deregistering it) closes that window; the header documents this plainly rather than claiming a guarantee the design cannot make. Also keeps the two accumulated fixes this branch already carries: a durable pending-delivery record so an offset-write failure never strands an already- written message, checked and reported before any credential validation. Adds a regression test that reproduces the legacy script's exact non-atomic write shape mid-write, overlapping a batch that also contains a genuinely new update, and proves the batch blocks without corruption or duplication and resolves correctly once the legacy write finishes.
Carry the accepted Telegram adapter and regression coverage onto a fresh validation branch, including permanent API failure signaling and receipt recovery protections. Co-authored-by: Cursor <cursoragent@cursor.com>
Registers the captain's Telegram channel with the generic process-to-event runner so a captain message wakes firstmate within seconds instead of waiting up to five minutes for a check sweep. The adapter is deliberately thin: it owns Telegram's getUpdates long poll, the write-before-offset invariant that keeps a captain message from being lost, and token handling; ownership, durable capture, publication, and restart recovery stay with bin/fm-procevent.sh. The channel is never terminal on its own - only an explicit retire stops it.
The prior handoff-safety fixes checked whether an update id's inbox file already existed and then wrote it, which cannot be safe against state/telegram-watch.check.sh: that home-local script writes in place with no temp file and no rename, so its output can be observed mid-write, and a check-then-write gap can still race it. Replace that with an atomic claim: this adapter always writes its own complete, fsynced payload to a private temp file first, then hardlinks that finished file onto the shared <update_id>.json name. A successful hardlink is an exclusive, race-free claim. A failed one (name already taken) is resolved by parsing whatever is already there - a complete, well-formed payload for that update means another claimant (the legacy script or an earlier invocation of this adapter) already delivered it, so this poll no-ops without a second captain-visible wake; anything else means a claimant, most likely the legacy script, is still mid-write, and that update blocks the whole batch's offset advance exactly like a failed write, so an unadvanced retry gives the write time to finish. handled/ is checked first so an archived update is never recreated in the live inbox. This does not make true simultaneous overlap (both producers inside getUpdates for the same not-yet-advanced offset) free - the legacy script has no knowledge of this adapter and can still fire its own independent wake through the check sweep, which nothing here can suppress. Only ensuring no legacy invocation is genuinely in flight before arming (not merely deregistering it) closes that window; the header documents this plainly rather than claiming a guarantee the design cannot make. Also keeps the two accumulated fixes this branch already carries: a durable pending-delivery record so an offset-write failure never strands an already- written message, checked and reported before any credential validation. Adds a regression test that reproduces the legacy script's exact non-atomic write shape mid-write, overlapping a batch that also contains a genuinely new update, and proves the batch blocks without corruption or duplication and resolves correctly once the legacy write finishes.
Carry the accepted Telegram adapter and regression coverage onto a fresh validation branch, including permanent API failure signaling and receipt recovery protections. Co-authored-by: Cursor <cursoragent@cursor.com>
Preserve the local implementation history while merging the pipeline's rebased base and accepted Telegram safety fixes for the next validation run. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…anup-order contracts
…-telegram-local-fork Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # .agents/skills/process-event-sources/SKILL.md # bin/fm-procevent-telegram.sh # tests/fm-procevent-telegram.test.sh
Owner
Author
|
Superseded: hand-created PR cannot receive no-mistakes pipeline attestation. Reopening via pipeline-created fork PR on the same branch head f18b369. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
CEO overview
mainchanges.mainchanges are integrated by merge commit; the validated Telegram files remain byte-identical to upstream heade7dd9178b7920dc50982f8915fcf7e8a48fae337. Merge only after all required fork checks pass.What changed technically
This branch merges current fork
mainat54681894c5ab839fe6d5c2f0170a1d94aa427361with validated upstream heade7dd9178b7920dc50982f8915fcf7e8a48fae337in merge commitd59128d7ff98ba81d9def82cb149395448cdd83a. When the fork is behind, this also brings the fork up to the upstream base carried by the original upstream PR #2933.Validation
fm/telegram-state-redesign, not by this PR. Theupdate_idceiling rationale in the validated validation module is also an inaccurate documentation rationale carried forward deliberately. This PR does not claim at-least-once, no-loss, or lossless behavior for the handoff path.Module-boundary decision
Current module retained: This delivery does not redesign or alter the Telegram adapter storage core.
Decision needed
No decision required for the code adoption. Do not merge until the fork’s required checks pass.