fix(fb-34): align next_cursor semantics with docs (PR #125 round 2)

Previous round-1 fix dropped the speculative cursor branch on
the truncated path, leaving a contradiction with the docs:
- snippet-only shrunk → cursor emitted (returned == k_effective)
- k-popped → cursor null (returned < k_effective)
But docs promised the opposite.

R2 resolution: emit cursor whenever more hits may be reachable
(either retriever filled the page OR budget popped hits — the
popped ones remain fetchable from offset+returned). Drop the
artificial "widen vs paginate" copy; truncated and next_cursor
are now independent signals — caller may do either or both.

Updates: app.rs::search_with_opts logic + SearchResponse doc +
schema description + SKILL.md two bullets + max_tokens=0 test
asserts cursor IS emitted on k-pop case.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
th-kim0823
2026-05-09 21:07:04 +09:00
parent f485608108
commit e084b306e5
4 changed files with 48 additions and 40 deletions

View File

@@ -152,4 +152,10 @@ fn max_tokens_zero_returns_one_hit_truncated() {
.unwrap();
assert_eq!(resp.hits.len(), 1, "max_tokens=0 collapses to 1-hit floor");
assert!(resp.truncated);
// p9-fb-34 R2: cursor IS emitted on k-pop case so the popped
// hits remain reachable.
assert!(
resp.next_cursor.is_some(),
"k-pop truncation must still emit next_cursor; popped hits at offset+returned"
);
}