Files
gbrain/scripts/e2e-test-map.ts
0bbaed2e48 v0.42.67.0 feat(migrate): provider-agnostic embedding migration — the path off ZeroEntropy (#3390, fixes #3391) (#3459)
* feat(migrate): provider-agnostic embedding migration service — the path off ZeroEntropy (#3390)

- gbrain migrate embeddings --to <provider:model> (alias: retrieval-upgrade):
  plan + cost preflight, consent gate (--yes / TTY confirm / non-TTY exit 2),
  live probe against the target provider before any mutation, env-override
  gate, schema dimension transition via the shared runSchemaTransition,
  dual-plane config write, NULL-signature-inclusive invalidation, query-cache
  purge, resumable re-embed through the standard embed pipeline (single-flight
  locks, backoff, pacing, stderr progress). Killed runs resume by re-running
  the same command; the NULL-embedding column is the checkpoint.
- #3391 root-cause fix (both engines): countStaleChunks / sumStaleChunkChars /
  invalidateStaleSignatureEmbeddings accept includeNullSignature to lift the
  v108 grandfather clause; embed --stale warns loudly when a model swap
  leaves NULL-signature pages in the old embedding space, and
  --include-null-signature re-embeds them. Default sweep behavior unchanged.
- knobs_hash v=12 → v=13 (prov=default legacy callers must not be served
  pre-migration cache rows).
- migrate_embeddings op: scope admin, localOnly, hidden cliHints, hard
  remote refusal, needs_confirmation without yes=true.
- One-shot post-upgrade ZE-sunset banner (ze_sunset_notice_shown) for brains
  resolving to a zeroentropyai:* embedding model or reranker.
- doctor's dimension-mismatch repair hint now names the real command.
- Docs: docs/guides/embedding-migration.md, KEY_FILES entries, spend-controls
  gate row. Tests: PGLite unit + full-lifecycle flow (interrupted-run resume),
  real-Postgres e2e (pgvector DDL path + #3391 predicate parity).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(test): satisfy check:test-isolation + bump the remaining knobs_hash pins

- test/migrate-embeddings-flow.test.ts → .serial.test.ts: the file holds a
  temp GBRAIN_HOME + an installed fake embed transport for its whole
  lifecycle (beforeAll → afterAll), which withEnv() can't wrap. This also
  fixes the CI shard-pollution failure in
  test/ai/recipes-existing-regression.test.ts (that file passes solo on both
  master and this branch; the flow test's configureGateway + provider-key
  deletion was leaking into it inside the same shard process).
- test/embedding-migration.test.ts: env-override case now uses withEnv().
- Bump the three remaining KNOBS_HASH_VERSION pins to 13
  (cross-modal-phase1, search-alias-resolved-boost, search/knobs-hash-reranker).
- Docs + llms bundles follow the test rename.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore(test): wire the new Postgres e2e into the smart e2e selector map

Changes to embed.ts / embedding-migration.ts / retrieval-upgrade-planner.ts /
postgres-engine.ts now trigger test/e2e/migrate-embeddings-postgres.test.ts —
the #3391 stale predicates and runSchemaTransition's DDL path behave
differently on real pgvector than on PGLite, so the smart selector has to know.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(migrate): consult spend.posture in the embedding-migration consent gate

The brief asked the gate to honor spend.posture; it previously didn't read it
at all. Now it does — but deliberately does NOT bypass on tokenmax: posture
waives the spend CEILING, and this gate also guards a destructive schema
rebuild (existing vectors dropped, retrieval degraded until the re-embed
finishes). Under tokenmax the dollar figure is marked informational on stderr
and the confirmation is still asked; --yes stays the single scripted bypass.

Pinned by a new case in the flow test so a later refactor can't quietly turn
posture into a bypass. Guide + spend-controls table updated to match.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* wip: blocker fixes

---------

Co-authored-by: Garry Tan <garrytan@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 17:48:37 -07:00

122 lines
5.7 KiB
TypeScript

// scripts/e2e-test-map.ts
//
// Path-glob -> E2E test files map. Used by scripts/select-e2e.ts.
//
// CONTRACT: This map can ONLY narrow from "all". When a changed src/ path
// matches no glob here, the selector falls back to "run all E2E" (fail-closed).
// You can safely add narrowing entries; you cannot break correctness by missing
// one. Tune as misses surface (i.e., when ci:local:diff ran more than necessary
// and you'd like to narrow that surface area).
//
// Glob syntax is the minimal subset implemented in select-e2e.ts:
// - "**" matches any sequence of path segments (including zero)
// - "*" matches any characters within a single path segment
// - everything else is literal
// No brace expansion, no ?, no [ ].
export const E2E_TEST_MAP: Record<string, string[]> = {
// Source-aware ranking, hybrid search, intent classification.
"src/core/search/**": [
"test/e2e/search-quality.test.ts",
"test/e2e/search-exclude.test.ts",
"test/e2e/search-swamp.test.ts",
],
// Tree-sitter chunkers feed code-indexing E2E.
"src/core/chunkers/**": ["test/e2e/code-indexing.test.ts"],
// OpenClaw context-engine plugin: engine + entry feed the plugin-shape E2E
// (mocked SDK) AND the real-loader Tier 2 E2E that spawns openclaw and
// actually installs the plugin into an isolated --profile.
"src/core/context-engine.ts": [
"test/e2e/openclaw-context-engine-plugin.test.ts",
"test/e2e/openclaw-plugin-load-real.test.ts",
],
"src/openclaw-context-engine.ts": [
"test/e2e/openclaw-context-engine-plugin.test.ts",
"test/e2e/openclaw-plugin-load-real.test.ts",
],
// dream.ts is a thin alias over runCycle in cycle.ts.
"src/core/cycle.ts": ["test/e2e/cycle.test.ts", "test/e2e/dream.test.ts"],
// Multi-source sync writes share the per-source bookmark anchor.
"src/core/sync.ts": ["test/e2e/sync.test.ts", "test/e2e/multi-source.test.ts"],
// v0.32.8 multi-source bug class regression suite — fires on any cycle
// phase, extract, integrity, embed, or migrate-engine change.
"src/core/cycle/extract-takes.ts": ["test/e2e/multi-source-bug-class.test.ts"],
"src/core/cycle/patterns.ts": ["test/e2e/multi-source-bug-class.test.ts"],
"src/core/cycle/synthesize.ts": [
"test/e2e/multi-source-bug-class.test.ts",
"test/e2e/synthesize-bigint-job-id-postgres.test.ts",
],
"src/commands/embed.ts": [
"test/e2e/multi-source-bug-class.test.ts",
// #3391: the NULL-signature stale predicates differ per engine.
"test/e2e/migrate-embeddings-postgres.test.ts",
],
// #3390: runSchemaTransition's DDL path + the stale predicates behave
// differently on real pgvector than on PGLite.
"src/core/embedding-migration.ts": ["test/e2e/migrate-embeddings-postgres.test.ts"],
"src/core/retrieval-upgrade-planner.ts": ["test/e2e/migrate-embeddings-postgres.test.ts"],
"src/commands/extract.ts": ["test/e2e/multi-source-bug-class.test.ts"],
"src/commands/migrate-engine.ts": ["test/e2e/multi-source-bug-class.test.ts"],
// Any minions queue/worker/handler change exercises all minion E2E.
"src/core/minions/**": [
"test/e2e/minions-concurrency.test.ts",
"test/e2e/minions-resilience.test.ts",
"test/e2e/minions-shell.test.ts",
"test/e2e/minions-shell-pglite.test.ts",
"test/e2e/worker-abort-recovery.test.ts",
],
// postgres.js bind paths + JSONB shapes + parity vs PGLite.
"src/core/postgres-engine.ts": [
"test/e2e/postgres-bootstrap.test.ts",
"test/e2e/postgres-jsonb.test.ts",
"test/e2e/jsonb-roundtrip.test.ts",
"test/e2e/engine-parity.test.ts",
"test/e2e/schema-drift.test.ts",
// #3391: includeNullSignature stale predicates (engine parity).
"test/e2e/migrate-embeddings-postgres.test.ts",
],
// PGLite bootstrap path + parity guard.
"src/core/pglite-engine.ts": [
"test/e2e/postgres-bootstrap.test.ts",
"test/e2e/engine-parity.test.ts",
"test/e2e/schema-drift.test.ts",
],
// Schema source of truth: any change must pass the cross-engine drift gate.
"src/schema.sql": ["test/e2e/schema-drift.test.ts"],
"src/core/pglite-schema.ts": ["test/e2e/schema-drift.test.ts"],
"src/core/migrate.ts": ["test/e2e/schema-drift.test.ts", "test/e2e/migrate-chain.test.ts"],
// MCP stdio + HTTP transports share dispatch.
"src/mcp/**": ["test/e2e/mcp.test.ts", "test/e2e/http-transport.test.ts"],
// Integrity batch-load fast path.
"src/commands/integrity.ts": ["test/e2e/integrity-batch.test.ts"],
// gbrain connect — raw-bearer MCP smoke probe exercised end-to-end against
// a real serve --http (PGLite), so changes to either feed it.
"src/commands/connect.ts": ["test/e2e/connect-bearer.test.ts"],
"src/core/connect-probe.ts": ["test/e2e/connect-bearer.test.ts"],
// Upgrade chains migration ledger; touches both runners.
"src/commands/upgrade.ts": [
"test/e2e/upgrade.test.ts",
"test/e2e/migrate-chain.test.ts",
"test/e2e/migration-flow.test.ts",
],
"src/commands/doctor.ts": ["test/e2e/doctor-progress.test.ts"],
// Knowledge graph layer feeds graph-quality.
"src/core/link-extraction.ts": ["test/e2e/graph-quality.test.ts"],
// v0.38 ingestion substrate. POST /ingest lives inside serve-http.ts
// (per the plan-eng-review E1 decision); the daemon + built-in sources
// + ingest_capture Minion handler all feed the in-process roundtrip
// E2E AND the HTTP contract E2E for the webhook route.
"src/commands/serve-http.ts": [
"test/e2e/serve-http-ingest-webhook.test.ts",
"test/e2e/serve-http-oauth.test.ts",
],
"src/core/ingestion/**": [
"test/e2e/ingestion-roundtrip.test.ts",
"test/e2e/serve-http-ingest-webhook.test.ts",
],
"src/core/minions/handlers/ingest-capture.ts": [
"test/e2e/ingestion-roundtrip.test.ts",
"test/e2e/serve-http-ingest-webhook.test.ts",
],
};