Skip to content

feat(lip): push-driven health via long-lived subscribe#210

Merged
SimplyLiz merged 2 commits intodevelopfrom
feat/lip-push-subscribe
Apr 15, 2026
Merged

feat(lip): push-driven health via long-lived subscribe#210
SimplyLiz merged 2 commits intodevelopfrom
feat/lip-push-subscribe

Conversation

@SimplyLiz
Copy link
Copy Markdown
Owner

Summary

  • Replaces 60 s TTL polling of IndexStatus with a long-lived subscriber that consumes the daemon's existing index_changed pushes (LIP v1.5.0+)
  • New internal/lip/subscribe.go: one connection, pings index_status every 3 s to flush the daemon's broadcast channel, reads every frame, reconnects with exponential backoff (cap 30 s)
  • Engine.lipSemanticAvailable() is now lock-free — no RPC, no dial, no TTL check — so the rerank gate is free on the hot path. Worst-case staleness drops from 60 s to ~3 s
  • CHANGELOG catches up on feat(query): gate LIP semantic rerank on !MixedModels #208 and feat(query): position-weighted seeding + coherence gate for LIP rerank #209 which merged to develop without entries

Why push not poll

The LIP daemon broadcasts IndexChanged { indexed_files, affected_uris } to every active session after each upsert (session.rs:279). CKB's client was unary-only so we couldn't consume them — we polled instead. The daemon only drains queued pushes after writing a response (no select! between the read and the broadcast channel), so the subscriber still has to issue a cheap request on a ticker; the request doubles as the health probe that feeds the mixed-models gate.

Test plan

  • go test ./internal/query/... ./internal/lip/...
  • go build -o ckb ./cmd/ckb
  • go vet ./...
  • New test TestLipSubscriber_ReusesSingleConnection verifies lipSemanticAvailable triggers zero extra daemon requests
  • Manual: ckb mcp against a live LIP daemon, confirm ckb doctor still reads MixedModels correctly and the rerank gate flips within ~3 s of lip index rebuild
  • Manual: kill the LIP daemon mid-session, confirm subscriber reconnects and lipSemanticAvailable flips to false within one ping

🤖 Generated with Claude Code

CKB used to re-probe IndexStatus on a 60 s TTL every time the rerank
path checked whether the LIP index was mixed-models. The LIP daemon has
pushed IndexChanged frames to all active sessions since v1.5.0, so the
polling was pure debt.

New internal/lip/subscribe.go opens a long-lived connection, pings
IndexStatus every 3 s to flush the daemon's broadcast channel (the
session loop drains queued pushes only after writing a response), reads
every frame in a loop, and routes index_changed and index_status by
type tag. Reconnects with exponential backoff to 30 s on daemon drop.

Engine owns one subscriber, started in NewEngine and cancelled in
Close. The cached availability/mixed flags are now written by the
subscriber, not the query path — lipSemanticAvailable is lock-free
RLock+read, no RPC. Worst-case staleness for the rerank gate drops
from 60 s to ~3 s.

Tests rewritten: the fake daemon now serves multiple requests per
connection and tests wait for the first health frame before asserting,
plus a new TestLipSubscriber_ReusesSingleConnection verifies the hot
path issues zero requests.

Also: CHANGELOG entries for #208 and #209 which landed on develop
without one.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 15, 2026

🟢 Change Impact Analysis

Metric Value
Risk Level LOW 🟢
Files Changed 0
Symbols Changed 0
Directly Affected 0
Transitively Affected 0

Blast Radius: 0 modules, 0 files, 0 unique callers


Generated by CKB

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 15, 2026

CKB Analysis

Risk Files +0 -0 Modules

📊 2 complex · 📚 197 stale

Risk factors: Small, focused change

Metric Value
Impact Analysis 0 symbols → 0 affected 🟢
Doc Coverage 6.598984771573605% ⚠️
Complexity 2 violations ⚠️
Coupling 0 gaps
Blast Radius 0 modules, 0 files
Index indexed (0s) 💾
📊 Complexity · 2 violations
File Cyclomatic Cognitive
internal/lip/subscribe.go 11 ⚠️ 24
internal/query/lip_health_test.go 11 ⚠️ 32
💡 Quick wins · 10 suggestions
📚 Stale docs · 197 broken references

Generated by CKB · Run details

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 15, 2026

Codecov Report

❌ Patch coverage is 65.90909% with 45 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
internal/lip/subscribe.go 61.4% 29 Missing and 15 partials ⚠️
internal/query/lip_health.go 93.3% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##           develop    #210    +/-   ##
========================================
  Coverage     43.2%   43.3%            
========================================
  Files          526     527     +1     
  Lines        81200   81317   +117     
========================================
+ Hits         35114   35242   +128     
+ Misses       43622   43604    -18     
- Partials      2464    2471     +7     
Flag Coverage Δ
unit 43.3% <65.9%> (+<0.1%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

📢 Thoughts on this report? Let us know!

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Had a package-level init() that printed cartographer version on import
under the cartographer build tag — not a test, and leaked output into
unrelated test runs when the tag was enabled.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 15, 2026

CKB Review: ✅ PASS — 87/100

4 files (+37 changes) · 3 modules · go

Changes 4 files across 3 modules (go). No blocking issues found.

Check Status Detail
hotspots ℹ️ INFO 3 hotspot file(s) touched
blast-radius ℹ️ INFO No symbols with callers in changes
test-gaps ℹ️ INFO 16 untested function(s) in changed files (showing top 10)
format-consistency ✅ PASS No format consistency issues
comment-drift ✅ PASS No comment/code drift detected
bug-patterns ✅ PASS 3 new bug pattern(s) (7 pre-existing filtered) (all on unchanged lines)
unwired ✅ PASS All exported symbols are reachable from entrypoints
dead-code ✅ PASS No dead code in changed files
breaking ✅ PASS No breaking API changes
risk ✅ PASS Risk score: 0.30 (low)
health ✅ PASS No significant health changes
coupling ✅ PASS No missing co-change files
secrets ✅ PASS No secrets detected
tests ✅ PASS 1 test(s) cover the changes
complexity ✅ PASS No significant complexity increase
layers ⚪ SKIP Cartographer not compiled in this build
arch-health ⚪ SKIP Cartographer not compiled in this build
Change Breakdown
Category Files Review Priority
churn 3 🔴 Stability concern
config 1 🟢 Quick check
Code Health

Estimated review: ~26min (moderate)

Reviewers: lisa.welsch1985 (100%) · talantyyr (50%) · lisa (75%)

@SimplyLiz SimplyLiz merged commit 645d3ac into develop Apr 15, 2026
8 of 9 checks passed
@SimplyLiz SimplyLiz deleted the feat/lip-push-subscribe branch April 15, 2026 12:14
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