---
title: "Semantic Search and Context: Finding Hidden Code Dependencies"
description: Combine vector search with one-hop graph relation expansion in code refactoring, keeping similarity scores, candidates, and sources verifiable on disk.
image: "https://zengliangyi.com/og/blog/en/semantic-search-relation-context.png"
---

When refactoring an authentication module, search may find notes about JWT directly, while relation expansion adds context about permissions, refresh jobs, or key management. Being expanded into the result does not mean the current code depends on that note. This constructed scenario shows how to turn retrieval clues into a verification list.

The implementation basis is the [embedding search](https://github.com/ZengLiangYi/ChatCrystal/blob/764276814e5c5a33ecbfeae63754f74b9261a3a8/server/src/services/embedding.ts) and [relation service](https://github.com/ZengLiangYi/ChatCrystal/blob/764276814e5c5a33ecbfeae63754f74b9261a3a8/server/src/services/relations.ts) at fixed commit [`7642768`](https://github.com/ZengLiangYi/ChatCrystal/tree/764276814e5c5a33ecbfeae63754f74b9261a3a8). The authentication-refactoring scenario illustrates the method; it is not a measured result.

## Establish a direct-hit baseline

Start with a known target query, then repeat with a paraphrase and a no-answer query:



```bash
curl   --get   http://localhost:3721/api/search   \  
    --data-urlencode   'q=JWT authentication token validation'   \  
    --data-urlencode   'limit=5'
```



The HTTP `data` array contains `note_id`, `conversation_id`, title, project, score, tags, and `via_relation`. Direct results have no relation marker. Scores already include application candidate, term, and deduplication rules; they are not probabilities or measured dependency strength. Follow each ID to the note and original conversation and record whether it actually concerns the current module.

## Turn on one-hop relation expansion

Use `expand=true`:



```bash
curl   --get   http://localhost:3721/api/search   \  
    --data-urlencode   'q=JWT authentication token validation'   \  
    --data-urlencode   'limit=5'   \  
    --data-urlencode   'expand=true'
```



The current implementation reads one-hop relations from direct hits and expands only edges with confidence at least `0.5`. Linked scores use `direct score × 0.7 × confidence`. Notes already in the result set are skipped, and expansion can make the total exceed the direct-query limit. It is not multihop traversal and does not find the strongest path for every target.

## Turn relation types into investigation questions

Search expands relations in both directions, while `via_relation` returns only the type. Check source and target in the relation details first, then use the type to ask questions rather than state conclusions:

- `DEPENDS_ON`: find an actual call, shared field, or lifecycle constraint in current code and configuration.

- `LEADS_TO`: check whether the downstream behavior is triggered by this step instead of inferring causality from similar topics.

- `RESOLVED_BY`: confirm that the old fix’s assumptions still hold in the current version.

- `REFERENCES` or `SIMILAR_TO`: use as reading entrances, not runtime dependency claims.

The relation service considers at most 20 candidates, falls back to recent notes when semantic candidates are unavailable, and filters model output by candidate ID, confidence, and a maximum of five. Graph coverage is therefore bounded by candidate selection and model output; it is not a complete static dependency graph.

## Turn hidden dependencies into verification actions

For each indirect candidate, record source evidence, a current code location, and a verification command. Run a test or minimal reproduction and compare behavior before and after the refactor. Recheck assumptions when versions, deployment, or projects differ. Keep no-answer queries and false matches; they reveal retrieval boundaries.

Relation expansion broadens reading, but it does not replace IDE references, code search, tests, or review. For task-memory recall, follow the [Claude Code memory workflow](/en/blog/claude-code-memory-workflow); for relation and projection endpoints, see [note relations and graph views](/en/blog/note-relations-and-graph).

Share:

##  Related Posts

[##  Graph-Assisted Refactoring: Turning Relational Clues into Checks

Turn note and code graph relations into verifiable fault checks: trace candidate edges, check dependencies, and avoid treating links as proof.          曾亮懿       October 7, 2026      5 min read

#ChatCrystal

#Knowledge graph

#Testing](/en/blog/graph-assisted-refactoring)    [##  Note Relations and Graph Views: Discover, Project, and Verify

Trace ChatCrystal relation APIs, candidate discovery, and graph projections, keeping generated edges and tag co-occurrence within verified boundaries.          曾亮懿       October 3, 2026      3 min read

#ChatCrystal

#Knowledge graph

#Relations](/en/blog/note-relations-and-graph)    [##  Recover a debugging solution: retrieve, read, then verify reuse

Use a constructed debugging scenario to check notes, vectors, and search results, then compare the original conversation with the current project.          曾亮懿       October 3, 2026      4 min read

#ChatCrystal

#Semantic search

#Debugging](/en/blog/recover-debugging-notes)

##  From writing to code

Explore ChatCrystal, developer tools and daily learning notes on my GitHub. Questions about the implementation are welcome.

[Visit my GitHub](https://github.com/ZengLiangYi)

```json
{
  "@context": "https://schema.org",
  "@type": "WebSite",
  "name": "ZengLiangYi Blog",
  "alternateName": [
    "Zeng Liangyi",
    "ZengLiangYi",
    "zengliangyi.com"
  ],
  "url": "https://zengliangyi.com",
  "description": "曾亮懿的个人网站。记录 AI Native 探索、开发者工具与全栈产品实践。"
}
{
  "@context": "https://schema.org",
  "@type": "BlogPosting",
  "headline": "Semantic Search and Context: Finding Hidden Code Dependencies",
  "description": "Combine vector search with one-hop graph relation expansion in code refactoring, keeping similarity scores, candidates, and sources verifiable on disk.",
  "url": "https://zengliangyi.com/en/blog/semantic-search-relation-context/",
  "image": "https://zengliangyi.com/images/blog/semantic-search-relation-context.svg",
  "datePublished": "2026-10-03T00:00:00.000Z",
  "dateModified": "2026-10-23T00:00:00.000Z",
  "author": {
    "@type": "Person",
    "name": "曾亮懿",
    "url": "https://zengliangyi.com/en/about"
  },
  "publisher": {
    "@type": "Organization",
    "name": "ZengLiangYi Blog",
    "logo": {
      "@type": "ImageObject",
      "url": "https://zengliangyi.com/favicon-96x96.png"
    }
  },
  "mainEntityOfPage": {
    "@type": "WebPage",
    "@id": "https://zengliangyi.com/en/blog/semantic-search-relation-context/"
  }
}
{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    {
      "@type": "ListItem",
      "position": 1,
      "name": "Home",
      "item": "https://zengliangyi.com/en"
    },
    {
      "@type": "ListItem",
      "position": 2,
      "name": "Blog",
      "item": "https://zengliangyi.com/en/blog"
    },
    {
      "@type": "ListItem",
      "position": 3,
      "name": "Semantic Search and Context: Finding Hidden Code Dependencies",
      "item": "https://zengliangyi.com/en/blog/semantic-search-relation-context/"
    }
  ]
}
```
