Skip to content

Merge latest bkt3 (bkmain b7af1e60) into stage - #327

Merged
bk-agent-01 merged 32 commits into
stagefrom
sync/bkmain-into-stage-2026-10-19
Oct 19, 2026
Merged

bk-agent-01 merged 32 commits into
stagefrom
sync/bkmain-into-stage-2026-10-19

Conversation

@bk-agent-01

Copy link
Copy Markdown
Collaborator

Summary

This PR merges the latest bkmain (b7af1e60, production BkT3) into stage (f073c8c0), on Tushar's instruction of 2026-10-19: pull the latest bkt3 before the stage → bkmain merge, and deploy to stage first. After this merge, stage runs production's code plus the stage-only work. The stage → bkmain promotion (#324) then carries only that stage-only work.

The merge has no conflicts. It adds 46 files (+5545 / −78) from bkmain to stage:

From bkmain What
#315 bkt3 product metrics in PostHog (server and web analytics, deploy/bkt3/posthog-dashboards.py)
#318 Fast session-webhook acknowledgement (Toolyard callbacks no longer time out)
#296, #309, #306, #312, #314, #321 MCP OAuth redirect limit, async MCP questions, agent toolkit and earlier stage promotions (mostly already in stage)
#326 Promotion of the PR-sweep freeze fix (#325, already in stage)

Stage-only work that stays: #317 (only the newest plan stays actionable), #319, #320, #322 (Claude account revive queue and rebalance), #325.

Migrations: the merged registry ends at 1053 (ThreadClaudeAccountWait), with no duplicate ids.

How I tested

  • git merge-tree reported no conflicts, and the merge commit's tree matches it.
  • CI runs on this head. After the merge, I check that ~/.t3/stage-dev/deployed-sha equals the merge commit and that stagebkt3 serves it.

Risks and rollback

  • Risk: stagebkt3 restarts on deploy. It is the staging instance, not production.
  • Rollback: Revert the merge commit on stage.

🤖 Generated with Claude Code (Claude Opus 5.5, T3 Code)

bk-agent-01 and others added 30 commits October 10, 2026 16:27
…gister

Google's MCP connector registers more than 5 redirect URIs, and the
register endpoint refused it with invalid_redirect_uri.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fix(server): accept up to 20 MCP OAuth redirect URIs so Google can register
Promotes PRs #297-#300, #302, #303 and #305 (stage, tested there) to bkmain.
Built on stage before #301, so #301 stays on stage for its owner to test.

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

feat(mcp): agent toolkit, scheduled prompts and session watches (promote to bkmain)
…ns block

A Codex async question is a runtime request answered by message. The
shell leaves those out of pendingRuntimeRequest and only flags them, so
the agent toolkit's loader read nothing: t3_inbox showed the question
without options and t3_answer said nothing waits.

The loader now reads pending message-mode requests whenever the shell
flags one. Every question shows whether it blocks the agent; t3_answer
takes a short requestId, reports how a non-blocking answer reached the
agent, and dismisses a non-blocking question with dismiss: true.
t3_send_message no longer refuses for a non-blocking question.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rs only its question

Review fixes:
- an approval next to a non-blocking question loaded no details, because
  the approval read sat in an else branch;
- t3_answer without requestId now refuses when more than one question is
  open, and every answer hint carries the short requestId, so a retried
  answer cannot land on the next question;
- a secret request (the shell stands it in as a question) now says that a
  person enters it in the app, instead of asking to try again;
- t3_inbox counts the non-blocking questions it does not show;
- the delivery check reads only the answer's own run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…the secret id type

- the secret stand-in id is compared as a string (TS2367: TurnItemId vs
  RuntimeRequestId);
- t3_answer refuses a question, dismiss or decision that has a
  clientRequestId but no requestId, so a retry cannot land on a request
  asked since; approval hints carry the short requestId;
- t3_send_message names a secret request instead of pointing to t3_answer;
- secret text in JSON output is cut like other agent-written text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fix(mcp): t3_answer sees Codex async questions and says which questions block
… end fix

Promotes #310, #311 and #301 (whose own promotion PR is #307).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
chore: promote stage to bkmain (Running shelf, collapse-all, Claude subagent end fix)
…rver)

TEC-1306

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
chore: promote stage to bkmain (TEC-1306 settled shelf follows the server)
- Session time-in-state tracker: one state per session (agent_running,
  waiting_human, waiting_workers, queued, idle, archived) emitted as
  session.state.span events, plus run/request/subagent/plan events and a
  5-minute concurrency snapshot. Same reducer drives a history backfill.
- Identity: distinct_id is the environment user's work email, instance
  property and group, property allowlist that drops free text.
- No upstream default PostHog key; telemetry stays off without one.
- Agent child processes no longer inherit the analytics env.
- Server events for MCP tool calls, scheduled tasks, webhooks, session
  recovery and Linear links.
- Web/desktop client analytics via lazily loaded posthog-js, named events
  only, config delivered by the server at runtime.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- No zero-length spans; span id includes state, waitKind and run id.
- Ignore late updates of finished runs; close only active spans at shutdown.
- Backfill: normalised emails, --until required for --send.
- Web: no persistent opt-out, strip all URL-derived properties,
  identify only by normalised email.
- Register backfill script with knip; scope one Effect diagnostic.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
feat(server): bkt3 product metrics in PostHog
A thread kept its PLAN pill, Plan Ready group and needs-human count for as
long as its plan stayed active, even after plan mode was turned off. A plan
now waits only while its thread is in plan mode, matching upstream's Plan
Ready rule, so stale tags clear without a migration.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit e925a5b)
- Remove the plan card's Preview button; Expand plan stays.
- New header: icon, title, state, step count, reading time, and a
  Widen plan toggle that lets cards use the free width beside the chat.
- Plan bodies get the chat's markdown features (skills, runnable shell
  commands, image preview, artifact templates).
- HTML in a plan renders as a live themed page, like html_render: a whole
  HTML plan, a raw HTML document, or an html-render fence.
- Selecting plan text offers Cite and the comment actions; highlights,
  pins and scroll-to-quote work on plans, and the panel labels them.
- Plan-mode turns tell the agent how to add an html-render visual.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 0d14438)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit a0d2255)
- The plan-format hint joins the fork's plan policy only when plan
  submission is off, so provider replays keep their recorded input.
- Compare a citation's message id with the plan id as plain strings.
- Type the comments panel's message list so plans can join it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 9e3b3f8)
- Plan HTML loads inline through srcDoc, so a frame opened on its own
  cannot run with the app's origin. The reader's theme is written into
  the page for the first paint and posted on change.
- A remounted plan page starts at its last measured height, so the
  virtualised list does not jump.
- A wide card starts after the timeline minimap's clickable strip.
- Plan cards read a memoised slice of the timeline state.
- Comment gutter bars sit in the card padding, not over the text.
- Settings and docs no longer point at the removed Preview button.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 0901743)
…smissed

When a run fails while the agent waits on a question (the provider stream
closes, an event fails to ingest), the run ends and its provider session is
detached, but the question stays pending with a live capability. Submit then
failed with "Provider session ... was not found", dismiss failed with
"This question needs an answer", and Stop was gone.

A request whose session is detached or whose run has ended is now handled in
message mode: an answer resolves it and reaches the agent as the next
message, a dismissal closes it, and an approval closes without a reply. The
composer marks such a question dismissible. Multi-select answers join their
choices when sent as a message.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit e8ee65f)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 2a6abc8)
- A completed run no longer counts as ended: its session stays live and a
  background subagent can still wait on an approval. Failed, interrupted
  and cancelled runs do.
- Read only the request's own run, and take it from the timeline item when
  the node has none.
- MCP lists a question whose run failed or stopped as non-blocking, so
  t3_answer can dismiss it and t3_send_message no longer refuses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 56e1306)
… bkt3

Promote plan cards and stuck-question fix to bkt3 (#319, #320)
…ime out) (#318)

* fix(server): fast webhook ack and personal-token toolyard proxy

Session webhook receive: the admission transaction called the Toolyard
integration's owner check, which reads environment users through
Effect.runPromise on a fresh fiber. The SQLite client has one connection
behind a one-permit semaphore held by the open transaction, so that read
waited for the transaction that waited for it. Every push callback hung
until Toolyard's 20 s client timeout, the request was interrupted and the
insert rolled back. The transaction now runs SQL only; the binding is
checked before it and again by the dispatch loop.

Upstream MCP proxy: a personal T3 token (t3usr_) may call
/mcp/upstream/toolyard as the token's own user, with that user's managed
Toolyard credential, when the server and user external MCP switches are on.
No x-t3-session-id is sent for these calls. Provider sessions are unchanged.

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

* test(server): fix the session-webhook owner-check test for lint and the live clock

- Reuse one payload for the duplicate delivery. Under it.live a second
  h.event() carries a new timestamp, so the retry was a 409 content
  conflict instead of a duplicate.
- Keep the fresh-fiber Effect.runPromise read, which replicates the
  production owner check, behind a reasoned oxlint suppression.

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

* revert(server): drop the personal-token toolyard proxy from this PR

The host relay timer that needed a personal t3usr_ token on
/mcp/upstream/toolyard was cancelled (2026-10-15), so the new access
path has no user. Keep only the fast session-webhook ack.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ezing bkt3

The minute pull-request sweep checked all 1,100 unsettled threads on bkt3.
Each check starts 6-7 git processes and every start forks the 1.4 GB server
on the event loop, so a sweep ran 50-95 s of every two minutes with the main
thread saturated (55% of samples in uv_spawn). Replies took 504 ms median
during a sweep against 2 ms outside it, and desktop connections hit their
15 s setup limit. A thread with no run or message for a day is now checked
once every 30 passes; its own events still queue an immediate check.

The agent toolkit's plan-flag correction read a run's turn items with an
`IN (...) OR (...)` filter, so SQLite walked every item of the thread in
ordinal order: 0.3-2.6 s per cold 30,000-item thread, measured as a 2.5 s
event-loop stall at 10:32 UTC. Run filters now read through the
(thread_id, run_id) index: 4 ms median on the same cold threads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 5afbacb)
bk-agent-01 and others added 2 commits October 19, 2026 16:51
fix(server): promote the pull-request sweep and plan-flag freeze fix to bkt3
Tushar, 2026-10-19: pull the latest bkt3 before the stage -> bkmain merge,
and deploy to stage first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL labels Oct 19, 2026
@bk-agent-01
bk-agent-01 merged commit a26a040 into stage Oct 19, 2026
25 of 26 checks passed
@bk-agent-01
bk-agent-01 deleted the sync/bkmain-into-stage-2026-10-19 branch October 19, 2026 15:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant