From d350bc5ad988ec4b3b7de661df7d25089c130248 Mon Sep 17 00:00:00 2001 From: Aofei Sheng Date: Thu, 9 Jul 2026 17:45:10 +0800 Subject: [PATCH] docs: add Code Search product architecture Document the Code Search product and system boundary for generic project code search. Cover searchable corpus, source identity, file selection, text and structural search semantics, indexing lifecycle, authorization constraints, admin experience, and ecosystem references. Fixes #3331 Signed-off-by: Aofei Sheng --- docs/product/code-search.zh.md | 342 +++++++++++++++++++++++++++++++++ 1 file changed, 342 insertions(+) create mode 100644 docs/product/code-search.zh.md diff --git a/docs/product/code-search.zh.md b/docs/product/code-search.zh.md new file mode 100644 index 000000000..701e3a005 --- /dev/null +++ b/docs/product/code-search.zh.md @@ -0,0 +1,342 @@ +# Code Search + +Code Search 是 XBuilder 的项目代码搜索能力。它面向 XBuilder 项目中的源码和选定项目元数据,提供可解释、可定位、可审计的文本搜索和结构化搜索能力。 + +本文档定义 Code Search 的产品与系统边界。它描述目标状态和关键语义,不定义最终数据库 schema、完整 OpenAPI 契约或具体实现任务。 + +## 背景与目标 + +XBuilder 项目代码目前保存在项目文件集合中。`Project.files` 和 `ProjectRelease.files` 都是 `path -> universal URL` 形式的文件映射,文件内容可能以内联 `data:` URL 保存,也可能通过 `kodo://` 等对象存储地址引用。现有 `/projects` 的 `keyword` 参数只搜索项目展示名或名称模式,不搜索项目源码。 + +XBuilder 需要一套通用的项目代码搜索能力,用于在用户项目中查找具体源码、结构化代码形态、可解析的匹配位置和可聚合的结果。第一个预期客户端是 XBuilder 管理台,但 Code Search 本身不是某个 admin 页面专用功能,也不应该被建模为某个框架的专用报告。 + +目标包括: + +- 支持跨 XBuilder 项目源搜索源码和选定项目元数据 +- 支持代码导向的文本搜索,并返回具体匹配位置和片段 +- 支持语法级结构化搜索,并返回匹配范围、captures 和诊断信息 +- 将文本搜索、结构化搜索和未来的语义过滤分层建模 +- 明确 latest project content 和 release snapshot 的来源身份 +- 明确可搜索文件、文件角色、语言检测和排除策略 +- 通过索引提供稳定、可分页、可解释的搜索结果 +- 暴露索引覆盖、陈旧、失败和部分结果状态 +- 支持面向 admin 的首个使用界面,同时保持后端能力通用 +- 保护私有项目源码和派生索引中的用户内容 +- 为 `tree-sitter-xgo`、XGo 语义分析和后续代码迁移能力留下演进空间 + +非目标包括: + +- 不定义 spx 专用 API 使用统计报告 +- 不把后端 API 做成 spx 或任意单个 XGo classfile framework 专用接口 +- 不把 Code Search 等同于社区项目搜索或 `/projects` keyword 搜索 +- 不提供自然语言、embedding 或 LLM 语义相似搜索作为权威匹配机制 +- 不要求第一阶段支持 resolved symbol 级精确匹配 +- 不要求第一阶段支持完整 ast-grep 或 Semgrep 兼容 +- 不把 lint、severity、message、fix、rule pack 或 codemod 作为第一阶段搜索契约 +- 不在默认结果中暴露完整源码、原始 file collection、universal URL 或 signed URL +- 不让搜索引擎、对象存储或外部索引后端成为绕过后端授权的读取路径 + +## 核心概念 + +| 概念 | 含义 | +| - | - | +| Code Search | XBuilder 的项目代码搜索能力,覆盖文本搜索、语法级结构化搜索和未来的语义过滤 | +| 项目源 project source | 可被搜索的项目代码来源,如 latest project content 或 release snapshot | +| latest project content | `Project.files` 表示的当前项目文件集合,是可变来源 | +| release snapshot | `ProjectRelease.files` 表示的项目发布快照,是发布时复制出的文件集合 | +| source identity | 标识一次匹配来自哪个项目源、哪个文件、哪个内容版本和哪个索引版本的信息 | +| file collection | `path -> universal URL` 形式的项目文件集合 | +| searchable file | 被 Code Search 纳入索引和查询的文件 | +| file role | 文件在 XBuilder 项目模型中的角色,如 spx project code、spx sprite code、project config、sprite config、asset metadata、generated internal metadata 或 binary asset | +| text search | 面向源码文本的字面量、标识符、字符串、路径相关或正则搜索 | +| structural matching | 基于语法树的结构化匹配,用代码形态或语法节点描述要查找的源代码结构 | +| semantic filtering | 在文本搜索和结构化匹配候选结果上,使用 XGo 语义信息确认 resolved symbol、类型、接收者或 classfile 语义 | +| capture | 结构化匹配中命名的子树或子片段,带有源代码范围和文本 | +| coverage | 一次搜索实际覆盖了哪些项目源、哪些文件、哪些语言和哪些索引状态 | +| search index | 从项目源派生出的可搜索状态,不是项目源码的权威存储 | +| reindex | 因源内容变化、文件选择策略变化、解析器变化、matcher 变化或索引格式变化而重新生成派生索引 | + +## 能力边界 + +Code Search 的后端能力应该保持通用。它接收来源范围、项目过滤、文件过滤、文本查询、结构化 matcher 和执行控制,返回匹配结果、诊断、覆盖信息和可选聚合摘要。具体客户端可以在此基础上组织出不同工作流,例如 admin 排查、项目迁移评估、框架兼容性审查或未来的代码迁移辅助。 + +Code Search 不应把某个工作流固化为后端契约。即使第一批实际需求来自维护 spx 这类 XBuilder 支持的 XGo classfile framework,后端 API 也不应该出现只能表达某个 framework 报告的结构。framework 相关能力应作为文件角色、语言、结构化 matcher 或未来语义过滤的组合出现。 + +Code Search 与社区项目搜索不同。社区项目搜索面向作品发现,查询对象是项目展示名、作者、可见性、排序和社区行为。Code Search 查询对象是项目源内的源码和选定项目元数据,结果需要具体文件、范围、snippet、captures、诊断和覆盖状态。 + +Code Search 与 XGo 编译器、XGo LSP 和 Tree-sitter grammar 的边界也需要清晰。Code Search 负责编排索引、检索、匹配、授权、结果和可观测状态。XGo 编译器或语言服务负责语义事实。`tree-sitter-xgo` 如果存在,负责提供 XGo 源码的 concrete syntax tree 和 Tree-sitter 生态兼容层。 + +## 系统边界 + +Code Search 处在 XBuilder 项目模型、项目文件存储、后台索引、查询 API 和客户端体验之间。 + +XBuilder 项目和发布仍然是源码来源的权威。`Project.files` 表示当前项目文件集合,`ProjectRelease.files` 表示发布快照文件集合。Code Search 索引只是这些来源的派生数据。 + +Code Search API 是查询和管理派生索引的权威入口。它负责授权、来源范围、过滤、matcher 校验、结果形态、覆盖信息、审计边界和完整源码读取边界。外部索引后端、对象存储、解析器或 matcher 都不应该成为客户端直接依赖的公共契约。 + +后台索引器负责从项目源读取 file collection,解析 universal URL,识别可搜索文件,提取可索引文本和必要元数据,运行语法解析或语义分析,并写入可搜索状态。索引器可以使用后台任务执行,但任务执行状态不应成为项目源是否可搜索的唯一权威。 + +搜索索引负责加速检索,不负责最终授权判断。PostgreSQL、`pg_trgm`、Zoekt、Tantivy 或 OpenSearch 都可以作为实现候选,但 API 不应暴露具体索引引擎、引擎查询语言或引擎评分模型。 + +XBuilder 管理台是第一客户端。它应该作为通用 Code Search 能力上的操作界面,而不是把后端能力变成 admin-only 或 spx-only。 + +## 可搜索语料 + +Code Search 的语料来自 XBuilder 项目源。项目源至少包括: + +- latest project content,来自 `Project.files` +- release snapshot,来自 `ProjectRelease.files` + +latest project content 是可变来源,保存项目后可能变化。release snapshot 是发布时复制出的来源,应该按发布快照理解。相同项目、相同路径在 latest project content 和不同 release snapshot 中可能代表不同内容。 + +一次查询必须显式声明或由 API 明确默认 source scope。结果也必须带回 source identity,不能只返回 owner、project 和 file path。否则调用方无法判断命中来自当前项目内容、某个发布快照,还是某个已经被后续保存覆盖的旧内容。 + +文件内容解析必须通过 universal URL 处理。一个 `data:` URL 可能直接包含文本源码或 JSON 元数据,一个 `kodo://` URL 可能指向较大的文本文件或二进制资产。索引器不能把存储 scheme 当成语言检测或文件角色判断依据。 + +对象存储只应该参与索引或重建索引时的内容读取。搜索请求如果已经有足够的索引文本、snippet 和结构化事实,不应该在热路径上反复读取对象存储。 + +## 文件选择与语言检测 + +Code Search 应索引用户相关的源码和选定项目元数据,而不是索引项目文件集合中的所有文件。 + +当前 XBuilder spx 项目的主要代码文件是: + +- `main.spx`,表示 project 或 stage 级代码 +- `.spx`,表示 sprite 级代码 + +这些 `.spx` 文件应作为 XGo 语法处理。spx 是 XGo classfile framework,`main.spx` 是 project classfile,其他 sprite `.spx` 是 work classfile。这个角色影响文件元数据和未来语义分析,但不应该要求独立于 XGo 的另一套语法解析器。 + +现有 Stage 加载逻辑还兼容 `index.spx`、`main.gmx` 和 `index.gmx` 等历史 stage code 路径。是否纳入第一阶段索引是文件选择策略问题。若纳入,应保留原始 file path,并将其识别为 stage code 兼容路径。 + +已知 XBuilder JSON 文件应该按文件角色分类,而不是因为扩展名是 `.json` 就全部当成代码文件: + +- `assets/index.json` 表示项目级配置,如 stage config、zorder、camera、tilemap path 和 runtime settings +- `assets/sprites//index.json` 表示 sprite 配置,如物理设置、碰撞形状、造型、动画和动画绑定 +- sound、tilemap 等资源 JSON 表示资源级元数据,如资源路径、声音元数据、tilemap layers 和 decorators + +这些 JSON 文件可以用于元数据提取、兼容性检查、迁移评估,以及可选的文本搜索或 JSON 结构化搜索。它们不应被当作 XGo 源码,也不应只按扩展名粗暴纳入。 + +生成的内部文件默认不应纳入普通 Code Search,例如 `builder-ai-description.md` 和 `builder-ai-description.hash`。图片、音频、视频等二进制资产也不属于代码语料。 + +索引器应保存明确的检测结果。检测结果至少应表达文件是否被纳入普通搜索、是否可文本搜索、是否可结构化搜索、检测语言、文件角色、使用的 parser 或 grammar,以及解析或检测诊断。 + +语言检测和文件角色判断不属于 Tree-sitter grammar 的职责。`tree-sitter-xgo` 应只负责解析 XGo 源码语法。`main.spx` 是否是 project classfile、某个 `.spx` 是否是 sprite classfile、某个 JSON 是否应索引,都属于 XBuilder 项目模型和文件选择策略。 + +## 搜索语义 + +Code Search 的搜索语义分为三层: + +1. 文本搜索 +2. 语法级结构化搜索 +3. 未来的语义过滤 + +文本搜索用于在源码文本和选定元数据文本中查找字面量、标识符、selector、package path、字符串字面量、注释或 JSON key。它应该是代码导向、确定性、可解释的搜索,不应使用 stemming、synonym expansion、embedding similarity 或自然语言改写。 + +文本搜索中的多词行为必须显式。空白不应该悄悄改变为 phrase search、token search、AND、OR 或 fuzzy matching。第一阶段可以把查询作为一个 literal expression。后续如果支持 term query、phrase query、boolean query 或正则搜索,应作为明确模式。 + +大小写、标识符边界和标点行为也必须显式。`github.com/goplus/spx/v2`、`broadcast`、`Sprite.step`、字符串字面量和 JSON key 这类代码文本不能依赖搜索引擎默认 analyzer 意外决定匹配语义。 + +结构化搜索用于通过代码形态查找源代码结构。它应该匹配语法树中的 node 或 subtree,并返回源代码范围、captures、snippet 和诊断。第一阶段的结构化搜索应保持语法级,不应声称已经理解 resolved symbol、类型、隐式 receiver、framework package lookup 或 classfile lowering。 + +面向人编写的结构化查询可以参考 ast-grep-like pattern。它比原始 Tree-sitter query 更接近代码写法,适合 admin 页面中的查询编辑。第一阶段不需要承诺完整 ast-grep 兼容,除非实现确实使用 ast-grep。一个明确记录的子集是可以接受的,前提是未支持能力必须被校验拒绝,而不是静默忽略。 + +结构化查询的有用子集可以包含: + +- `pattern`,用于代码形态匹配 +- `context` 和 `selector`,用于需要解析上下文的片段 +- metavariables 和 captures +- capture constraints,如 node kind、text regex 和 nested pattern +- 位于 matcher 外部的 source scope、project filter、file filter、language 和 path 过滤 + +Tree-sitter query 仍然是重要的低层参考。它可以描述 node kind、field、capture、anonymous node、wildcard 和 parser error node。它适合内部调试、高级能力或实现层,但作为 admin 首选查询格式会偏语法树细节。 + +语义过滤是结构化候选之后的可选层。它用 XGo 语义信息确认某个 capture 是否解析到特定 package symbol、type、method、field、receiver 或 framework-provided member。语义过滤结果应暴露状态,如 syntax-only、semantic-confirmed、semantic-unavailable、semantic-failed 或 ambiguous。 + +语义过滤不属于第一阶段语法级结构化搜索的必需条件。即使语义层暂不可用,Code Search 也应能返回 syntax-level 匹配,并清楚标识这些结果不是语义精确结果。 + +## `tree-sitter-xgo` 与 XGo 语义 + +如果第一阶段包含语法级结构化搜索,`tree-sitter-xgo` 值得作为 XGo 官方语法工件评估,而不是只作为 XBuilder 后端内部实现细节。 + +Tree-sitter grammar 将语言的 concrete source syntax 暴露给多种工具。它可以支持语法树查询、语法高亮、locals、injections、tags、浏览器侧 Wasm 解析、Tree-sitter 编辑器生态和 ast-grep custom language。对于 Code Search,它可以提供稳定的语法树基础,也可以让 admin 页面获得更好的本地校验和预览体验。 + +基于 XGo classfile 语法,一个 `tree-sitter-xgo` 应足够覆盖语法层。XGo classfile frameworks 共享同一类源代码形态。framework 差异来自文件分类、registry metadata、base class、work class、隐式 receiver 查找、生成方法和 project/work assembly。这些是语义和 lowering 问题,不应拆成每个 framework 一套 grammar。 + +`tree-sitter-xgo` 应覆盖 XGo 和 classfile 的共享源码语法,包括普通 XGo 文件、XGo classfile、省略 package clause 的 classfile、classfile declaration 之前的 imports、top-level statements、field declarations、tags,以及 classfile-only static method declaration,如 `func .Name(...)`。 + +`tree-sitter-xgo` 不应编码 framework-specific 或语义行为。例如它不应判断一个文件是 project classfile 还是 work classfile,不应判断某个 class extension 属于哪个 framework registration,不应判断 base class 或 work class,不应判断某个 identifier 是否通过隐式 receiver 或 framework package lookup 解析,也不应判断某个匹配是否解析到特定 package symbol。 + +XGo 语义分析仍然是语义事实的来源。spx 项目的 `.spx` 文件不是孤立脚本。它们的含义依赖 classfile framework metadata、自动导入、生成成员、project/work 组合和 workspace 文件集合。Code Search 的 resolved symbol 分析应该使用与 XBuilder editor-side language service 一致的项目级上下文,而不是孤立解析某个 `.spx` 文件。 + +## 查询模型与 API 边界 + +Code Search 的 API 不应把文本搜索、结构化 matcher、路径过滤、项目过滤、来源范围和未来语义过滤压缩进一个自由字符串。请求结构应该把这些关注点分开,让校验、授权、索引、执行和 UI 反馈都可解释。 + +请求模型应包含以下逻辑部分: + +- source scope,如 latest project content、release snapshot 或二者组合 +- project filters,如 owner、project identity、project type、visibility、project full name 或 release full name +- file filters,如 path、language、file role、text-searchable status 或 structurally-searchable status +- text query,用于 literal、identifier-oriented、phrase、boolean 或 regex 搜索 +- structural matcher,用于语法级结构化匹配 +- future semantic filters,用于 resolved symbol 或 XGo 语义过滤 +- execution controls,如 result limit、pagination、timeout、partial result policy 和 execution mode + +结构化 matcher 需要独立 validation 能力。调用方应该能在执行宽范围搜索之前校验 pattern、unsupported features、parser availability、language mismatch 和 file role mismatch。校验诊断应该足够让 admin 页面给出快速反馈。 + +执行模式需要明确。简单文本搜索和窄范围结构化搜索可以同步返回分页结果。跨所有用户项目的宽范围结构化搜索可能需要超时、部分结果、异步执行或更严格的过滤要求。API 不应把未覆盖、超时或失败包装成普通空结果页。 + +API 不应暴露底层引擎是否使用 PostgreSQL、Zoekt、Tantivy、OpenSearch、Tree-sitter query 或 ast-grep。公共契约应暴露 Code Search 概念,如 source identity、match range、captures、diagnostics、coverage、counts、grouping 和 freshness。 + +## 结果模型 + +Code Search 的核心结果应该是 match-oriented。一个 result item 表示某个项目源中某个文件里的一个具体匹配,而不是只表示一个项目或一个文件。 + +一个匹配结果应包含: + +- source identity,包括 source kind、project identity 和 release identity +- file path、file role、language 和 parser 或 matcher 信息 +- matched range,包括行列或可映射到源码的范围 +- snippet 和 matched text +- captures,包括 capture name、range 和 text +- match kind,如 text match 或 structural match +- semantic status,如果语义过滤或语义标注参与执行 +- freshness 和 coverage 信息,如 indexed time、source hash、index format version、stale status、parse diagnostics 或 matcher diagnostics + +默认结果不应返回完整 source file、完整 file collection、universal URL 或 signed URL。完整源码读取应该是单独授权的操作,且需要清楚的审计边界。 + +结果需要支持 grouping 和 counts,但 grouping 不应替代核心匹配结果。客户端可能按 project、owner、file、source kind、language、file role、match kind、parser status 或 semantic status 分组。后端可以返回通用 summaries,但不应把某个工作流的聚合方式固化成唯一结果。 + +计数语义必须明确。match count、file count、source count、project count 和 owner count 不是同一个数字。一个项目可以有多个 source,一个 source 可以有多个文件,一个文件可以有多个匹配。release snapshot 是否纳入、是否与 latest project content 去重,也会改变 project count。 + +分页结果中的 totals 必须说明含义。普通 XBuilder list API 的 `ByPage` 使用 exact `total`,但 Code Search 对宽范围结构化查询、部分执行、超时或外部索引后端不一定总能提供完整精确 total。API 应区分 exact、approximate、unavailable 和 incomplete。 + +没有匹配、没有覆盖、索引陈旧、索引失败、结构化 parser 不可用、文件被策略排除,是不同状态。结果和 summary 必须让调用方能区分这些状态。 + +## 索引与维护 + +Code Search 索引是派生数据。项目源码的 source of truth 仍然是 `Project.files` 和 `ProjectRelease.files`。 + +搜索请求应该读取已索引的可搜索状态,而不是在请求路径上扫描所有 project files、解析所有 universal URL 或重建源码索引。项目保存、发布创建和普通用户编辑流程也不应等待解析、匹配或索引更新完成。 + +索引状态应由 Code Search 域拥有。它需要记录哪个 source 被索引、哪个 file collection 或 file content 生成了索引、哪个索引逻辑版本生成了索引,以及当前状态是 current、stale、failed 还是 in progress。 + +索引维护至少包含三类流程: + +1. 初始 backfill,用于既有 latest project sources 和选定 release sources +2. 增量维护,用于 source content 变化、release 创建、删除、rename 或 visibility 变化 +3. 重建索引,用于 file selection policy、language detection、parser、matcher 或 index schema 变化 + +内容变化需要重新索引。metadata-only 变化可能只需要更新 source identity、authorization metadata 或 visibility metadata。parser、matcher 或 file selection policy 变化即使没有源文件变化,也可能要求 reindex。 + +索引必须是幂等且版本感知的。索引结果应绑定 source identity、source content hash 或 version,以及 index format version。如果更新的 source content 或更新的 index format 已经存在,旧任务结果不能覆盖当前可搜索状态。 + +手动 reindex 应作为运维控制存在。它应该触发后台索引工作,而不是在请求内联执行。reindex 可以按单个 project source、owner、project scope、failed records、stale records 或旧 index format version 定位。 + +搜索执行和 reindex 请求是不同操作。搜索请求询问当前可搜索状态中的匹配。reindex 请求要求后端刷新派生数据。搜索应在索引或重建进行中继续可用,并通过 coverage 信息说明哪些 source 当前未索引、陈旧、失败或仍在索引中。 + +## 权限、隐私与审计 + +全局项目代码搜索是对用户创建内容的特权读取路径。它不是普通项目元数据查询。 + +XBuilder 当前项目访问模型包含 owner 和 visibility。公开项目可被非 owner 读取,私有项目通常要求 owner。release snapshot 没有独立 visibility,应跟随所属项目。admin 级 Code Search 如果纳入私有项目,就引入了跨用户读取源码的新路径。 + +权限边界必须显式。能够访问 `/admin/*` 或管理 Account 资源,不应自动获得 Code Search 权限。Code Search 需要独立 capability,或明确映射到某个经过文档定义的 capability。 + +搜索索引与源文件具有相同隐私等级。索引文本、snippet、captures、parse tree 和 extracted facts 都可能包含用户源码或项目元数据。如果使用外部搜索后端,该后端不能成为绕过后端授权和审计的第二读取路径。 + +授权应在搜索执行和结果详情读取时执行,而不只是在建立索引时执行。索引中的 visibility 和 owner metadata 可以用于过滤,但最终权限判断仍应由后端负责。visibility 变化、项目删除和角色变化必须在索引清理完成前也能影响可见性。 + +搜索结果默认不应暴露 raw file collection、universal URL、signed URL 或完整源码。`data:` URL 可以直接包含完整文本,`kodo://` URL 可以指向用户内容。默认结果应返回 source identity、file path、range、snippet、captures 和 diagnostics。 + +Code Search 应写入 admin audit logs。审计记录应避免保存完整源码、完整 snippet、captures、signed URL 或用户内容。适合审计的字段包括 source scope、visibility scope、language、matcher mode、query hash、result count、是否包含 private project content、是否 partial、duration 和 actor。 + +普通用户可见搜索和 privileged admin search 应区分。后端能力可以通用,但实际 searchable corpus 必须来自调用者的 authorization context。普通用户可能只能搜索自己的项目和公开项目,admin workflow 才能在具备 capability 和审计的前提下搜索更广范围。 + +## Admin 体验 + +第一个客户端可以是 XBuilder 管理台页面。该页面应是通用 Code Search 能力上的工具界面,不是 spx 专用报告页面。 + +现有 `/admin/*` 页面是 capability-gated 的操作页面,通常包含 URL-backed filters、pagination、refresh、loading、error states、table/detail navigation 和权限提示。Code Search 管理台页面应沿用这种操作台形态,但查询界面会比普通资源列表更复杂。 + +管理台需要组合结构化请求,而不是只提供一个搜索框。合理控件包括: + +- source scope 选择 +- owner、project、visibility 和 project type 过滤 +- file path、language、file role 和 searchable status 过滤 +- text query 输入和模式选择 +- structural matcher 编辑器 +- validation 按钮或自动校验反馈 +- result limit、timeout 和 partial result 设置 +- grouping 和 summary 展示 + +轻量状态应该写入 URL,例如 filters、source scope、pagination 和 selected mode。长文本或多行结构化 pattern 不一定要完整塞进 query parameters。可复现性重要,但不应扭曲请求模型。 + +结构化 matcher 需要先验证再执行宽范围查询。页面应展示 pattern diagnostics、unsupported features、parser availability 和 file-language mismatch。`tree-sitter-xgo` 或 matcher 不可用时,应作为 parser 或 matcher coverage 显示,而不是表现成没有结果。 + +如果浏览器侧 Tree-sitter-compatible XGo grammar 可用,客户端可以提供本地解析、query validation 和 match preview。这只是编辑体验辅助。后端校验仍然是权威,因为真实搜索运行在后端索引、后端 parser version、matcher version、文件选择策略和授权上下文上。 + +结果检查是管理台体验的核心。每个结果都应能作为一个 source file 中的一个 match 被查看,带有 project identity、source kind、file path、matched range、snippet、captures、freshness state 和 diagnostics。管理台可以按 project 或 file 分组展示,但后端核心结果不应只返回 project-level counts。 + +导航必须 source-aware。latest project content 的命中可以链接到当前项目或编辑器上下文。release snapshot 的命中不能被呈现为来自可变的 latest project files。结果需要足够的 source identity,让客户端决定链接到项目页、编辑器、release history 或只读源码预览。 + +## 生态参考 + +Code Search 应贴近业内成熟代码搜索和结构化搜索约定,但不需要复制任何单一产品。 + +GitHub Code Search 和 Sourcegraph Code Search 都将查询文本与 repo、language、path、symbol、content、visibility、count 或 timeout 等过滤条件区分开。这支持 Code Search 将 source scope、project filters、file filters、text query、structural matcher 和 execution controls 分开建模,而不是复制单字符串查询语言。 + +GitHub 和 Sourcegraph 的文本搜索也说明,代码搜索应该保持解释性。正则、boolean 行为、path 过滤、language 过滤、大小写和结果限制都应明确,而不是依赖自然语言检索或 embedding similarity。 + +ast-grep 和 Semgrep 是人类编写结构化查询的重要参考。二者都使用 code-like patterns 和 metavariables。Code Search 可以采用 ast-grep-like 子集作为结构化查询风格,但不应把 lint、severity、message、fix、taint 或 rule pack 引入第一阶段搜索契约。 + +Sourcegraph Structural Search 是性能边界的提醒。跨全部项目的无文本锚点结构化查询应该被视为独立执行形态,需要 filters、limits、partial coverage、timeout 或 asynchronous execution。 + +CodeQL 代表更重的语义分析模型。它依赖语言特定 database、AST、data flow、control flow、name binding 和 type information。Code Search 第一阶段不应直接走 CodeQL-like 路线,但可以保留未来 semantic facts 和 resolved symbol filtering 的接口空间。 + +Zoekt、Tantivy、OpenSearch 和 PostgreSQL `pg_trgm` 是实现参考,而不是公共 API 参考。它们可以影响索引实现,但不应该决定 Code Search 的公共概念、结果模型或权限边界。 + +## 后续演进方向 + +第一阶段应同时包含文本搜索和语法级结构化搜索的最小可用能力。只有文本搜索会让许多代码形态问题难以表达,直接进入 resolved symbol 级语义搜索又会过早绑定 XGo 编译和 classfile 语义。 + +语法级结构化搜索应优先围绕 XGo 语法和 `.spx` 文件落地。`tree-sitter-xgo` 如果成熟,可以作为长期语法树基础。如果它尚未成熟,后端实现可以采用更小的内部结构化 matcher 或其他可替换实现,但公共契约仍应保持语法级 matcher 的语义。 + +语义过滤应作为后续层接入。它用于确认 resolved package、type、method、field、receiver、implicit receiver 或 framework-provided member。语义事实应来自 XGo 拥有的编译器、语言服务或语义分析组件,而不是 Tree-sitter grammar。 + +索引后端应可替换。小规模或第一阶段可以由 PostgreSQL 管理 metadata、freshness、权限信息、索引状态和部分文本检索。随着数据量和查询复杂度增长,可以评估 Zoekt、Tantivy 或 OpenSearch。API 不应因后端替换而改变核心语义。 + +未来可以在 Code Search 结果之上构建更高层工作流,例如迁移候选列表、批量 review queue、framework 兼容性审查或代码迁移辅助。自动改写或全局代码编辑属于后续能力,不属于第一阶段 Code Search 契约。 + +## 待收敛事项 + +以下事项需要在后续 OpenAPI、后端实现或阶段计划中收敛: + +- 第一阶段默认 source scope 是 latest project content、release snapshot 还是两者都支持 +- 第一阶段具体纳入哪些 JSON file roles +- 历史 stage code 路径是否进入第一阶段索引 +- 文本搜索的第一批模式是 literal、identifier-oriented、phrase、boolean 还是 regex +- 结构化 matcher 的第一批 ast-grep-like 子集范围 +- `tree-sitter-xgo` 的成熟度与后端结构化搜索时间线如何协调 +- 索引是否存储完整 searchable text、snippet cache、parse tree、extracted facts 或仅存引用 +- 初始实现使用 PostgreSQL `pg_trgm` 还是引入独立搜索索引 +- 宽范围结构化查询使用同步 partial result、异步执行,还是要求更强过滤条件 +- Code Search admin capability 的命名、授权映射和审计字段 + +这些事项不改变本文档的核心边界。Code Search 应保持通用、分层、source-aware、match-oriented、可审计,并且不把某个 framework 或某个 admin 工作流编码进后端能力。 + +## 参考资料 + +- [goplus/builder#3331](https://github.com/goplus/builder/issues/3331) +- [Tree-sitter](https://tree-sitter.github.io/tree-sitter/) +- [Tree-sitter query syntax](https://tree-sitter.github.io/tree-sitter/using-parsers/queries/1-syntax.html) +- [ast-grep pattern syntax](https://ast-grep.github.io/guide/pattern-syntax.html) +- [Semgrep pattern syntax](https://docs.semgrep.dev/writing-rules/pattern-syntax) +- [GitHub Code Search syntax](https://docs.github.com/en/search-github/github-code-search/understanding-github-code-search-syntax) +- [Sourcegraph Code Search queries](https://sourcegraph.com/docs/code-search/queries) +- [Sourcegraph Structural Search](https://sourcegraph.com/docs/code-search/types/structural) +- [CodeQL overview](https://codeql.github.com/docs/codeql-overview/about-codeql/) +- [PostgreSQL `pg_trgm`](https://www.postgresql.org/docs/current/pgtrgm.html) +- [Zoekt](https://github.com/sourcegraph/zoekt) +- [Tantivy](https://github.com/quickwit-oss/tantivy) +- [OpenSearch full-text queries](https://docs.opensearch.org/latest/query-dsl/full-text/)