feat(ai-echo): AI echo system — pgvector retrieval, personas, memories, generic engine#2735
Open
Innei wants to merge 8 commits into
Open
feat(ai-echo): AI echo system — pgvector retrieval, personas, memories, generic engine#2735Innei wants to merge 8 commits into
Innei wants to merge 8 commits into
Conversation
…migrations) Adds pgvector custom Drizzle type, four new tables (corpus_embeddings, persona_profiles, ai_memories, ai_echoes), three AIFeatureKey entries (Echo, Embedding, PersonaDistill) with matching AISchema config keys and AiService resolvers, five new AITaskType entries with dedup keys, two new BusinessEvents (RECENTLY_ECHO_LANDED, PERSONA_PROFILE_REFRESHED), new AppErrorCode entries with payload + definition mappings, stub modules registered in AiModule, deterministic test mocks for embedding and chat runtimes.
Implements the human-authored canonical-facts layer for ai-echo: CRUD endpoints, salience-only + vector-based recall, async embed-on-write task, KPI counts. All v2 fields (confidence, salience, supersession, expiry) accepted on input and surfaced in detail view but unused by MVP logic. Recall gracefully no-ops when no embedding model is configured.
Add the ai-echo engine module (repository, service, controller, prompt builder, scenario registry, ECHO_GENERATE task processor) plus the recently scenario provider that registers via OnModuleInit. Engine is generic over EchoScenario; recently is the first concrete consumer. - Status state machine enforced via step-2 guard in the processor (replay-safe) - Daily quota enforced via Redis INCR; over-limit rows persisted as failed - Subject-delete cascade: in-flight rows -> failed/aborted, ready/edited -> archived - Public read endpoint filters to ready/edited; admin manages full row - 23 unit + integration tests cover prompt builder, scenario registry, quota, status guard, regenerate force, edit, runtime failures, replay, hypothetical extra scenario
SafeDep Report SummaryNo dependency changes detected. Nothing to scan. This report is generated by SafeDep Github App |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Summary
Adds a generic AI echo engine and three supporting modules, anchored on the
recently(wishing-well / 树洞) module: every new recently entry receives AI-written replies voiced by configurable personas. The engine is scenario-pluggable so future scenarios (comment auto-reply, reader companion) plug in without touching the engine.Four new modules under
apps/core/src/modules/ai/:post/note/page; chunker (paragraph-aware, deterministic, hash-diffed);EMBED_SYNCtask + event listeners; admin backfill + stats; retrieval API returnssimilarity = 1 - cosine_distance.PERSONA_REGISTRYconst withinner-self(dynamic, distilled) +passerby(static);persona_profilestable; single-pass LLM distillation with Redis lock; length-window + recency-weighted exemplar selection.recallsupports salience-only (no query) and vector-ranked (with query, re-ranked bysimilarity × salience × confidence); KPI.EchoScenarioabstraction +ai_echoestable;ECHO_GENERATEtask with status-guarded idempotent replay; daily quota; admin regenerate/edit/delete/list + public list. Ships one scenario:recently(triggers onRECENTLY_CREATE, cascades onRECENTLY_DELETE).Shared foundation:
vectorcustom Drizzle column type0015_ai_echo_system.sql(additive only; expand-contract safe)AIFeatureKey.Echo/Embedding/PersonaDistill+ matchingAISchemaconfig slots +AiServiceresolversAITaskTypeentries with dedup keysAppErrorCodeentries with payload + definition mappingsBusinessEvents(RECENTLY_ECHO_LANDED,PERSONA_PROFILE_REFRESHED)Specs
docs/superpowers/specs/2026-05-23-ai-echo-system-root.mddocs/superpowers/specs/2026-05-23-ai-echo-engine-design.mddocs/superpowers/specs/2026-05-23-ai-embeddings-design.mddocs/superpowers/specs/2026-05-23-ai-persona-design.mddocs/superpowers/specs/2026-05-23-ai-memory-design.mdImplementation deviations (all reality adaptations)
EchoScenarioRegistryservice replaces the spec'sECHO_SCENARIOmulti-provider injection token — NestJS doesn't natively supportmulti: true(Angular concept); consumer modules self-register viaOnModuleInit. Functionally equivalent.AiServiceis locally provided inAiPersonaModule/AiMemoryModuleto avoid circular import; stateless (only resolves config). Worth consolidating later.POST /ai-embeddings/backfillafter configuring an embedding model. Spec §12 already allows this fallback.pgvector/pgvector:pg17(one-line tag swap inpg-testcontainer.ts).Test plan
pnpm exec eslint --fix— clean across all modified filespnpm -C apps/core run lint:migrations— ok (16 files scanned)npx vitest run --no-file-parallelism test/src/modules/ai/{ai-embeddings,ai-persona,ai-memory,ai-echo}— 110/110 passing (15 spec files)status='ready';RECENTLY_ECHO_LANDEDfires twiceGET /ai-echo/by-subject/recently/:idfilters toready+editedai_echoes.metadata.memoryIdsKnown infra debt (pre-existing, not introduced here)
Full-suite test runs have occasional flakes due to
dbHelper.clear()(intest/helper/db-mock.helper.ts) issuing blanketTRUNCATEacross parallel vitest worker processes that share the same pg-testcontainer. The new specs pass deterministically when run in isolation. A future cleanup should either scopedbHelper.clear()to per-spec tables or setpoolOptions.forks.singleFork: true.Follow-ups (deferred to v2 per spec)
ai-inflight/from-passageLLM draft,MEMORY_EXTRACT+ forced review,MEMORY_DECAY, supersede detection, KPI nudge widget