Skip to content

fix(kilo-mcp): watch router schema inputs and prune stale vectors - #8603

Merged
iscekic merged 1 commit into
mainfrom
fix/mcp-catalog-coverage
Oct 22, 2026
Merged

iscekic merged 1 commit into
mainfrom
fix/mcp-catalog-coverage

Conversation

@iscekic

@iscekic iscekic commented Oct 22, 2026

Copy link
Copy Markdown
Collaborator

What

Closes two gates that let the kilo-mcp catalog and its Vectorize index fall behind the code.

  1. Change detection missed schema inputs. A router .input() schema can be built from an import: relative schemas from services/cloud-agent-next/src/shared/, and schemas or limits from @kilocode/app-shared, cloud-agent-profile, cloud-agent-sdk, kiloclaw-instance-tiers, kiloclaw-secret-catalog, organization-entitlement and session-ingest-contracts. Those paths matched neither the catalog workflow's detection pattern nor ci.yml's kilocode_backend filter, so a schema-only change reached main with no catalog regeneration and no Vectorize upsert.

  2. No prune. embed-catalog.ts only upserted, so a removed or renamed procedure kept its vector id. The search drops ids that are absent from the catalog, so no bad call reached an agent, but stale ids competed for the kNN slots.

How

  • Both detection steps now match those workspaces.
  • scripts/kilo-mcp-catalog.test.mjs derives the workspace set from the router sources' imports and fails when a workspace is neither in the detection pattern nor covered by web-test's byte-for-byte catalog test. The same test asserts the PR and merge patterns stay identical, and a mutation test proves the derived check bites.
  • After the upsert, the script lists the index and deletes every vector whose procedure path left the catalog (delete_by_ids, 100 ids per request, paginated list). An empty catalog prunes nothing, so a bad artifact cannot empty the index.

Verification

  • node --test scripts/kilo-mcp-catalog.test.mjs: all pass, including the derived coverage check.
  • vitest run src/embed-catalog-script.test.ts: prune covers deletion, cursor paging, the in-sync no-op, the empty-catalog skip and the batch size.
  • End-to-end: the real CLI ran against a local fake Cloudflare API with the committed catalog, upserted every row, then listed the index and issued one delete_by_ids for exactly the two ids the catalog lacks.
  • Proof of the original gap: changing one constant in services/cloud-agent-next/src/shared/preview-port.ts made dump.ts --check report two stale rows, with no CI job watching that file.

A router input schema can come from an import: zod schemas from
services/cloud-agent-next/src/shared, and schemas or limits from
@kilocode/app-shared, cloud-agent-profile, cloud-agent-sdk,
kiloclaw-instance-tiers, kiloclaw-secret-catalog, organization-entitlement
and session-ingest-contracts. None of those paths matched the catalog
workflow's change detection or ci.yml's kilocode_backend filter, so a
schema-only change reached main with no catalog regeneration and no
Vectorize upsert. Changing PREVIEW_PORT_MIN alone rewrites inputSchema in
two catalog rows.

- Add those workspaces to both change-detection patterns.
- Derive the workspace set in scripts/kilo-mcp-catalog.test.mjs from the
  router sources' imports and fail when a workspace is neither in the
  pattern nor covered by web-test's byte-for-byte catalog test. The test
  also asserts the PR and merge patterns stay identical.
- Prune: after the upsert, list the index and delete every vector whose
  procedure path left the catalog (delete_by_ids, 100 ids per request). An
  empty catalog prunes nothing, so a bad artifact cannot empty the index.
@kilo-code-bot

kilo-code-bot Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

Reviewed the widened catalog change-detection patterns, the derived coverage test, and the new stale-vector prune against the current router imports, workflow wiring, and catalog semantics; the change is consistent and fails safe on the paths I could verify.

Assumptions:

  • [INFERENCE] The prune relies on the Cloudflare Vectorize v2 list response fields (vectors[].id, isTruncated, nextCursor) and on delete_by_ids accepting { ids } with up to 100 ids. The PR's end-to-end proof used a local fake Cloudflare API, so the real REST contract and count cap could not be exercised here; a wrong field name would fail safe (empty page / early stop, never an over-delete), but a wrong delete_by_ids shape would fail the merge job after the upsert.
  • [INFERENCE] The coverage invariant is derived only from direct imports of files under apps/web/src/routers and apps/web/src/scripts/mcp-catalog. I traced the transitive workspace imports of the newly watched packages (app-shared, cloud-agent-profile, cloud-agent-sdk, kiloclaw-instance-tiers, kiloclaw-secret-catalog, organization-entitlement, session-ingest-contracts) and they resolve to the watched patterns or to packages/db, packages/encryption, packages/worker-utils, which kilocode_backend already routes to web-test's byte-for-byte catalog test. Workspace package.json/config files under the newly watched packages are not matched by the .../src/ pattern, which is acceptable today because resolution changes that alter the catalog also touch src/ or the lockfile.
  • Verified no PR-triggered step can reach Vectorize or the embed script, the PR and merge grep patterns are byte-identical, the empty-catalog guard prevents an empty artifact from emptying the production index, and the merge drift check still runs before the upsert so the prune only sees a catalog that matches the dump output.
Files Reviewed (4 files)
  • .github/workflows/kilo-mcp-catalog.yml
  • scripts/kilo-mcp-catalog.test.mjs
  • services/kilo-mcp/scripts/embed-catalog.ts
  • services/kilo-mcp/src/embed-catalog-script.test.ts

Reviewed by deepseek-flash-latest · Input: 196.9K · Output: 34.2K · Cached: 3M

Review guidance: REVIEW.md from base branch main

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.

2 participants