Org-wide Memory — Task Checklist
Status: Draft v1 · Date: 2026-07-18 Spec: spec.md · Plan: plan.md
Granular checklist agents and reviewers tick off as work lands. Additive by default (NN #20); every schema change ships its migration in the same PR (NN #16).
Phase P1 — Org-wide aggregation page (search + list, no new tables)
Repository / facade
-
WorkKnowledgeDocumentRepository.list()— accept optionalworkIds: string[]IN-list; keep the mandatory-scope guard (reject unscoped calls). -
VectorStoreFacadeService.queryChunksAcrossWorks(workIds[], …)— pgvector row-filter path + per-Work fan-out/merge for namespace-per-Work backends; preserve P0workIdfilter on every chunk query. -
KnowledgeBaseService.orgSemanticSearch(orgId, q, filters)— resolve org Work ids viaWorkRepository.findIdsByOrganization, embed viaAiFacadeService.embed(degrade to lexical-only when no embedder), RRF-blend with FTS.
API
- New
apps/api/src/organizations/org-memory.controller.ts— guard stack mirrored fromorg-kb.controller.ts. -
GET /api/memory— faceted, paginated union feed (q,type[],work[],source[],status[],tag[],view,cursor,limit). -
GET /api/memory/facets— per-facet counts honoring other active filters. -
GET /api/memory/stats—{ documentsIndexed, conceptsSynthesized: 0, worksCovered, lastIndexedAt }. -
POST /api/memory/documents—+ New; delegates toKnowledgeBaseService.createOrgDocument(org-scopedWorkKnowledgeDocument). -
GET /api/memory/documents/:id— uniform item detail (proxies KB doc / agent-memory session). - New
apps/api/src/organizations/org-memory.service.ts— buildsMemoryItemunion feed + agent-memory read-through (best-effort, empty on failure).
Contracts
-
MemoryItemDto,MemoryFeedResponseDto,MemoryFacetsDto,MemoryStatsDto,CreateMemoryDocumentDtoinpackages/contracts. - OpenAPI annotations on every endpoint.
Web
- Web proxy
apps/web/src/app/api/organizations/[orgId]/memory/**(passesX-Scope-Slug). - Route
apps/web/src/app/[locale]/(dashboard)/organizations/[slug]/memory/page.tsx+ legacy alias. - Search input (reuse
KbSearchPalette, org-scoped). - Header counts row (
{documentsIndexed} documents indexed · {conceptsSynthesized} concepts synthesized; concepts hidden/—until P3). - Filter chips
[Type][Work][Source][Status][Tag]— multi-select, count badges, clear-all. - List view rows: title, type/source badge, Work chip, snippet, updated-at, provenance link.
-
+ Newdialog (reuse Tiptap editor) →POST /api/memory/documents. -
List | Graphtoggle (Graph disabled with "coming soon" tooltip).
Sidebar / i18n / routing
- Insert
{ name: t('navigation.memory'), href: ROUTES.DASHBOARD_MEMORY, icon: Brain }after the Agents item inDashboardSidebar.tsx(L124). - Add
ROUTES.DASHBOARD_MEMORY→/{slug}/memory(+ legacy/memory). -
navigation.memoryi18n key in all locales (no half-translation). - Hooks
useOrgMemory(),useMemoryFacets().
Tests
- Repo guard: rejects unscoped, accepts
workIdsIN-list. - Facade fan-out preserves
workIdfilter (pgvector + namespace-per-Work paths). - Controller membership guards (member reads, admin writes).
-
GET /api/memoryfaceted shape + pagination. -
+ Newwrites an org-scoped doc (workId NULL, organizationId set, XOR CHECK holds). - Playwright: open Memory → search → filter Type/Work → create note → appears in feed.
Phase P2 — memory + rag plugin categories + first plugin
Contracts / categories
- Append
'memory'and'rag'toPLUGIN_CATEGORIESinplugin-manifest.types.ts(append-only + breadcrumb comment). -
packages/plugin/src/contracts/capabilities/memory.interface.ts—IMemoryPlugin+MemoryScope,MemoryWriteInput,MemoryRecord,MemoryQuery,MemorySession,PromotionPassInput,SynthesisPassInput. -
packages/plugin/src/contracts/capabilities/rag.interface.ts—IRagPlugin+RagIngestInput,RagQuery,RagHit. - Type guards + optional
base-memory.ts/base-rag.tsabstracts (mirrorbase-vector-store.ts).
Facades
-
MemoryFacadeService(packages/agent/src/facades/memory-facade.service.ts) — selection cascade +MemoryNotConfiguredErrordegrade-to-empty. -
RagFacadeService— composescontent-extractor+ai-provider.embed+vector-storeforingest; blendedretrieve.
First-party memory plugin
-
packages/plugins/agentmemory/manifest →category: 'memory',capabilities: ['memory','agent-memory'](additive — keepagent-memory),defaultForCapabilities: ['memory']. - Implement
IMemoryPluginoveragentmemory-client.ts(remember/recall;promote/synthesizeno-op flat tier until P3). - Verify the shipped agent-memory pipeline suite still passes (no regression).
Office-doc extractor (complementary)
-
@ever-works/officecli-extractor-pluginascontent-extractor(docx/xlsx/pptx text;systemPlugin:false,autoEnable:false) per office eval. - Run the Alpine/musl gate before wiring into any image build;
mammoth+SheetJSfallback if musl fails.
Capability REST
-
apps/api/src/plugins-capabilities/memory/+rag/sub-controllers (enable / select active per org).
Tests
- Category tuple type guard accepts
memory/rag. -
MemoryFacadeServiceselection cascade + degrade path. -
agentmemoryplugin satisfies both capabilities; agent-memory pipeline unbroken. - Office extractor
canExtract+ SSRF-guard/byte-cap reuse.
Phase P3 — Graph + cognitive-memory model + synthesis + Mission/Team facets
Cognitive-memory tables (migrations same-PR)
-
memory_entryentity + migration (Tier A: nullabletenantId+organizationId;partition,tier,embedding vector(1536),salience, source correlation cols). -
memory_conceptentity + migration (Tier A;entryCount,lastSynthesizedAt). -
memory_concept_linkentity + migration (Tier C denormalized;(targetType,targetId)index for graph edges). - Enums
memory_partition(working/episodic/semantic/procedural/user-model),memory_tier(session/work/org/global). - Register all three entities in
database.config.tsENTITIESarray (same PR; unregisteredforFeature→ runtime 500).
Passes
- Trigger.dev
memory-promote— salience increment/decay, thresholdsession→work→orgpromotion, embedding-cosine dedupe/merge; per-org cadence + budget cap. - Trigger.dev
memory-synthesize+POST /api/memory/synthesize(admin-gated) — cluster → summarize →memory_concept+derived-fromlinks; idempotent re-synthesis. -
GET /api/memory/statsconceptsSynthesized=COUNT(memory_concept WHERE org).
Graph view
-
GET /api/memory/graph— nodes + edges (citations, wiki-links,memory_concept_link), filter-aware, server-side subgraph windowing (node cap, top-N by weight). - Web graph client component; wire List|Graph toggle live.
Mission facet — blocked on Prerequisite A
- (Prereq, other feature) First-class Work→Mission linkage — recommended nullable
works.missionId+ one-time backfill fromacceptedFromIdeaId → WorkProposal.missionId. Owned by Missions/Ideas/Works, not this feature. - Add
[Mission ▾]chip +mission[]filter +missionId/missionTitleonMemoryItem; feature-detect (hide if column absent).
Team facet — blocked on Prerequisite B (Teams feature)
- (Prereq, Teams feature)
team_resources(teamId, resourceType, resourceId)polymorphic join + Tier C scope cols +(resourceType,resourceId)reverse index +(organizationId,teamId)index. New additive table owned by the Teams feature, NOT built here. - Add
[Team ▾]chip via reverse lookup (team_resources WHERE resourceType='work' AND resourceId IN (org work ids)); feature-detect on presence ofteam_resources(hide if Teams unshipped).
Tests
- Entity round-trips + migration idempotency (all three P3 tables).
- Promotion threshold + dedupe/merge correctness.
- Synthesis idempotency + concept-count counter.
- Graph node-cap / windowing.
- Mission chip appears only when
works.missionIdexists; Team chip only whenteam_resourcesexists.
Cross-cutting
- Update
apps/docs/user-facing docs: Memory (org-wide knowledge) + memory/rag plugin categories. - No existing UI string changes other than additions (NN #20).
- Every entity touched ships its migration in the same PR (NN #16).
- All PRs target
develop(NN #21); two consecutive green E2E runs before merge cascade. - Invariants preserved: P0 chunk
workIdfilter; KB list mandatory-scope guard; agent-memory best-effort; untrusted memory output fenced.
Prerequisite ownership (tracked outside this feature)
| Prereq | Table/column | Owner feature | Consumed by |
|---|---|---|---|
| A | works.missionId (denormalized, recommended) | Missions / Ideas / Works | P3 Mission chip |
| B | team_resources(teamId, resourceType, resourceId) | Teams | P3 Team chip |
Neither blocks P1/P2. Flag on the respective feature specs so they are not lost.
JIRA linkage
Epic + per-phase Stories to be created in the EW project (keys added once tickets exist):
- Epic: Org-wide Memory (Cortex)
- P1 — Aggregation page (search + list): TBD
- P2 —
memory+ragplugin categories + first plugin: TBD - P3 — Graph + cognitive-memory model + synthesis + Mission/Team facets: TBD
- Prereq A — Work→Mission linkage (Missions/Ideas/Works epic): TBD
- Prereq B —
team_resourcesjoin (Teams epic): TBD