| name | add-rerank-preset |
| description | Named ranking strategy combining derived signals with weights + overlay mask, exposed as enum option to MCP tools. Triggers on "new tech-debt preset", "create hotspot detector", "security-audit ranking", "rank by ownership and churn". NOT for adding single signal — use add-derived-signal for that. |
Add Rerank Preset
New rerank preset defining scoring weights for search result ranking.
Step 1: Choose trajectory
- Git trajectory (
traj-git-presets): presets using git-derived signals
(techDebt, hotspots, codeReview, etc.)
- Static trajectory (
domains/trajectory/static/rerank/presets/): presets
using structural signals (relevance, decomposition)
- Explore domain (
explore-presets): composite presets combining signals
from multiple trajectories
Step 2: Create the preset file
Create <preset-name>.ts in appropriate presets directory.
Template:
import type { ScoringWeights } from "../../../../../contracts/types/provider.js";
import type {
OverlayMask,
RerankPreset,
} from "../../../../../contracts/types/reranker.js";
export class MyPreset implements RerankPreset {
readonly name = "myPreset";
readonly description = "What this preset optimizes for";
readonly tools = ["semantic_search", "hybrid_search", "rank_chunks"];
readonly weights: ScoringWeights = {
similarity: 0.3,
};
readonly overlayMask: OverlayMask = {
derived: ["signalA", "signalB"],
file: ["rawField1", "rawField2"],
};
}
Step 3: Key design decisions
name: lowercase camelCase, unique across all presets
tools: which MCP tools support preset. Usually all three, but
rank_chunks only makes sense if preset doesn't rely on similarity
weights: keys must match DerivedSignalDescriptor.name values. Negative
weights penalize (e.g., blockPenalty: -0.05). Weights don't need to sum to 1
— relative.
overlayMask: curates which signals appear in ranking overlay results.
derived = derived signal names, file/chunk = raw payload field names.
groupBy: optional, rank_chunks only. Groups results by payload field
(e.g., "parentName" to group by class).
Step 4: Register in barrel
Edit index.ts in same directory:
- Import:
import { MyPreset } from "./my-preset.js";
- Export:
export { MyPreset } from "./my-preset.js";
- Add instance to array:
- Git:
GIT_PRESETS
- Static:
STATIC_PRESETS
No other registration — TrajectoryRegistry.getAllPresets() collects presets
automatically. SchemaBuilder generates enum for MCP tools.
Step 5: Update documentation
Update with new preset:
CLAUDE.md global → tea-rags section → rerank presets tables
- Project
CLAUDE.md if it changes available rerank options
Step 6: Write tests
Create tests/core/domains/trajectory/{domain}/rerank/presets/<name>.test.ts or
add to existing presets test file.
Minimal test:
import { MyPreset } from "<path>";
import { describe, expect, it } from "vitest";
describe("MyPreset", () => {
const preset = new MyPreset();
it("has valid structure", () => {
expect(preset.name).toBe("myPreset");
expect(preset.tools).toContain("semantic_search");
expect(Object.keys(preset.weights).length).toBeGreaterThan(0);
});
it("overlay mask references valid signals", () => {
for (const key of Object.keys(preset.weights)) {
expect(typeof preset.weights[key]).toBe("number");
}
});
});
Step 7: Verify
npx tsc --noEmit
npx vitest run tests/core/domains/trajectory/
Registration chain (automatic)
Preset class → barrel index.ts → {DOMAIN}_PRESETS array
→ Trajectory.presets → TrajectoryRegistry.getAllPresets()
→ createComposition() → Reranker(resolvedPresets)
→ SchemaBuilder.buildPresetSchema(tool) → MCP tool enum