mirror of
https://github.com/garrytan/gbrain.git
synced 2026-07-27 22:15:33 +00:00
* feat(search): intent-aware adaptive return-sizing (default-off) New opt-in retrieval feature: trim the ranked result set to an intent-driven cap (entity -> tight, else -> recall-preserving) instead of always returning top-K. Pure module src/core/search/return-policy.ts (resolve + apply + config-read + at-least-minKeep failsafe); wired into hybridSearch after rerank, before slice, offset===0 only; decision stamped into HybridSearchMeta.adaptive_return; cache skipped when on (KNOBS_HASH fold is a follow-up). SearchOpts.adaptiveReturn per-call override. Default OFF — existing search behavior byte-identical. Mechanism is an intent cap, not a score-cliff detector (PrecisionMemBench data showed the cliff carries no signal). 19 unit tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: bump version and changelog (v0.41.30.0) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: document adaptive return-sizing module in CLAUDE.md (v0.41.30.0) Add a Key Files entry for src/core/search/return-policy.ts (intent-aware adaptive return-sizing, default OFF) covering its exports, the four search.adaptive_return* config knobs, the hybrid.ts wiring (post-rerank, pre-slice, offset===0 only), and the cache-skip behavior. Regenerate llms-full.txt to match. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(query): agent-facing adaptive_return param on the query op Expose adaptive_return (boolean) on the query MCP/CLI op so the AGENT — not the human config knob — decides per query whether to return a tight, intent-sized set. The param description teaches WHEN (single-answer questions on; breadth off; limit:1 for a hard single-answer cap), matching the salience/recency 'YOU (the agent) decide' pattern. Threaded into hybridSearchCached. End users never touch config; their agent serves them per query. Pinned by test/search/query-op-adaptive-return.test.ts. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: re-version to v0.41.33.0 + document agent surface Re-version 0.41.30.0 -> 0.41.33.0 (VERSION/package.json/CHANGELOG/TODOS/CLAUDE.md). CHANGELOG + CLAUDE.md now document the agent-facing query-op adaptive_return param + when-to-use guidance. llms regenerated (build-llms test green). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(core): harden fence-strip + config parsing against non-string input stripTakesFence/stripFactsFence crashed with "undefined is not an object" when a read op returned a page with no compiled_truth (e.g. metadata-only rows). The get_page untrusted-reader path calls both on page.compiled_truth, which can be undefined. Guard both to no-op when body is not a string. loadSearchModeConfig.safeGet trusted engine.getConfig to honor its string|null contract; a non-string value (array/boolean) reached loadOverridesFromConfig and crashed on ce.toLowerCase(). Treat any non-string config value as "not set" so it falls through to the mode-bundle default, matching missing-key behavior. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
34 lines
1.3 KiB
TypeScript
34 lines
1.3 KiB
TypeScript
/**
|
|
* Pins the agent-facing surface for adaptive return-sizing on the `query` op.
|
|
*
|
|
* The feature is useless to an agent unless the MCP/op tool schema exposes the
|
|
* param AND its description teaches WHEN to reach for it. This test guards both
|
|
* so a future refactor can't silently drop the agent instruction.
|
|
*/
|
|
|
|
import { describe, expect, test } from 'bun:test';
|
|
import { operationsByName } from '../../src/core/operations.ts';
|
|
|
|
describe('query op — adaptive_return agent surface', () => {
|
|
const query = operationsByName['query'];
|
|
|
|
test('query op exists', () => {
|
|
expect(query).toBeDefined();
|
|
});
|
|
|
|
test('adaptive_return is a boolean param on query', () => {
|
|
const param = query.params?.adaptive_return as { type?: string; description?: string } | undefined;
|
|
expect(param).toBeDefined();
|
|
expect(param?.type).toBe('boolean');
|
|
});
|
|
|
|
test('description teaches the agent WHEN to use it (single-answer vs breadth)', () => {
|
|
const desc = (query.params?.adaptive_return as { description?: string })?.description ?? '';
|
|
// Must instruct the agent on both directions of the decision.
|
|
expect(desc.toLowerCase()).toContain('true when');
|
|
expect(desc.toLowerCase()).toContain('breadth');
|
|
// Must reassure the safety contract so the agent isn't afraid to use it.
|
|
expect(desc.toLowerCase()).toContain('never returns empty');
|
|
});
|
|
});
|