Skip to content

fix(f247): back off the personal Chrome reply poll while the Host Adapter is unavailable (cherry-pick of upstream #1531) - #193

Merged
mindfn merged 1 commit into
develop_basefrom
fix/develop-base-f247-poll-backoff
Sep 27, 2026
Merged

mindfn merged 1 commit into
develop_basefrom
fix/develop-base-f247-poll-backoff

Conversation

@mindfn

@mindfn mindfn commented Sep 26, 2026

Copy link
Copy Markdown
Owner

What

A cherry-pick (git cherry-pick -x) of upstream zts212653#1531, merged as 1789afb026 and approved in review 5324110998 at f6413758c1. It fixes zts212653#1532: on a Host without ChatGPT Pro (F247 personal Chrome), the reply poller checks for the Host Adapter every second, forever, and with debug logging on it writes a [F247] personal Chrome assistant return poll deferred line each time. Landy noticed this in our running instance.

While the adapter answers HOST_UNAVAILABLE, the poller now backs off exponentially: 2s, 4s, 8s, 16s, 32s, then one check every 60s. The backoff is timed on a monotonic clock. It logs one line when it starts backing off and one when it resumes. The first answer restores the one-second cadence.

Files: the poller, a new personal-chrome-assistant-return-poller-backoff.test.ts, and one line of packages/api/package.json that adds the new test to the test:f247-chrome-host-spike lane. The cherry-pick applied cleanly: the poller and the original poller test are byte-identical to upstream's pre-fix versions, and the lane line is unchanged on develop_base.

Verification on this branch (8c7b7014c7, on develop_base 7d57371444)

  • New backoff tests: 4/4. Adapter tests: pass.
  • Original personal-chrome-assistant-return-poller.test.ts: 5/6, with one pre-existing failure on develop_base that this PR doesn't cause:
    • The failing test is retains a no-Redis restart return without head-blocking newer authorized returns.
    • Its fixture calls MessageStore.append with no sender, and develop_base's MessageStore rejects that: append requires one valid MessageFrom sender identity.
    • The same test fails identically against develop_base's own poller without this commit.
    • This file runs only in the test:f247-chrome-host-spike lane, not public CI, so the failure has gone unnoticed. The fixture needs a from identity; the owner of the MessageFrom change should take it.
  • tsc --noEmit (API) is clean. Biome is clean on the changed files.
  • pnpm gate --no-rebase (the fork-internal merge criterion) is running; its result will be posted here.

After merge

The running instance picks this up only after the operator pulls develop_base and restarts. Cats don't restart the instance. That restart can also pick up anything else merged into develop_base by then, such as #191.

[宪宪/claude-opus-5-5🐾]

🤖 Generated with Claude Code

@mindfn

mindfn commented Sep 26, 2026

Copy link
Copy Markdown
Owner Author

pnpm gate --no-rebase on 8c7b7014c7: fails at step 4/6 (full type check including tests). The failure already exists on develop_base; this PR doesn't cause it.

I ran the gate with REDIS_URL, NODE_ENV and npm_config_production stripped, so it could not reach the running instance's Redis.

  • Steps 1–3 pass, including the build (public direct lane, F299 provider census OK).
  • Step 4 fails in packages/web:
    src/stores/__tests__/chatStore-delivered-connector-source.test.ts(83,9): error TS2353: Object literal may only specify known properties, and 'mentions' does not exist in type '{ id: string; from?: MessageFrom | undefined; ... }'
    
    • This PR changes no web files (git diff --stat develop_base..HEAD -- packages/web is empty), so the result is the same on develop_base itself. Every fork PR will fail the gate here until the fixture is fixed.
    • The test stages after step 4 did not run.

Both pre-existing breakages trace back to fork-only F117 changes to the message shape:

  • The web fixture above still passes mentions. git log -S mentions on the web store types points to 63921725d8 / f8071e44ae.
  • The API fixture in personal-chrome-assistant-return-poller.test.ts (5/6, noted in the PR description) appends without a sender. develop_base has required one since f426fb7902 (feat(F117): register the unified message delivery lifecycle).

I've reported both to the F117 owner thread.

This PR's own checks pass: backoff tests 4/4, adapter tests, API tsc --noEmit, Biome on the changed files, and the build. Whether to merge before the F117 fixtures are fixed is the maintainer's call. After a merge, the fix takes effect when the operator restarts the running instance.

[宪宪/claude-opus-5-5🐾]

…pter is unavailable (zts212653#1531)

* fix(f247): back off the personal Chrome reply poll while the Host Adapter is unavailable

Why: the Host always starts PersonalChromeAssistantReturnPoller at boot
(index.ts), and it polls every second. On a Host where ChatGPT Pro is not
installed there is no pairing record, so every tick fails with
HOST_UNAVAILABLE ("personal Chrome Host Adapter is not installed") and writes
"[F247] personal Chrome assistant return poll deferred". That is one wasted
check and one log line per second, forever, for everyone who does not use this
optional feature (reported by the maintainer from a running instance).

What: while the adapter answers HOST_UNAVAILABLE, the poller backs off
exponentially from twice the poll interval up to 60s (2s, 4s, 8s, 16s, 32s,
then 60s). The first successful answer resets it to the normal cadence. Only
changes of state are logged: one line when it starts backing off and one when
it resumes. HOST_UNAVAILABLE also covers "installed but the helper is not
running", which is why a capped backoff is used rather than a fixed idle
period: a reply is picked up at most 60s after the helper comes back. Other
errors keep today's per-attempt debug line.

The durable fix is F202 C1 W2-3 h3: reply polling becomes generic and runs only
for an enabled package that declares it, so a Host without ChatGPT Pro does not
poll at all. This change keeps the current wiring and only makes it quiet
until then.

Tests: personal-chrome-assistant-return-poller.test.ts, with an injected
clock.
- Over 3 minutes of 1s ticks with the adapter absent, the adapter is asked
  only at 0/2/6/14/30/62/122s, and exactly one line is logged.
- After 3 failures the adapter answers at 14s; polling returns to every
  second, with one "resumed" line.
- RED before the change. Poller and adapter suites: 19/19. tsc clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(f247): time the reply-poll backoff on a monotonic clock; test the reply that waited

Review of zts212653#1531 at db8d07f (5324077784):
- P1: the backoff deadline came from Date.now(), so a backward wall-clock step (NTP, sleep and
  wake, a manual change) could suspend recovery for as long as the step, far past the 60 s cap.
  It now uses performance.now(). The injectable clock is renamed monotonicNow so the contract is
  explicit. Regression: after the first failure Date.now() steps back an hour, and the retry still
  happens once 100 ms of real time has passed (red before the fix).
- P2: the first log line now says polling backs off exponentially, up to one check per 60s.
  Both state-change lines are asserted exactly.
- P2: a reply waiting when the adapter comes back is ingested once and acknowledged at its exact
  source on the first poll that gets an answer (14 s), then polling continues every second, with
  exactly two log lines.

Also: the backoff tests move to their own file, so the original poller test is back to its
upstream 331 lines (under the 350-line cap). The backoff steps in drainOnce move into small private
methods (Biome cognitive complexity 19, over the 15 limit, now within it). The new test file joins
the test:f247-chrome-host-spike lane.

[宪宪/claude-opus-5-5🐾]

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 1789afb)
@mindfn
mindfn force-pushed the fix/develop-base-f247-poll-backoff branch from 8c7b701 to 8e659d3 Compare September 26, 2026 10:29
@mindfn

mindfn commented Sep 26, 2026

Copy link
Copy Markdown
Owner Author

Rebased onto develop_base 52b80e1f6c, which now includes #194, the F117 fixture fix. The new head is 8e659d3049. The diff is unchanged: 3 files, +207/−6.

Gate evidence. I ran pnpm gate --no-rebase, with REDIS_URL and NODE_ENV stripped, on a local branch equal to 7d57371444 + this fix + #194's a3dd94f789. That tree is byte-identical to the rebased head (git diff 9ef5ce79fa 8e659d3049 is empty).

Merging is the maintainer's call. After a merge, the fix takes effect once the operator restarts the running instance.

[宪宪/claude-opus-5-5🐾]

@mindfn
mindfn merged commit 6824f84 into develop_base Sep 27, 2026
mindfn added a commit that referenced this pull request Sep 27, 2026
…k PR #193 把修复带到 develop_base

Why: zts212653#1531 这条线的收尾要进账本:上游合入的坐标;fork 侧通过普通 PR 把修复带到 develop_base(不用 force-push);
gate 被 F117 现存 fixture 挡在 Step 4,已报 owner;合入与重启归 Landy。只在本地提交,随下一次推送一起。

[宪宪/claude-opus-5-5🐾]

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mindfn added a commit that referenced this pull request Sep 27, 2026
… 后 gate Step 1–4 通过

Why: zts212653#1531 这条线在 fork 侧收尾:Landy 让我自己合 fork-internal 的 #193(…000470);
记下 gate 证据(Step 5 被机器休眠拖过 3 小时墙钟上限截断,截断前 0 失败)和剩下的一步(operator 重启)。

[宪宪/claude-opus-5-5🐾]

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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