Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,4 @@ PYTHON_INTERNAL_ALLOWLIST=
# Which Plan-tier allowlist file the clawix-pypi-proxy mounts (prod compose only).
# Values: standard | extended | unrestricted. Defaults to extended.
PYTHON_ALLOWLIST_TIER=extended

4 changes: 4 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export default tseslint.config(
'**/generated/**',
'scripts/**',
'data/**',
// playwright.config.ts requires @playwright/test which is not yet installed
'**/playwright.config.ts',
],
},
js.configs.recommended,
Expand Down Expand Up @@ -93,6 +95,8 @@ export default tseslint.config(
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-extraneous-class': 'off',
'@typescript-eslint/no-useless-constructor': 'off',
// Integration tests legitimately use console.warn to signal skipped suites
'no-console': 'off',
},
},
{
Expand Down
9 changes: 8 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,14 @@
"@prisma/engines",
"@swc/core",
"prisma"
]
],
"packageExtensions": {
"@whiskeysockets/baileys": {
"dependencies": {
"long": "^5.3.2"
}
}
}
},
"devDependencies": {
"@eslint/js": "^9.18.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"private": true,
"type": "module",
"scripts": {
"build": "tsc",
"build": "tsc && node --input-type=module -e \"import('fs/promises').then(fs => fs.cp('src/engine/wiki/schema-template.md', 'dist/engine/wiki/schema-template.md'))\"",
"dev": "nest start --watch",
"start": "node dist/main.js",
"typecheck": "tsc --noEmit",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
-- Wiki Memory Redesign — see docs/specs/2026-05-17-wiki-memory-redesign-design.md §6.1
-- Additive: legacy MemoryItem/MemoryShare tables stay until Phase 5.

-- 1. pg_trgm extension (required for trigram GIN indexes)
CREATE EXTENSION IF NOT EXISTS pg_trgm;

-- 2. New enum
CREATE TYPE "WikiScope" AS ENUM ('AMBIENT', 'ARCHIVED');

-- 3. WikiPage table
CREATE TABLE "WikiPage" (
"id" TEXT NOT NULL,
"ownerId" TEXT NOT NULL,
"title" TEXT NOT NULL,
"slug" TEXT NOT NULL,
"summary" TEXT NOT NULL,
"content" TEXT NOT NULL,
"tags" TEXT[],
"scope" "WikiScope" NOT NULL DEFAULT 'ARCHIVED',
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,

CONSTRAINT "WikiPage_pkey" PRIMARY KEY ("id")
);
CREATE UNIQUE INDEX "WikiPage_ownerId_slug_key" ON "WikiPage" ("ownerId", "slug");
CREATE INDEX "WikiPage_ownerId_scope_idx" ON "WikiPage" ("ownerId", "scope");
CREATE INDEX "WikiPage_ownerId_updatedAt_idx" ON "WikiPage" ("ownerId", "updatedAt");

-- 4. WikiShare (visibility + sharing for WikiPage)
CREATE TABLE "WikiShare" (
"id" TEXT NOT NULL,
"pageId" TEXT NOT NULL,
"sharedBy" TEXT NOT NULL,
"targetType" "ShareTarget" NOT NULL,
"groupId" TEXT,
"sharedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"revokedAt" TIMESTAMP(3),
"isRevoked" BOOLEAN NOT NULL DEFAULT false,

CONSTRAINT "WikiShare_pkey" PRIMARY KEY ("id")
);
CREATE INDEX "WikiShare_pageId_isRevoked_idx" ON "WikiShare" ("pageId", "isRevoked");
CREATE INDEX "WikiShare_groupId_isRevoked_idx" ON "WikiShare" ("groupId", "isRevoked");

-- 5. WikiLink (cross-references derived from [[slug]] markers in content)
CREATE TABLE "WikiLink" (
"id" TEXT NOT NULL,
"fromPageId" TEXT NOT NULL,
"toPageId" TEXT NOT NULL,

CONSTRAINT "WikiLink_pkey" PRIMARY KEY ("id")
);
CREATE UNIQUE INDEX "WikiLink_fromPageId_toPageId_key" ON "WikiLink" ("fromPageId", "toPageId");
CREATE INDEX "WikiLink_toPageId_idx" ON "WikiLink" ("toPageId");

-- Foreign keys
ALTER TABLE "WikiPage" ADD CONSTRAINT "WikiPage_ownerId_fkey" FOREIGN KEY ("ownerId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "WikiLink" ADD CONSTRAINT "WikiLink_fromPageId_fkey" FOREIGN KEY ("fromPageId") REFERENCES "WikiPage"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "WikiLink" ADD CONSTRAINT "WikiLink_toPageId_fkey" FOREIGN KEY ("toPageId") REFERENCES "WikiPage"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "WikiShare" ADD CONSTRAINT "WikiShare_pageId_fkey" FOREIGN KEY ("pageId") REFERENCES "WikiPage"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "WikiShare" ADD CONSTRAINT "WikiShare_groupId_fkey" FOREIGN KEY ("groupId") REFERENCES "Group"("id") ON DELETE CASCADE ON UPDATE CASCADE;

-- 6. Per-user migration marker (set by T20 lazy filesystem ingest)
ALTER TABLE "User" ADD COLUMN "wikiMigratedAt" TIMESTAMP(3);

-- 7. New policy fields (legacy `maxMemoryItems` kept until Phase 5)
ALTER TABLE "Policy" ADD COLUMN "maxWikiPages" INTEGER NOT NULL DEFAULT 1000;
ALTER TABLE "Policy" ADD COLUMN "maxAmbientPages" INTEGER NOT NULL DEFAULT 5;
ALTER TABLE "Policy" ADD COLUMN "wikiLintEnabled" BOOLEAN NOT NULL DEFAULT true;

-- 8. Seed per-tier defaults for the new caps (tier name conventions per docs)
UPDATE "Policy" SET "maxAmbientPages" = 5, "maxWikiPages" = 500 WHERE "name" = 'standard';
UPDATE "Policy" SET "maxAmbientPages" = 15, "maxWikiPages" = 2000 WHERE "name" = 'extended';
UPDATE "Policy" SET "maxAmbientPages" = 30, "maxWikiPages" = 10000 WHERE "name" = 'unrestricted';

-- 9. Extra GIN indexes for full-text and trigram search (Prisma-unmanaged; additive only)
CREATE INDEX "wiki_page_tags" ON "WikiPage" USING GIN (tags);
CREATE INDEX "wiki_page_content_trgm" ON "WikiPage" USING GIN (content gin_trgm_ops);
CREATE INDEX "wiki_page_title_trgm" ON "WikiPage" USING GIN (title gin_trgm_ops);
CREATE INDEX "wiki_page_tsv" ON "WikiPage"
USING GIN (to_tsvector('simple',
coalesce(title,'') || ' ' || coalesce(summary,'') || ' ' || coalesce(content,'')));
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-- Drop legacy MemoryItem/MemoryShare tables after Phase 5 backfill.
-- WikiPage/WikiShare have been the source of truth since FEATURE_WIKI_MEMORY=true (T34).
-- The backfill script (T19) copied data; no further data preservation needed.
--
-- ⚠️ DESTRUCTIVE — operators MUST run the backfill (packages/api/src/scripts/migrate-memory-to-wiki.ts)
-- BEFORE deploying this migration in any environment with real data.

DROP TABLE IF EXISTS "MemoryShare";
DROP TABLE IF EXISTS "MemoryItem";

ALTER TABLE "Policy" DROP COLUMN IF EXISTS "maxMemoryItems";
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-- WikiShare.sharedBy FK to User
--
-- Previously a free TEXT column; this adds a true foreign-key relation with
-- ON DELETE SET NULL so audit references survive user deletion. Switching to
-- nullable is the only safe option: existing rows already point at real users
-- (those rows stay populated), and future user-deletes leave the share row in
-- place but un-attributed rather than cascade-removing it.

ALTER TABLE "WikiShare" ALTER COLUMN "sharedBy" DROP NOT NULL;

ALTER TABLE "WikiShare"
ADD CONSTRAINT "WikiShare_sharedBy_fkey"
FOREIGN KEY ("sharedBy") REFERENCES "User"("id")
ON DELETE SET NULL ON UPDATE CASCADE;

CREATE INDEX "WikiShare_sharedBy_idx" ON "WikiShare" ("sharedBy");
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
-- Session Recall — see docs/specs/2026-05-26-session-recall-design.md §2
-- Additive, Prisma-unmanaged: partial GIN indexes over conversational
-- SessionMessage rows (user + assistant) for cross-session full-text search.
-- The `tool`/`system` rows (verbatim tool output, hints) are intentionally
-- excluded. The to_tsvector expression below MUST stay byte-identical to the
-- one in SessionMessageSearchRepository.search().

-- pg_trgm already created by the wiki migration; idempotent / harmless to repeat.
CREATE EXTENSION IF NOT EXISTS pg_trgm;

-- Full-text index (partial: conversational rows only).
CREATE INDEX "session_message_recall_tsv"
ON "SessionMessage"
USING GIN (to_tsvector('simple', content))
WHERE role IN ('user', 'assistant');

-- Trigram index for typo-tolerant fuzzy matching (partial: same predicate).
CREATE INDEX "session_message_recall_trgm"
ON "SessionMessage"
USING GIN (content gin_trgm_ops)
WHERE role IN ('user', 'assistant');
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-- DropIndex
DROP INDEX "session_message_recall_trgm";

-- DropIndex
DROP INDEX "wiki_page_content_trgm";

-- DropIndex
DROP INDEX "wiki_page_title_trgm";
Loading
Loading