Release v0.105.2 — the pre-send handset check reads the handset - #104
Merged
Merged
Conversation
Asterisk writes an AMI Getvar reply in two pieces: astman_start_ack() sends Response/ActionID unterminated, then Variable/Value and the blank line follow in a second write. parse_ami_blocks() parses the unterminated tail, so the single-response read loop stopped on the header, logged off and dropped the Value. DEVICE_STATE read "" on 28 of 29 announcements and the busy/unreachable guard judged nothing. - ami.terminated_blocks(): stop tests act only on blocks whose terminator has arrived (_ami_command single-response stop, actions_responded, actions_complete). Final parse unchanged. - The two guard refusals (skipped-busy, unreachable) now carry the clip and join the retry population (delivery.ANNOUNCE_GUARD_REFUSED), so a refused announcement is replayed under the v0.105.0 rules instead of never. - The reconciler judges a refused clip once it has been replayed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
What was wrong
Before it places an announcement, the web UI reads the handset's
DEVICE_STATEover AMI and skips the call if the phone is busy or has no contact. That read returned""on 28 of 29 announcements, so the guard judged nothing and every announcement was recordedannounce-guard-unjudged.Captured on the production PBX: Asterisk writes a Getvar reply in two writes about 10 µs apart.
astman_start_ack()sendsResponse: Success/ActionID:with no terminator, thenVariable:/Value:and the blank line follow.parse_ami_blocks()parses the unterminated tail as a block, so_ami_command(single_response=True)stopped on the header, logged off and dropped the Value.Changes
ami.terminated_blocks(): read-loop stop tests act only on blocks whose\r\n\r\nhas arrived. It is used by the single-response stop,actions_responded(the batched codec Getvars) andactions_complete. The final parse still usesparse_ami_blocks, so a read that times out keeps what it received. Every other single-response reply (Originate, Hangup, Redirect, PJSIPNotify, PJSIPRegister, errors) is written whole, so its stop fires on the samerecvas before.skipped-busyandunreachablebecome real. Both rows now carry the clip, anddelivery.ANNOUNCE_GUARD_REFUSEDmakes them retry candidates under the v0.105.0 rules (idle twice, two attempts, ≤150 s, newest per room). Otherwise the fix would have turned "originated, failed, replayed" into "refused, never replayed", which is the post-restart cordless case v0.105.0 exists for.Verification
manager.csource and found no framing defect. Its retry-contract findings were addressed: the reconciler verdict gap is fixed, and the producer re-send path was checked and does not exist.🤖 Generated with Claude Code