Skip to content

fix(server): stale toolBroker test; activity-label no-op clears + bounded maps (GHE #341, #202, #203) - #149

Draft
johnnyelwailer wants to merge 2 commits into
mainfrom
fix/toolbroker-test-activity-label-341-202-203
Draft

johnnyelwailer wants to merge 2 commits into
mainfrom
fix/toolbroker-test-activity-label-341-202-203

Conversation

@johnnyelwailer

Copy link
Copy Markdown
Owner

Distro issues: nexplore.ghe.com/pj/nexi-distribution#341, #202, #203.

What

Receipts

  • pnpm exec vp test run src/t3team-toolBroker.test.ts src/t3team-activityLabelSummarizer.test.ts src/t3team-boundedThreadMap.test.ts → 33/33
  • typecheck: no errors in touched files
  • LOC: reactor 261→279, summarizer 301→337 (both already over the 200 cap on main; the map logic was extracted to keep growth to the new subscription + forget(); a proper split of these two files is separate debt)

Codex review pending.

🤖 Generated with Claude Code

@github-actions github-actions Bot added size:L vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Sep 2, 2026
@johnnyelwailer

Copy link
Copy Markdown
Owner Author

Codex review (refute-first) — 1 confirmed bug + 1 partial; NOT fixed yet, PR stays draft

  1. Stranded label after FIFO eviction (t3team-activityLabelSummarizer.ts:130-132, 180, 185, 260): pending lives on after a successful persist (kept alive for TTL), eviction deletes it and cancels the TTL, and the new clear() early-return then bails on idle → a persisted real label is never cleared. Repro: persist label for t1, push 500 other threads, t1 idles. Fix direction: track "label persisted" separately from pending, and on evict either persist {activityLabel: null} or keep a tiny persisted-set so clear() still fires. Test: eviction-after-persist then idle → meta.update null dispatched.
  2. Persist after thread.deleted (reactor.ts:247, 273-275; run() :176/:180): generation is detached and does not re-check after await persist; forget() clears maps only, so a thread.meta.update can land on a deleted thread. Low impact (no state resurrection); fix: re-check a per-thread generation token after the await.

Verified clean: FIFO cap + eviction tests; timer cancellation on evict/forget; idle/deletion ordering is sequential in one stream fiber.

@johnnyelwailer

Copy link
Copy Markdown
Owner Author

Both Codex findings fixed in the 2nd commit (new sibling t3team-activityLabelPersistTracker.ts; summarizer 337→346 lines, reactor unchanged). Tests 35/35 incl. eviction-after-persist → null clear, and forget-during-persist → result discarded. Still draft: no live-app run.

johnnyelwailer pushed a commit that referenced this pull request Sep 2, 2026
… results after forget()

Codex review findings on PR #149: (1) FIFO eviction dropped the pending entry that
clear() gated on, so a persisted label was never cleared — a sibling persist tracker now
records 'label persisted' independently of pending, clear() persists null whenever a label
is persisted, and eviction of such a thread persists the null clear; (2) generation ran
detached and did not re-check after await persist — a per-thread epoch bumped by forget()
is checked before and after the await. Tests 35/35 (2 new).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 4, 2026 •

Copy link
Copy Markdown
Contributor

Thread transfer impact

⚠️ The latest CI run did not produce a thread transfer result for 6c4d4d3.

This comment will update automatically after the next completed run.

Phil J and others added 2 commits September 9, 2026 18:09
…persists no-op clears and bounds its maps

GHE #341: the "binds generic thread tools without a stored view context" expectation was
missing t3team.orchestration.status / .resume, which genericThreadToolIds has bound since
58c8d66 — red on pristine main.

GHE #202: summarizer.clear() persisted `thread.meta.update {activityLabel: null}` on every
idle-type event even when no label was ever noted for the thread (flag off, no activity).
It returns early when there is no pending state, so idle threads stop bumping updatedAt.

GHE #203: userGistByThread (reactor) and windowByThread (summarizer) were pruned only on
idle; a thread that never idles leaked until restart. Both now use one small sibling
createBoundedThreadMap (insert-time FIFO cap of ACTIVITY_LABEL_MAX_TRACKED_THREADS = 500,
onEvict hook), and the reactor subscribes to thread.deleted (same pattern as
t3team-threadToolContextEvictionReactor) to forget() without persisting.

Tests: toolBroker + activityLabelSummarizer + boundedThreadMap — 33/33.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… results after forget()

Codex review findings on PR #149: (1) FIFO eviction dropped the pending entry that
clear() gated on, so a persisted label was never cleared — a sibling persist tracker now
records 'label persisted' independently of pending, clear() persists null whenever a label
is persisted, and eviction of such a thread persists the null clear; (2) generation ran
detached and did not re-check after await persist — a per-thread epoch bumped by forget()
is checked before and after the await. Tests 35/35 (2 new).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@johnnyelwailer
johnnyelwailer force-pushed the fix/toolbroker-test-activity-label-341-202-203 branch from 00f4612 to 6c4d4d3 Compare September 9, 2026 16:25

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 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