Retry the Bookeo write-back on its own schedule, not the reply checker's - #39
Merged
DorwardTech merged 2 commits intoAug 3, 2026
Conversation
23 lines sitting unwritten on a live install, and the dashboard describing them as "retried hourly". Both halves of that were mine. The retry ran at the end of CheckSmsReplies. That job is scheduled only when `crm.reply_checker_enabled` is true, and it ships FALSE on purpose — enabling it before the equivalent Cowork Routine is disabled would handle every reply twice. So on a normal install the retry never ran once. The backlog could only grow, and nothing anywhere said so. RetryBookeoLog now carries it, gated on `crm.bookeo_write_back_enabled` alone, hourly, with no between() window: unlike a reply notification there is nobody to wake, and a customer file that catches up at 3am beats one that waits for morning. Safe on its own schedule — every row it touches is marked when the write lands and skipped forever after, it sends no SMS, and it charges no credits. ## The dashboard was worse than silent "retried hourly" is a claim, and it was printed unconditionally. Whenever write-back is switched off, or Bookeo has no credentials, the number cannot move — and those are exactly the states that produce a backlog someone notices. The caption sent you looking for a fault in Bookeo when the answer was a setting in this app. The card now names the cause: "write-back is off in Settings", "Bookeo credentials are missing", or "retried hourly" when it really is. Three states, three captions, one test each. `crm:bookeo-log-backfill --dry-run` had the same gap — it reported a count and nothing about whether anything was trying to write it, which is the first question you have when looking at a backlog. It now says which of the three you are in, and points at `crm:bookeo-check` for the credentials case. Guide and README updated: the retry no longer depends on the reply checker, and the guide gains a troubleshooting entry keyed to the caption on the card, since that is what somebody will be looking at when they need it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014E51bA27LnFMK7v4YigZY1
The new dashboard fixture was called unmirroredSend(), which BookeoLogBackfillTest already declares. PHP has one global function namespace and Pest includes every test file into it, so the second declaration is a fatal — the whole run died in under a second, before a single test executed. Renamed to dashboardUnmirroredSend(). Reusing the existing one instead would have coupled the two files by collection order, which tests/Pest.php already warns against. Added a scan so this cannot come back quietly. It is static rather than a runtime check for two reasons: the fatal names only the second file, so the pair is not obvious from the output, and which file loads second depends on collection order — a collision can hide locally and only fail in CI. The scan fails one readable test naming both files, in the same order every time. Verified it catches a planted duplicate, not merely that it returns empty. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014E51bA27LnFMK7v4YigZY1
DorwardTech
marked this pull request as ready for review
August 3, 2026 00:47
DorwardTech
merged commit Aug 3, 2026
c94e38c
into
claude/zone3-darwin-internal-tool-YQKKN
2 checks passed
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.
Robert reported 23 lines not on customer files. The dashboard was describing them as "retried hourly". Both halves of that were mine.
Why nothing retried
The retry ran at the end of
CheckSmsReplies. That job is scheduled only whencrm.reply_checker_enabledis true — and it shipsfalseon purpose, so a deploy can't double up with the Cowork Routine that's still live.So on a normal install the retry never ran once. The backlog could only grow, and nothing anywhere said so.
RetryBookeoLognow carries it, gated oncrm.bookeo_write_back_enabledalone. Hourly, with nobetween()window: unlike a reply notification there's nobody to wake, and a customer file that catches up at 3am beats one that waits for morning.Safe on its own schedule — every row it touches is marked when the write lands and skipped forever after (
bookeo_logged_at,mirrored_at), it sends no SMS, and it charges no credits. The worst a spurious run can do is ask Bookeo a question it has already answered.The dashboard card was worse than silent
"retried hourly" is a claim, and it was printed unconditionally. Whenever write-back is switched off, or Bookeo has no credentials, the number cannot move — and those are exactly the states that produce a backlog somebody notices. The caption sent you looking for a fault in Bookeo when the answer was a setting in this app.
write-back is off in SettingsBookeo credentials are missingretried hourlyevery message is on its customer fileBookeoSmsLog::enabled()issetting && $bookeo->isConfigured(), so those first two are genuinely different faults with different fixes — worth separating rather than collapsing into "off".--dry-runhad the same gapIt reported a count and nothing about whether anything was trying to write it, which is the first question you have when you're staring at a backlog. It now names which of the three states you're in, and points at
crm:bookeo-checkfor the credentials case.What this does not explain
If the caption turns out to say "retried hourly" — write-back on, credentials present — then Bookeo is refusing the writes, and this PR only makes that visible rather than fixing it.
crm:bookeo-checkreports whether the key works and whether it's allowed to write customer files, which is the likelier culprit after a key rotation: the customers-write permission is a separate grant.Tests
RetryBookeoLogis scheduled with the reply checker off — the exact bugcrm.bookeo_write_back_enabledis offonOneServer,withoutOverlappingThe dashboard tests needed a helper:
BookeoClientcaptures its credentials when the singleton is built, so setting config afterwards does nothing until the container forgets the instances that captured them. The existing backlog test was passing only because the test environment has no Bookeo credentials at all — which, with this change, is now a different caption. That's the test catching the new branch, and it's been updated to configure credentials explicitly.vendor/can't be installed in this environment (codeload.github.comis blocked by the proxy), so CI is the verification.Generated by Claude Code