Skip to content

feat(search): 通用拼音搜索 — locale 开关 + 名称字段 __search 拼音伴随列(#2486, ADR-0097) - #3027

Merged
os-zhuang merged 2 commits into
mainfrom
claude/vibrant-euler-of05nx
Jul 16, 2026
Merged

feat(search): 通用拼音搜索 — locale 开关 + 名称字段 __search 拼音伴随列(#2486, ADR-0097)#3027
os-zhuang merged 2 commits into
mainfrom
claude/vibrant-euler-of05nx

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

实现 #2486:在 ADR-0061 现有 $search 之上,为"输拼音"补一条名称字段伴随列,纯加性 — 其它搜索行为一律不动。方案记录为 ADR-0097

实现(按 issue 组件清单)

平台开关(locale 推导默认值)

  • @objectstack/types 新增 resolveSearchPinyinEnabled({ locales? }):显式 OS_SEARCH_PINYIN_ENABLED 永远优先;未设置时由配置 locale 推导(挂任意 zh-* 即默认开)。
  • 单一决策点:CLI serve 是唯一看得到 stack i18n 配置的地方 — 在那里解析一次并把结果回写进环境变量,之后每个消费方(各 engine 的 SchemaRegistry、插件门控)通过无参形式读到同一个答案。
  • 开关开时 serve 自动把 pinyin-search 能力加入 requires 并加载插件(与 mcp 的 default-on 模式同形态)。无字段级元数据,不存在 ADR-0049 的死标记。

编译期物化(1 列 / 对象)

  • packages/objectql/src/search-companion.ts(新):provisionSearchCompanionSchemaRegistry.registerObject 里、provisionPrimary 之后运行 — 只对 ADR-0079 解析出的 display/name 字段挂隐藏列 __search(hidden/readonly/system/searchable:false/index:true),migration 走 driver syncSchema 正常加列(ADR-0045 加性物化)。
  • 安全护栏(ADR-0061 D5 延伸,fail-closed):带 requiredPermissions(FLS)、hidden、secret/虚拟类型的源字段一律不进伴随列 — 在唯一的 eligibility gate 强制,不靠作者记得。

plugin-pinyin-search(纯 hook,对齐 plugin-sharing primary-BU 投影先例)

  • 全局 beforeInsert/beforeUpdate hook:只在源字段出现在本次写入时重算(无写放大);pinyin-pro 懒加载(开关关/非中文部署零成本);全拼+首字母同列存储("张伟""zhangwei zw");改名为非中文时清空 blob(无 stale 召回)。
  • 写路径兜底:kernel:bootstrapped 分页幂等回填 + rebuildSearchCompanion 对账/重建入口(绕过 hook 的 bulk import / 迁移直写)。

查询期接入(纯加性)

  • expandSearchToFilter:对象存在 __search 列时,每个拉丁 term 额外 OR { __search: { $contains: term } };中文 term 跳过(直打源列)。
  • resolveSearchFields原样不动;$searchFields override 与 allowed 求交后天然够不到伴随列(已测)。$or+$contains 所有驱动已支持,零驱动改动

通用化接缝

SEARCH_COMPANION_NORMALIZERS = ['pinyin'] — 只实现 pinyin,简繁/全半角/重音折叠共用同一列与机制。

验证

showcase 真机端到端(pnpm dev --fresh,zh-CN locale 自动点亮,插件出现在加载列表):

输入结果
$search=zhangwei(全拼)命中 张伟 ✓
$search=zw(首字母)命中 张伟 ✓
$search=张(中文)命中 张伟 ✓(源列直搜,行为不变)
$search=ada(拉丁原文)命中 Ada Lovelace ✓(不变)
$searchFields=__search 越权求交为空 → 回退默认集,伴随列不可被 override 指定 ✓
自动生成列表/表单__search 被 hidden 过滤,不出现 ✓

说明:__search 会随单记录默认响应返回(null 或拼音 blob)— 与现有 hidden 系统列(organization_id 等)的平台行为完全一致,且值只派生自人人可读的名称字段,无新信息面。

测试:objectql 880(新增 29:eligibility gate / provisioning / registry 集成 / 查询期 OR / override 不可达)、types 14、cli 509、plugin-pinyin-search 14(真实 pinyin-pro)全绿。开关默认关 → 全套既有测试即"纯加性"证明。

范围 / 非目标(同 issue)

相关性排序 / typo 容错 / 整词防噪属 Tier-2;不物化非名称字段、不引入 search blob、不改 searchableFields;不依赖数据库分词器,方言/引擎无关。多音字用 pinyin-pro 默认启发式(P2 字典覆盖留 issue 跟踪)。

下游:objectstack-ai/objectui#2112 分层选人器 picker 仅发 $search,拼音透明点亮,无需 UI 改动。

Closes#2486

🤖 Generated with Claude Code

https://claude.ai/code/session_01RMugRriiNv3nsnmLczfhuY


Generated by Claude Code

…on column (#2486)
Implements ADR-0097 (extends ADR-0061 Tier-1 $search, purely additive):
- OS_SEARCH_PINYIN_ENABLED platform switch (resolveSearchPinyinEnabled in
@objectstack/types): explicit env wins; when unset the CLI boot path
derives the default from the stack's configured locales (any zh-* -> on)
and stamps the decision back into the env so the per-engine
SchemaRegistry and the plugin gate read the same answer.
- Compile-time materialization: SchemaRegistry.registerObject provisions a
hidden `__search` companion column (hidden/readonly/system/searchable:false,
indexed) for the ADR-0079 display/name field, right after provisionPrimary.
FLS-restricted (requiredPermissions), hidden, secret/virtual source fields
never feed the companion (ADR-0061 D5, fail-closed).
- New @objectstack/plugin-pinyin-search: global beforeInsert/beforeUpdate
hooks fill the blob (full pinyin + initials, "zhangwei zw") via lazy-loaded
pinyin-pro only when the source field is in the write; paged idempotent
boot backfill on kernel:bootstrapped plus rebuildSearchCompanion reconcile
entry for hook-bypassing writes.
- Query-time: expandSearchToFilter ORs { __search: { $contains: term } } into
each latin term's clause when the column exists; resolveSearchFields is
unchanged and the companion is unreachable via $searchFields overrides.
CJK terms skip the clause. Zero driver changes.
Verified end-to-end on the showcase app (zh-CN locale auto-enables):
$search=zhangwei / zw / 张 all recall 张伟; latin and CJK source-column
search behavior unchanged. Tests: objectql 880 passed (29 new), types 14,
cli 509, plugin-pinyin-search 14.
Closes#2486
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RMugRriiNv3nsnmLczfhuY
@vercel

vercelBot commented Jul 16, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
specReadyReadyPreview, CommentJul 16, 2026 6:25am

Request Review

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation dependencies Pull requests that update a dependency file tests tooling size/xl labels Jul 16, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 4 package(s): @objectstack/cli, @objectstack/objectql, @objectstack/plugin-pinyin-search, @objectstack/types.

27 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/skills-reference.mdx(via packages/cli)
  • content/docs/api/client-sdk.mdx(via @objectstack/cli)
  • content/docs/api/data-flow.mdx(via @objectstack/cli)
  • content/docs/api/environment-routing.mdx(via @objectstack/cli)
  • content/docs/api/error-catalog.mdx(via @objectstack/cli)
  • content/docs/automation/hook-bodies.mdx(via packages/cli)
  • content/docs/concepts/metadata-lifecycle.mdx(via @objectstack/objectql)
  • content/docs/data-modeling/formulas.mdx(via packages/objectql)
  • content/docs/deployment/backup-restore.mdx(via @objectstack/cli)
  • content/docs/deployment/migration-from-objectql.mdx(via @objectstack/objectql)
  • content/docs/deployment/self-hosting.mdx(via @objectstack/cli)
  • content/docs/deployment/vercel.mdx(via @objectstack/objectql)
  • content/docs/getting-started/cli.mdx(via @objectstack/cli)
  • content/docs/getting-started/your-first-project.mdx(via @objectstack/cli)
  • content/docs/kernel/runtime-services/data-service.mdx(via packages/cli)
  • content/docs/kernel/runtime-services/index.mdx(via packages/cli)
  • content/docs/kernel/services-checklist.mdx(via @objectstack/objectql)
  • content/docs/kernel/services.mdx(via @objectstack/objectql)
  • content/docs/permissions/authentication.mdx(via @objectstack/cli, @objectstack/objectql)
  • content/docs/plugins/index.mdx(via @objectstack/objectql)
  • content/docs/plugins/packages.mdx(via @objectstack/cli, @objectstack/objectql, @objectstack/types)
  • content/docs/protocol/kernel/index.mdx(via @objectstack/objectql)
  • content/docs/protocol/kernel/plugin-spec.mdx(via @objectstack/cli)
  • content/docs/protocol/kernel/realtime-protocol.mdx(via @objectstack/cli)
  • content/docs/protocol/objectql/state-machine.mdx(via @objectstack/objectql)
  • content/docs/releases/implementation-status.mdx(via @objectstack/cli, @objectstack/objectql)
  • content/docs/releases/v9.mdx(via @objectstack/objectql)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

…version group
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RMugRriiNv3nsnmLczfhuY
@os-zhuang
os-zhuang marked this pull request as ready for review July 16, 2026 07:12
@os-zhuang
os-zhuang merged commit 1c58abd into mainJul 16, 2026
17 checks passed
@os-zhuang
os-zhuang deleted the claude/vibrant-euler-of05nx branch July 16, 2026 07:12
os-zhuang added a commit that referenced this pull request Jul 16, 2026
…strable out of the box (#3034)
Follow-ups to the merged pinyin-search feature (ADR-0097, PR #3027):
- environment-variables.mdx: new "Search" section documenting OS_SEARCH_PINYIN_ENABLED (locale-derived default, explicit override, what it gates).
- queries.mdx: "Pinyin recall" subsection under Full-Text Search.
- showcase seed: CJK-named account (华宁科技) and contacts (张伟/王芳/李雷) so the auto-enabled pinyin search is demonstrable out of the box.
Verified on a fresh showcase boot: $search=zhangwei/zw/wf/huaning/hnkj all recall the seeded CJK records.
Refs #2486
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RMugRriiNv3nsnmLczfhuY
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependenciesPull requests that update a dependency filedocumentationImprovements or additions to documentationsize/xlteststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

通用拼音搜索:locale 开关 + 名称字段拼音伴随列(接入 ADR-0061,纯加性)

2 participants

@os-zhuang@claude