실제 제품을 적절한 조작 환경에서 실행해 변경 사항을 검증하고, 사용자가 확인할 수 있는 증거를 모아 인수 보고서로 게시합니다. 기존 검증 계획을 확인하거나 점검 항목을 만들고, `lh` CLI로 결과를 게시할 수 있습니다.
- 변경된 제품 동작을 실제로 확인하기
- 스크린샷 등 검증 증거 수집하기
- 검증 계획과 보고서 작성하기
메시지, 파일 등 제품 데이터의 전문 검색 변경을 안내합니다. PostgreSQL과 Elasticsearch 검색 경로, 권한 유지, 문서 매핑, 증분 동기화와 재색인을 다루며 에이전트의 외부 웹 검색은 범위에 포함하지 않습니다.
Use for product search: FtsSearchRepo, pg_search/pg_like/Elasticsearch, mapping migrations, projections, Outbox sync, reindexing and performance. Excludes agent web search.
실행 점수 미검증
설치 방법 보기이 스킬은 에이전트, 메시지, 파일, 지식 베이스 같은 제품 데이터의 전문 검색을 설계하고 구현할 때 참고할 내용을 안내합니다. 검색 요청을 저장소를 통해 처리하는 구조, PostgreSQL과 Elasticsearch 제공자 사이의 경계, 검색 문서의 매핑과 투영, 결과에 데이터베이스 권한을 유지하는 방법을 다룹니다. 새 검색 대상을 추가할 때는 관련 타입, 문서 스키마, 검색 동작, 변경 포착, 재색인, 지속 동기화까지 살펴봅니다. Outbox를 통한 변경 동기화, 마이그레이션 체크포인트, 세대 관리, 모니터링과 테스트도 포함합니다.
제품 내 검색 대상을 추가하거나 검색 제공자와 매핑을 변경할 때 활용할 수 있습니다. PostgreSQL에서 Elasticsearch로 옮기거나 인덱스를 다시 구축하는 경우, 권한과 동기화 동작을 유지하면서 검색을 수정하려는 경우에도 도움이 됩니다.
이 스킬의 대상은 제품 내부 데이터 검색이며 에이전트가 사용하는 외부 웹 검색은 포함하지 않습니다. 검색 제공자로 pg_search, elasticsearch, pg_like를 사용할 수 있습니다. Elasticsearch 작업에는 설정과 운영 환경이 필요하며, 원문은 관련 개발 저장소와 데이터베이스, 검색 서비스에 접근할 수 있다고 전제합니다.
이 소개문은 공개된 SKILL.md를 바탕으로 AI(OpenAI Codex)가 작성했습니다. 정확한 사양은 아래 원문을 확인하세요.
AI가 SKILL.md의 내용에서 주의가 필요한 작업과 도입 전제를 확인했습니다. 점수는 실제로 실행한 결과(실행 검증)만으로 매깁니다.
점수에는 넣지 않았습니다. 2026년 10월 26일 기준으로 AI(OpenAI Codex)가 판정했습니다. 참고용이므로 설치 전에 원문도 확인해 주세요.
설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.
This skill covers search over LobeHub-owned product data such as agents, topics, messages, files,
knowledge bases, documents, chat groups, and memories. It does not cover the agent's external web
search providers under apps/server/src/services/search/ or builtin web-browsing tools.
Product reads follow one stable path:
router/service -> createFtsSearchRepo -> FtsSearchRepo -> selected backend -> existing result schema
apps/server/src/services/ftsSearch/ owns request-scoped provider selection, Elasticsearch
configuration, its HTTP client, and backend telemetry. Routers and domain services must call
createFtsSearchRepo; they must not construct providers themselves.packages/database/src/repositories/ftsSearch/ owns the provider-neutral contract and the concrete
PostgreSQL and Elasticsearch implementations. Keep public result shapes stable in FtsSearchRepo.packages/types/src/ftsSearch.ts owns the shared searchable-entity list and search domain types.packages/database/src/repositories/ftsSearchDocument/ owns Elasticsearch document schemas,
mappings, queryable fields, and source-to-document projection.packages/database/src/schemas/ftsSearchSyncOutbox.ts and
packages/database/src/repositories/ftsSearchSyncOutbox/ own durable change capture, claims,
retries, dead letters, leases, revision fences, and capture-definition validation.scripts/elasticsearchReindex/ owns the resumable full-backfill command and its operational
runtime. Shared database source queries and document construction remain in
packages/database/src/repositories/ftsSearchDocument/. apps/server/src/services/ftsSearchSync/ and
scripts/elasticsearchSync/ own continuous incremental draining.packages/env/src/ftsSearch.ts owns generic Elasticsearch environment variables.FTS_SEARCH_PROVIDER is a deployment-level provider selector with current values pg_search,
elasticsearch, and pg_like. It is not a feature flag or a user rollout. Add another enum value
only when its provider covers all entities in FTS_SEARCH_BACKEND_ENTITIES end to end, including
mode: 'candidates' when the provider enables ftsSearchCandidateEnabled.pg_like is an explicitly selected lightweight
provider, not an implicit fallback: a missing extension or unreachable service must still fail.packages/database/src/repositories/ftsSearch/postgres/ owns the query, permission, pagination,
and hydration layer shared by PostgreSQL providers. pgSearch/ and pgLike/ own only their
provider adapter, dialect, and provider-specific candidate behavior. Neither provider directory
may import the other, so either provider can be retired without owning shared functionality.userId, workspaceId, and caller-agent visibility throughout every provider. Candidate
retrieval must not broaden the caller's scope.pg_like primarily serves individual users with small datasets. Review it for correct matching,
permissions, and usable result ordering at that scale. For richer search quality or larger datasets,
recommend self-hosted Elasticsearch or Elastic Cloud. Do not add indexes or change the database
schema as part of pg_like optimization. Keep repairs bounded; distinguish new implementation bugs
from shared provider limitations and deliberate lightweight-search trade-offs. Do not infer a
personal-user performance problem from large shared development datasets without representative
measurements.
Treat an entity addition or projection change as one cross-layer change. Inspect and update every applicable item:
FTS_SEARCH_DOCUMENT_ENTITIES and shared request/result types.FtsSearchDocumentBuilder, including soft deletion and fanout from related source rows.captureInfrastructure.ts.Schema fields, mappings, builders, and fixed fixtures must agree. Current mapping fields plus
explicit FTS_SEARCH_RETAINED_SOURCE_PROPERTIES must equal the current Zod fields, without overlap.
Retained source properties keep older open indexes writable during field removals; keep the builder
producing them until those indexes are closed. They must not appear in current query metadata.
A field outside the document schema must not appear in a mapping or query field list.
Elasticsearch multi_match query length is bounded by a shared leaf-clause budget divided by the
selected query-field count. Adding a field reduces that entity's safe query length, and changing a
query analyzer to emit multiple terms per Unicode code point requires revisiting the budget and its
field-count regression tests.
installCaptureInfrastructure() is transactional, definition-checked,
idempotent for an exact installation, and fail-closed for partial or altered definitions.(entity, document_id). A newer capture resets retry/dead-letter state and
allocates a new revision only after locking the conflicting row, preserving same-document commit
order.last_value alone as proof that all earlier Outbox rows are visible.The supported operator entrypoints below run from the OSS repository root. A wrapping repository
may expose different package scripts; check its package.json before invoking these or the mapping
migration commands linked below.
bun run db:install-fts-search-capture
bun run fts-search:reindex -- --status
bun run fts-search:reindex -- --apply --yes
bun run fts-search:sync -- --max-steps=8 --yes
bun run scripts/pgSearchCleanup/index.ts --status
bun run scripts/pgSearchCleanup/index.ts --apply --yes
Docker startup runs fts-search-elasticsearch-reindex.cjs --startup --yes after PostgreSQL
migrations when the selected provider is Elasticsearch. It blocks serving until index migration
and catch-up succeed. Persist the same checkpoint volume across application and migration
containers; failed namespace locks still require explicit recovery. Continuous sync remains a
separate worker. Hosted and manual workflows keep their explicit migration commands.
For mapping changes, generation operations, repeat/resume behavior, or deployment integration, read Mapping migration workflow. It routes to the public command guide and adds recovery, automation, and local Docker rehearsal rules.
resource_already_exists_exception, not a broad HTTP status range. Preserve any other creation
failure and stop before follow-up reads or mutations instead of turning a rejected request into a
misleading verification error.Elasticsearch cannot change an existing field's type or index-time analyzer in place. The code declares the target and Elasticsearch records the live state, per entity:
FTS_SEARCH_INDEX_DEFINITIONS[entity].schemaVersion is the declared generation; the fingerprint is
sha256 of the mapping plus the shared analysis. Add complete changed-entity definitions in a new
ftsSearchDocument/migration/NNNN-meaningful-name/ batch, register it and update current pointers
in migration/index.ts. Append expected fingerprints in __tests__/schemaSnapshots.json; preserve
published batches and baselines. mappings.test.ts and migration/index.test.ts check current
parity, history, version bumps and fingerprint changes. See migration/README.md for ownership.
Shared analysis changes alter
every entity fingerprint and classify as breaking for every entity; bump all affected versions
and rebuild rather than using in-place upgrades.<alias>-v<n> or same-schema rebuild <alias>-v<n>-r<runId> carries
_meta.{reindex_run_id, schema_version, schema_fingerprint}; the alias marks the live generation.
A rebuild suffix is physical identity, not a schema-version bump. Indexes created before fingerprints
existed may omit the fingerprint, but still need a valid run ID and schema version for sync
readiness. _meta.schema_version wins over the -v<n> suffix because an in-place upgrade advances
_meta without renaming the index.<alias>-v* indexes plus the alias write index, pruning each
document to the fields that index maps (every generation is dynamic: strict), so a new
generation can be backfilled beside the live one; a bulk work item is acknowledged only when
every existing generation accepted it (2xx or 409 conflict).(namespace, schemaVersion). Explicit current-version
rebuild checkpoints add reindexRunId, so repeated v1 rebuilds never reuse a completed v1 cursor.
--apply groups the requested entities by declared version, treats existing aliases as an
upgrade (no --fresh-run), leaves existing aliases in place, and emits promotion_pending. A
completed first install creates aliases. Promoting a newer generation requires a completed
checkpoint, a fingerprint match when targeting the declared version, and an idle target-entity Outbox. Rollback
to an older stamped generation can use its metadata without a retained checkpoint;
--retire requires in_sync and only closes old generations; explicit --purge installs
exact-index templates forbidding auto-creation before deleting eligible closed generations.
--in-place requires
mappingChange: additive, widens the live index with PUT _mapping, pins the checkpoint to that
index, and backfills with external_gte so concurrent sync writes win.--apply --rebuild-current --entity=<entity> --yes when projection or capture semantics changed
without a physical mapping change and historical documents must be regenerated from PostgreSQL.
Deploy runtime support first: sync must recognize -r<runId> generations before one is created.
Resume with the reported --run-id=<uuid>. Promote with the exact
--generation=<alias>-v<n>-r<uuid> because version-only selection is ambiguous. The old generation
remains dual-written for rollback and becomes same-version retirement-eligible only after the
promotion records which live run superseded it.ES_REINDEX_STATE_DIR across
invocations. Completed runs skip backfill; incomplete runs resume from saved cursors. Mutating CLI
commands share a non-expiring Elasticsearch namespace lock, independent of checkpoint location.
A failed command retains its lock when its outcome may be uncertain. Before --release-lock=<owner> --yes, stop the previous process and resolve pending requests; never assume age proves it stopped.
The lock does not serialize old binaries or external operator actions.scripts/elasticsearchReindex/runtime/generationService.ts owns classification (missing,
unmanaged, in_sync, drift, upgrade_available, rollback_required), promotion, and
retirement; keep them free of Cloud-specific policy.Read docs/self-hosting/advanced/neon-pg-search-migration.mdx or its Chinese counterpart before
changing the operational sequence. When database rollout or index cost affects the design, also
use the db-migrations skill and measure the relevant operation on the actual Dev database before
adding manual or deferred release steps.
apps/server/src/services/ftsSearch/observability.ts.
Keep labels bounded: entity, provider, operation, outcome, and coarse error type are acceptable;
raw queries, user IDs, document IDs, and index contents are not.src/features/CommandMenu/analytics.ts. Product analytics may cover end-to-end duration, rendered
result counts, empty results, result clicks, and abandonment without a Cloud business slot.FtsSearchRepo, providers cannot leak raw result shapes,
and telemetry failures do not affect search behavior.bun run check <changed-files...> from the repository root. For migration or database-runtime
changes, follow the db-migrations and testing skills and verify against the actual Dev database.아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.
로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.
아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.
실제 제품을 적절한 조작 환경에서 실행해 변경 사항을 검증하고, 사용자가 확인할 수 있는 증거를 모아 인수 보고서로 게시합니다. 기존 검증 계획을 확인하거나 점검 항목을 만들고, `lh` CLI로 결과를 게시할 수 있습니다.
LobeHub에 AI 모델 제공자를 추가하는 과정을 안내합니다. 런타임 연동, 모델 정보와 설정, 브랜드 표시, 문서화 및 인수 확인을 다루며, 기존 제공자에 모델만 추가하는 경우와 새 연동이 필요한 경우를 구분합니다.
서버 환경 변수로 사용자 설정의 기본값을 지정하도록 구현하는 절차를 안내합니다. 변수 검증, 서버 설정 구성, 사용자 저장소 반영부터 예시 환경 파일과 셀프 호스팅 문서 갱신까지 다룹니다.
에이전트 실행 단계, 도구 호출, 사람의 승인, 컨텍스트 압축, 하위 에이전트 호출에 훅을 등록하는 방법을 안내합니다. 이벤트를 관찰하고 로컬 도구 결과를 모의하거나 설정에 따라 웹훅으로 도구 호출을 허용 또는 거부할 수 있습니다.
에이전트의 이벤트 기반 백그라운드 작업을 설계하고 구현하도록 돕습니다. 소스, 시그널, 액션, 정책의 역할을 나누고 비동기 처리, 중복 실행 방지, 완료 기록과 관측 기능을 다룹니다.
실제 데스크톱 채팅 앱에서 봇 채널의 인수 테스트를 진행합니다. Discord, Slack, Telegram, WeChat, Lark, QQ에서 메시지를 보내고 응답을 기다린 뒤 결과 화면을 캡처합니다. iMessage는 BlueBubbles 브리지를 사용합니다.