Skip to content

fix(slack): preserve active prefetch claims under cap - #325

Merged
parkjs101 merged 6 commits into
devfrom
codex/issue-317-slack-context
Aug 12, 2026
Merged

fix(slack): preserve active prefetch claims under cap#325
parkjs101 merged 6 commits into
devfrom
codex/issue-317-slack-context

Conversation

@parkjs101

@parkjs101 parkjs101 commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

Scope

Narrow #316 follow-up discovered while auditing #317. The #317 conversation-context production wiring is already present on dev; this PR does not duplicate it.

At the 500-entry prefetch-claim cap, the prior eviction path could remove an active in-flight claim. A concurrent envelope for that same thread could then acquire a second claim and inject the same history twice.

Change

  • distinguish active claims from committed, completed claims
  • evict only committed claims under capacity pressure
  • fail open (return no claim) when all bounded slots are active
  • commit a claim only after history is actually injected
  • immediately commit the no-history claim for threads started by the bot
  • add regression coverage for all-active and mixed active/completed capacity pressure

Verification

  • post-fetch focused Slack context/enrichment/history/prefetch oracle: 100 passed, 0 failed
  • Slack-wide unit run: 457 passed, 0 failed, 1 skipped (devlog submodule unavailable)
  • npm run typecheck: passed
  • npm run build: passed
  • structure/verify-counts.sh: all 366 file-tree entries matched, 3 paths skipped; the script still exited 1 after the aggregate/public phase due the existing aggregate-parser behavior, so a full verify-counts pass is not claimed

No Slack scopes changed. Message delivery remains fail-open when no prefetch claim is available.

Summary by CodeRabbit

  • Bug Fixes

    • Improved Slack thread-history handling so relevant context is retained more reliably when processing messages.
    • Prevented active thread-processing slots from being displaced unexpectedly when capacity is reached.
    • Completed thread operations can now be cleared appropriately, allowing new activity to proceed without interrupting in-progress work.
  • Tests

    • Added coverage for thread-processing capacity and safe handling of active versus completed operations.

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 38716faa-2a12-41eb-97b6-ed97776a3a4e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Slack prefetch claims now commit only after history injection. Active claims remain protected when capacity is full. Completed claims can be evicted. Slack event paths now commit and release claims according to their lifecycle.

Changes

Slack prefetch lifecycle

Layer / File(s) Summary
Claim lifecycle and capacity rules
src/slack/thread-tracker.ts, tests/unit/slack-thread-prefetch.test.ts
Claims now store tokens with committed status. Capacity eviction removes only committed claims. commitThreadPrefetch validates ownership. Tests cover full capacity and completed-claim eviction.
Slack event integration
src/slack/bot.ts, structure/str_func.md
Message processing commits claims after history injection. Top-level mentions commit claims immediately. The file-tree reference updates Slack file line counts.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related issues

  • lidge-jun/cli-jaw#322 — Both changes modify Slack thread-prefetch claim lifecycle and eviction behavior.

Suggested reviewers: lidge-jun

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: preserving active Slack prefetch claims when the capacity cap is reached.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/issue-317-slack-context

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@parkjs101
parkjs101 marked this pull request as ready for review August 12, 2026 11:28

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/slack/bot.ts`:
- Around line 241-245: Update handleSlackEnvelope’s post-prefetch-token flow to
use a try/finally that releases the acquired claim on every early return and
attachment-recovery exception. Track whether enqueueSlackIngress (or the
existing ownership-transfer path) accepted the token, and only skip release when
ownership was accepted; preserve normal processing and commit behavior
otherwise.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3549565e-0dc8-4f80-940f-062ff8a69ff6

📥 Commits

Reviewing files that changed from the base of the PR and between c9da60c and 4afc972.

📒 Files selected for processing (4)
  • src/slack/bot.ts
  • src/slack/thread-tracker.ts
  • structure/str_func.md
  • tests/unit/slack-thread-prefetch.test.ts

Comment thread src/slack/bot.ts
Comment on lines +241 to +245
await runSlackMessageEvent(event, target, text, signal, opts, () => {
prefetchCommitted = Boolean(opts.prefetchToken) && commitThreadPrefetch(
event.channel || '', event.thread_ts || '', opts.prefetchToken || 0,
);
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Release claims on every pre-enqueue exit.

processSlackMessageEvent releases only claims that reach its finally. handleSlackEnvelope acquires prefetchToken before attachment recovery, then can return at Line 500 or Lines 503-511 without passing the claim to this function. An attachment-recovery exception has the same result.

These paths leave an uncommitted claim active. The new capacity logic cannot evict active claims. After 500 such threaded events, all later prefetch claims are declined until reset.

Wrap post-claim work in a try/finally. Release the token unless enqueueSlackIngress accepts ownership.

Proposed lifecycle guard
 const prefetchToken = event.thread_ts
     ? claimThreadPrefetch(event.channel || '', event.thread_ts)
     : 0;
+let prefetchHandedOff = false;
 
-const target = buildSlackTarget(event);
+try {
+const target = buildSlackTarget(event);
 // ... attachment recovery and early-return paths ...
 
 enqueueSlackIngress(slackIngressLaneKey(target), signal =>
     processSlackMessageEvent(event, target, text, signal, {
         prefetchToken,
         // ...
     }));
+prefetchHandedOff = true;
+} finally {
+    if (prefetchToken && !prefetchHandedOff) {
+        releaseThreadPrefetch(event.channel || '', event.thread_ts || '', prefetchToken);
+    }
+}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/slack/bot.ts` around lines 241 - 245, Update handleSlackEnvelope’s
post-prefetch-token flow to use a try/finally that releases the acquired claim
on every early return and attachment-recovery exception. Track whether
enqueueSlackIngress (or the existing ownership-transfer path) accepted the
token, and only skip release when ownership was accepted; preserve normal
processing and commit behavior otherwise.

@parkjs101
parkjs101 merged commit de921f0 into dev Aug 12, 2026
6 checks passed
@parkjs101
parkjs101 deleted the codex/issue-317-slack-context branch August 12, 2026 12:22
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