Skip to content

Field Guide

Search API (Hybrid)

Search API (Hybrid) ​

Coleo exposes two search surfaces:

  1. General hybrid search — SQLite FTS (keyword) + Qdrant (semantic) over tasks, bugs, arms, and indexed docs.
  2. Status history search — Qdrant semantic search over arm status reports / completions with keyword boost and filters.

POST /api/search

json
{
  "query": "authentication issues",
  "types": ["task", "bug"],
  "limit": 20,
  "offset": 0,
  "minScore": 0.1,
  "keywordWeight": 0.5,
  "semanticWeight": 0.5,
  "filters": { "priority": "high" }
}

Response includes per-result keywordScore, semanticScore, and combined score.
If Qdrant/embeddings fail, search degrades to keyword-only (semanticUsed: false).

Related:

MethodPathPurpose
GET/api/search/suggestions?q=Title suggestions
POST/api/search/indexUpsert document into the project's Qdrant search-index-<projectKey> collection

Implementation: src/api/routes/search.ts
Tests: src/api/routes/__tests__/search.test.ts

POST /api/status-history/search

json
{
  "query": "problems with database migrations",
  "filters": {
    "arm_ids": ["arm-alpha"],
    "event_types": ["status_report", "task_completion"],
    "from": "2026-07-01T00:00:00Z",
    "to": "2026-07-10T23:59:59Z",
    "task_id": "phase28g-d4c3d1",
    "classification": "development"
  },
  "limit": 20,
  "keywordWeight": 0.35,
  "semanticWeight": 0.65,
  "include_context": true
}

Response:

json
{
  "results": [
    {
      "event": { "id": "...", "type": "status_report", "title": "...", "content": "..." },
      "score": 0.84,
      "keywordScore": 0.66,
      "semanticScore": 0.91,
      "highlights": ["... migration ..."]
    }
  ],
  "total": 1,
  "query": "problems with database migrations",
  "semanticUsed": true,
  "query_time_ms": 42
}
MethodPathPurpose
GET/api/status-history/stats?period=weekCollection health / point count
GET/api/status-history/by-arm/:armIdFiltered list for one arm
POST/api/status-history/indexManual / backfill index

Implementation: src/api/routes/status-history.ts
Pipeline: src/vector/indexing-pipeline.ts
Collection: status-history (see STATUS_HISTORY_CONFIG)

Weights (hybrid ranking) ​

Combined score:

score = keywordScore * keywordWeight_norm + semanticScore * semanticWeight_norm

Weights are normalized to sum to 1. Defaults:

  • General search: 0.5 / 0.5
  • Status history: 0.35 keyword / 0.65 semantic

Set semanticWeight: 0 for pure keyword; keywordWeight: 0 for pure semantic.

Verification ​

bash
bun test src/api/routes/__tests__/search.test.ts
bun test src/api/routes/__tests__/status-history.test.ts

Live Qdrant + embeddings (optional):

bash
docker compose up -d qdrant
bun run test:qdrant
bun run test:embedding

Retention policy ​

Status-history points in Qdrant are purged by event type:

TypeDefaultEnv override
task_completion, task_created, discovery, bug_reportforeverCOLEO_STATUS_HISTORY_RETENTION_<TYPE>=forever
status_report, task_updated90 dayse.g. COLEO_STATUS_HISTORY_RETENTION_STATUS_REPORT=60
arm_event (heartbeats-like)7 daysCOLEO_STATUS_HISTORY_RETENTION_ARM_EVENT=7
bash
# Dry-run plan
bun run retention:status-history -- --dry-run

# Apply deletes in Qdrant
bun run retention:status-history

Implementation: src/vector/retention.ts, src/scripts/status-history-retention.ts

Backfill existing status reports ​

Import rows from SQLite status_reports into the project's Qdrant status-history-<projectKey> collection (embeds via configured embedding provider):

bash
# Preview
bun run backfill:status-history -- --dry-run --limit 20

# Apply
bun run backfill:status-history

# Another project (the DB must match that project's Coleo directory)
COLEO_PROJECT_DIR=/path/to/project COLEO_DIR=/path/to/project/.coleo bun run backfill:status-history

Ids are deterministic (status-report-<reportId>) so re-runs upsert safely.

Note: CLI coleo status-reports backfill imports .project/status-*.md into SQLite. bun run backfill:status-history indexes SQLite → Qdrant.

MCP tools (brain/arms) ​

Registered on the Coleo MCP server (src/mcp/server.ts):

ToolBackend
searchPOST /api/search — hybrid keyword + semantic over tasks/bugs/arms/index
search_status_historyPOST /api/status-history/search — hybrid over status history collection

Example arm call shape (status history):

json
{
  "query": "previous attempts at database migration",
  "filters": {
    "arm_ids": ["arm-alpha"],
    "event_types": ["status_report", "task_completion"],
    "days_back": 30
  },
  "limit": 10
}

Dependencies ​