Files
paperclip/packages/plugins/plugin-llm-wiki/tests/plugin.spec.ts
T
Dotta 508355b8fc [codex] Add LLM Wiki plugin package to master (#5716)
## Thinking Path

> - Paperclip orchestrates AI agents for zero-human companies.
> - The plugin system is the extension surface for optional product
capabilities without baking every workflow into core.
> - The LLM Wiki plugin package was reviewed in stacked PR #5592, which
targeted `pap-9173-llm-wiki-rest`.
> - The stack base PR #5597 merged to `master` before #5592 was merged
into that branch, so the plugin package never reached `master`.
> - A direct PR from `pap-9173-llm-wiki-rest` back to `master` would be
noisy because that branch has diverged from current `master`.
> - This pull request reapplies the reviewed
`packages/plugins/plugin-llm-wiki/` package onto current `master` and
updates Docker deps-stage manifest coverage.
> - The branch intentionally no longer changes `pnpm-workspace.yaml`
after maintainer feedback; because the new package is now a root
workspace importer, the remaining integration question is how
maintainers want the root lockfile handled under the current PR policy.

## What Changed

- Added the LLM Wiki plugin package under
`packages/plugins/plugin-llm-wiki/` from the merged PR #5592 head.
- Preserved the post-review cleanup from #5592: generated
design/screenshot artifacts are not committed, and `src/ui/index.tsx` /
`src/wiki.ts` are small public entrypoints.
- Added the new plugin package manifest to the Docker deps stage so
policy can validate package manifest coverage.
- Removed the earlier `pnpm-workspace.yaml` exclusion per maintainer
request, so the plugin is included by the existing `packages/plugins/*`
workspace glob.

## Verification

Current head:
- PGlite migration harness: ran migrations 001-003, verified old
non-space distillation unique constraints were removed, inserted
duplicate cursor and work-item keys in a second space, then reran
migration 003 successfully
- `node ./scripts/check-docker-deps-stage.mjs`
- `git diff --check`

Known current-head install result after removing the workspace
exclusion:
- `pnpm install --frozen-lockfile` fails because `pnpm-lock.yaml` has no
importer for `packages/plugins/plugin-llm-wiki/package.json`.

Previously verified on the same plugin source before the
workspace-exclusion removal:
- `pnpm --filter @paperclipai/plugin-sdk build`
- `cd packages/plugins/plugin-llm-wiki && pnpm install --lockfile=false
&& pnpm test`

## Risks

- The branch now includes `packages/plugins/plugin-llm-wiki` in the root
workspace but does not update `pnpm-lock.yaml`. Root frozen install will
fail until maintainers choose a lockfile path that fits repo policy.
- Committing `pnpm-lock.yaml` directly on this PR conflicts with the
current PR policy check, while excluding the package from
`pnpm-workspace.yaml` was rejected in maintainer feedback.
- The package includes UI code already reviewed in #5592; generated
screenshot/design artifacts were intentionally removed per maintainer
request, so visual review should regenerate screenshots locally if
needed.
- The package depends on plugin host support from #5597, which is
already merged to `master`.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

- OpenAI GPT-5 Codex via Codex CLI, tool use and local code execution
enabled; context window not exposed.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have run the targeted checks listed above
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge

Stack context: #5592 was merged into `pap-9173-llm-wiki-rest` after
#5597 had already merged that branch to `master`, so this follow-up PR
is needed to carry the plugin package itself into `master`.

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-05-11 20:45:41 -05:00

3747 lines
151 KiB
TypeScript

import { readFileSync } from "node:fs";
import { createElement } from "react";
import { renderToStaticMarkup } from "react-dom/server";
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import { createTestHarness } from "@paperclipai/plugin-sdk/testing";
import type { Agent, Issue, PluginManagedRoutineResolution, Project } from "@paperclipai/plugin-sdk";
import manifest, {
CURSOR_WINDOW_ROUTINE_KEY,
INDEX_REFRESH_ROUTINE_KEY,
NIGHTLY_LINT_ROUTINE_KEY,
PAPERCLIP_DISTILL_SKILL_KEY,
WIKI_MAINTAINER_AGENT_KEY,
WIKI_MAINTAINER_SKILL_CANONICAL_KEY,
WIKI_MAINTAINER_SKILL_KEY,
WIKI_MANAGED_SKILL_CANONICAL_KEYS,
WIKI_MANAGED_SKILL_KEYS,
WIKI_MAINTENANCE_ROUTINE_KEYS,
WIKI_PROJECT_KEY,
} from "../src/manifest.js";
import {
DEFAULT_AGENT_INSTRUCTION_FILES,
DEFAULT_AGENT_INSTRUCTIONS,
DEFAULT_IDEA,
DEFAULT_INDEX,
DEFAULT_LOG,
DEFAULT_WIKI_SCHEMA,
KARPATHY_LLM_WIKI_GIST_URL,
LINT_PROMPT,
QUERY_PROMPT,
} from "../src/templates.js";
import { SettingsPage, SidebarLink, WikiPage, WikiRouteSidebar } from "../src/ui/index.js";
import plugin from "../src/worker.js";
import { OPERATION_ORIGIN_KIND, type WikiSkillResource } from "../src/wiki.js";
const COMPANY_ID = "11111111-1111-4111-8111-111111111111";
const OTHER_COMPANY_ID = "99999999-9999-4999-8999-999999999999";
const ORIGINAL_DEPLOYMENT_MODE = process.env.PAPERCLIP_DEPLOYMENT_MODE;
const ORIGINAL_DEPLOYMENT_EXPOSURE = process.env.PAPERCLIP_DEPLOYMENT_EXPOSURE;
type TestBridgeGlobal = typeof globalThis & {
__paperclipPluginBridge__?: {
sdkUi?: Record<string, unknown>;
};
};
const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")) as {
dependencies?: Record<string, string>;
devDependencies?: Record<string, string>;
peerDependencies?: Record<string, string>;
};
const DEFAULT_MANAGED_SKILL = {
status: "resolved",
skillId: "skill-1",
resourceKey: WIKI_MAINTAINER_SKILL_KEY,
details: {
name: "LLM Wiki Maintainer",
key: WIKI_MAINTAINER_SKILL_CANONICAL_KEY,
description: "Use the LLM Wiki plugin tools to maintain a cited local company wiki.",
},
skill: {
id: "skill-1",
name: "LLM Wiki Maintainer",
key: WIKI_MAINTAINER_SKILL_CANONICAL_KEY,
description: "Use the LLM Wiki plugin tools to maintain a cited local company wiki.",
},
};
const DEFAULT_MANAGED_SKILLS = WIKI_MANAGED_SKILL_KEYS.map((skillKey, index) => ({
status: "resolved",
skillId: `skill-${index + 1}`,
resourceKey: skillKey,
details: skillKey === WIKI_MAINTAINER_SKILL_KEY
? DEFAULT_MANAGED_SKILL.details
: {
name: skillKey.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" "),
key: WIKI_MANAGED_SKILL_CANONICAL_KEYS[index],
description: null,
},
skill: skillKey === WIKI_MAINTAINER_SKILL_KEY
? DEFAULT_MANAGED_SKILL.skill
: {
id: `skill-${index + 1}`,
name: skillKey.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" "),
key: WIKI_MANAGED_SKILL_CANONICAL_KEYS[index],
description: null,
},
}));
let mockPathname = "/PAP/wiki";
let mockSearch = "";
let mockAutoSelectFile: string | null = null;
let mockNavigatedTo: string | null = null;
let mockOverviewFolder: Record<string, unknown> | null = null;
let mockSettingsFolder: Record<string, unknown> | null = null;
let mockSettingsManagedAgent: Record<string, unknown> | null = null;
let mockSettingsManagedRoutines: Array<Record<string, unknown>> = [];
let mockSettingsManagedSkills: Array<Record<string, unknown>> = [];
let mockDistillationOverviewData: Record<string, unknown> | null = null;
let mockPageContentsByPath: Record<string, string> = {};
let mockPageMetadataByPath: Record<string, {
backlinks?: string[];
sourceRefs?: Array<Record<string, unknown> | string>;
}> = {};
beforeEach(() => {
if (ORIGINAL_DEPLOYMENT_MODE == null) {
delete process.env.PAPERCLIP_DEPLOYMENT_MODE;
} else {
process.env.PAPERCLIP_DEPLOYMENT_MODE = ORIGINAL_DEPLOYMENT_MODE;
}
if (ORIGINAL_DEPLOYMENT_EXPOSURE == null) {
delete process.env.PAPERCLIP_DEPLOYMENT_EXPOSURE;
} else {
process.env.PAPERCLIP_DEPLOYMENT_EXPOSURE = ORIGINAL_DEPLOYMENT_EXPOSURE;
}
mockPathname = "/PAP/wiki";
mockSearch = "";
mockAutoSelectFile = null;
mockNavigatedTo = null;
mockOverviewFolder = null;
mockSettingsFolder = null;
mockSettingsManagedAgent = null;
mockSettingsManagedRoutines = [];
mockSettingsManagedSkills = [];
mockDistillationOverviewData = null;
mockPageContentsByPath = {};
mockPageMetadataByPath = {};
(globalThis as TestBridgeGlobal).__paperclipPluginBridge__ = {
sdkUi: {
usePluginData: (key: string, params?: Record<string, unknown>) => {
if (key === "overview") {
return {
data: {
status: "ok",
checkedAt: new Date().toISOString(),
wikiId: "default",
folder: mockOverviewFolder ?? {
configured: true,
path: "/tmp/company-wiki",
realPath: "/tmp/company-wiki",
access: "readWrite",
readable: true,
writable: true,
requiredDirectories: [],
requiredFiles: [],
missingDirectories: [],
missingFiles: [],
healthy: true,
problems: [],
checkedAt: new Date().toISOString(),
},
managedAgent: { status: "resolved", source: "managed", agentId: "agent-1", resourceKey: "wiki-maintainer", details: { name: "Wiki Maintainer", status: "idle", adapterType: "claude_local", icon: "book-open", urlKey: "wiki-maintainer" } },
managedProject: { status: "resolved", projectId: "project-1", details: { name: "LLM Wiki", status: "in_progress" } },
managedSkills: DEFAULT_MANAGED_SKILLS,
operationCount: 0,
eventIngestion: {
enabled: false,
sources: { issues: false, comments: false, documents: false },
wikiId: "default",
maxCharacters: 12000,
},
capabilities: [],
prompts: { query: QUERY_PROMPT, lint: LINT_PROMPT },
},
loading: false,
error: null,
refresh: () => undefined,
};
}
if (key === "spaces") {
return {
data: {
spaces: [
{
id: "space-default",
companyId: COMPANY_ID,
wikiId: "default",
slug: "default",
displayName: "default",
spaceType: "managed",
folderMode: "managed_subfolder",
rootFolderKey: "wiki-root",
pathPrefix: null,
configuredRootPath: null,
accessScope: "shared",
ownerUserId: null,
ownerAgentId: null,
teamKey: null,
settings: {},
status: "active",
createdAt: null,
updatedAt: null,
},
],
},
loading: false,
error: null,
refresh: () => undefined,
};
}
if (key === "pages") {
return {
data: {
pages: [
{
path: "wiki/concepts/sidebar-navigation.md",
title: "Sidebar navigation",
pageType: "concepts",
backlinkCount: 0,
sourceCount: 0,
contentHash: "abc123",
updatedAt: new Date().toISOString(),
},
],
sources: [
{
rawPath: "raw/sidebar-notes.md",
title: "Sidebar notes",
sourceType: "text",
url: null,
status: "captured",
createdAt: new Date().toISOString(),
},
],
},
loading: false,
error: null,
refresh: () => undefined,
};
}
if (key === "settings") {
return {
data: {
status: "ok",
checkedAt: new Date().toISOString(),
wikiId: "default",
folder: mockSettingsFolder ?? {
configured: true,
path: "/tmp/company-wiki",
realPath: "/tmp/company-wiki",
access: "readWrite",
readable: true,
writable: true,
requiredDirectories: [],
requiredFiles: [],
missingDirectories: [],
missingFiles: [],
healthy: true,
problems: [],
checkedAt: new Date().toISOString(),
},
managedAgent: mockSettingsManagedAgent ?? { status: "resolved", source: "managed", agentId: "agent-1", resourceKey: "wiki-maintainer", details: { name: "Wiki Maintainer", status: "idle", adapterType: "claude_local", icon: "book-open", urlKey: "wiki-maintainer" } },
managedProject: { status: "resolved", source: "managed", projectId: "project-1", resourceKey: "llm-wiki", details: { name: "LLM Wiki", status: "in_progress" } },
managedSkills: mockSettingsManagedSkills.length > 0 ? mockSettingsManagedSkills : DEFAULT_MANAGED_SKILLS,
managedRoutines: mockSettingsManagedRoutines,
managedRoutine: mockSettingsManagedRoutines[0] ?? null,
eventIngestion: {
enabled: false,
sources: { issues: false, comments: false, documents: false },
wikiId: "default",
maxCharacters: 12000,
},
agentOptions: [{ id: "agent-1", name: "Wiki Maintainer", status: "idle", icon: "book-open", urlKey: "wiki-maintainer" }],
projectOptions: [{ id: "project-1", name: "LLM Wiki", status: "in_progress", color: "#2563eb" }],
capabilities: [],
},
loading: false,
error: null,
refresh: () => undefined,
};
}
if (key === "space") {
return {
data: {
id: "space-default",
companyId: COMPANY_ID,
wikiId: "default",
slug: "default",
displayName: "default",
spaceType: "managed",
folderMode: "managed_subfolder",
rootFolderKey: "wiki-root",
pathPrefix: null,
configuredRootPath: null,
accessScope: "shared",
ownerUserId: null,
ownerAgentId: null,
teamKey: null,
settings: {},
status: "active",
createdAt: null,
updatedAt: null,
relativeRoot: "",
folder: {
configured: true,
path: "/tmp/company-wiki",
realPath: "/tmp/company-wiki",
access: "readWrite",
readable: true,
writable: true,
requiredDirectories: ["raw", "wiki"],
requiredFiles: ["AGENTS.md"],
missingDirectories: [],
missingFiles: [],
healthy: true,
problems: [],
checkedAt: new Date().toISOString(),
},
},
loading: false,
error: null,
refresh: () => undefined,
};
}
if (key === "distillation-overview") {
return {
data: mockDistillationOverviewData,
loading: false,
error: null,
refresh: () => undefined,
};
}
if (key === "page-content") {
const path = typeof params?.path === "string" ? params.path : "wiki/index.md";
const contents = mockPageContentsByPath[path] ?? (path === "AGENTS.md"
? DEFAULT_AGENT_INSTRUCTIONS
: path === "IDEA.md"
? DEFAULT_IDEA
: `# ${path}\n`);
return {
data: {
wikiId: "default",
path,
contents,
title: path === "AGENTS.md" ? "LLM Wiki Maintainer" : path.replace(/\.md$/, ""),
pageType: path === "AGENTS.md" ? null : "index",
backlinks: mockPageMetadataByPath[path]?.backlinks ?? [],
sourceRefs: mockPageMetadataByPath[path]?.sourceRefs ?? [],
updatedAt: null,
hash: "abc123",
},
loading: false,
error: null,
refresh: () => undefined,
};
}
return { data: null, loading: false, error: null, refresh: () => undefined };
},
usePluginAction: () => async () => ({}),
usePluginToast: () => () => null,
useHostNavigation: () => ({
resolveHref: (to: string) => `/PAP${to.startsWith("/") ? to : `/${to}`}`,
navigate: (to: string) => { mockNavigatedTo = to; },
linkProps: (to: string) => ({
href: `/PAP${to.startsWith("/") ? to : `/${to}`}`,
onClick: () => undefined,
}),
}),
useHostLocation: () => ({
pathname: mockPathname,
search: mockSearch,
hash: "",
}),
FileTree: (props: {
nodes: Array<{ name: string; path: string; kind: string; children?: Array<{ name: string; path: string; kind: string }> }>;
selectedFile?: string | null;
ariaLabel?: string;
wrapLabels?: boolean;
fileBadges?: Record<string, unknown>;
onSelectFile?: (path: string) => void;
}) => {
if (mockAutoSelectFile) props.onSelectFile?.(mockAutoSelectFile);
return createElement(
"div",
{
role: "tree",
"aria-label": props.ariaLabel,
"data-selected-file": props.selectedFile ?? "",
"data-wrap-labels": String(props.wrapLabels),
"data-has-file-badges": String(Boolean(props.fileBadges && Object.keys(props.fileBadges).length > 0)),
},
props.nodes.map((node) => createElement("div", { key: node.path }, node.name)),
);
},
IssuesList: (props: {
projectId?: string | null;
filters?: { originKindPrefix?: string };
}) => createElement(
"div",
{ "data-testid": "plugin-issues-list" },
`Issues table · ${props.projectId ?? "no-project"} · ${props.filters?.originKindPrefix ?? "no-origin-filter"}`,
),
MarkdownBlock: ({ content }: { content: string }) => createElement("div", { "data-testid": "markdown-block" }, content),
MarkdownEditor: ({ value, onChange }: { value: string; onChange: (value: string) => void }) => createElement("textarea", {
"data-testid": "markdown-editor",
value,
onChange: (event: { currentTarget: { value: string } }) => onChange(event.currentTarget.value),
}),
AssigneePicker: (props: {
value: string;
placeholder?: string;
onChange: (value: string, selection: { assigneeAgentId: string | null; assigneeUserId: string | null }) => void;
}) => createElement(
"button",
{
type: "button",
"data-testid": "assignee-picker",
onClick: () => props.onChange("agent:agent-1", { assigneeAgentId: "agent-1", assigneeUserId: null }),
},
props.value === "agent:agent-1" ? "Wiki Maintainer" : (props.placeholder ?? "Select assignee"),
),
ProjectPicker: (props: {
value: string;
placeholder?: string;
onChange: (projectId: string) => void;
}) => createElement(
"button",
{
type: "button",
"data-testid": "project-picker",
onClick: () => props.onChange("project-1"),
},
props.value === "project-1" ? "LLM Wiki" : (props.placeholder ?? "Project"),
),
ManagedRoutinesList: (props: {
routines: Array<{
key: string;
title: string;
href?: string | null;
projectId?: string | null;
assigneeAgentId?: string | null;
defaultDrift?: { changedFields: string[] } | null;
}>;
agents?: Array<{ id: string; name: string }>;
projects?: Array<{ id: string; name: string }>;
onReset?: (routine: { key: string; title: string }) => void;
}) => createElement(
"div",
{ "data-testid": "managed-routines-list" },
props.routines.map((routine) => {
const agent = props.agents?.find((item) => item.id === routine.assigneeAgentId);
const project = props.projects?.find((item) => item.id === routine.projectId);
return createElement(
"div",
{ key: routine.key },
createElement("span", null, routine.title),
createElement("button", null, "Run now"),
createElement("button", { role: "switch" }, "On"),
routine.href ? createElement("a", { href: `/PAP${routine.href}` }, "Configure") : null,
routine.defaultDrift?.changedFields.length
? createElement("span", null, `Plugin defaults changed: ${routine.defaultDrift.changedFields.join(", ")}`)
: null,
routine.defaultDrift?.changedFields.length && props.onReset
? createElement("button", null, "Reset")
: null,
createElement("span", null, `${project?.name ?? "No project"} · ${agent?.name ?? "No default agent"}`),
);
}),
),
},
};
});
afterEach(() => {
if (ORIGINAL_DEPLOYMENT_MODE == null) {
delete process.env.PAPERCLIP_DEPLOYMENT_MODE;
} else {
process.env.PAPERCLIP_DEPLOYMENT_MODE = ORIGINAL_DEPLOYMENT_MODE;
}
if (ORIGINAL_DEPLOYMENT_EXPOSURE == null) {
delete process.env.PAPERCLIP_DEPLOYMENT_EXPOSURE;
} else {
process.env.PAPERCLIP_DEPLOYMENT_EXPOSURE = ORIGINAL_DEPLOYMENT_EXPOSURE;
}
delete (globalThis as TestBridgeGlobal).__paperclipPluginBridge__;
});
function wikiMaintainerAgent(): Agent {
const now = new Date();
return {
id: "22222222-2222-4222-8222-222222222222",
companyId: COMPANY_ID,
name: "Wiki Maintainer",
urlKey: "wiki-maintainer",
role: "general",
title: "LLM Wiki Maintainer",
icon: "book-open",
status: "idle",
reportsTo: null,
capabilities: "Maintains the wiki",
adapterType: "claude_local",
adapterConfig: {},
runtimeConfig: {},
budgetMonthlyCents: 0,
spentMonthlyCents: 0,
pauseReason: null,
pausedAt: null,
permissions: { canCreateAgents: false },
lastHeartbeatAt: null,
metadata: {
paperclipManagedResource: {
pluginKey: manifest.id,
resourceKind: "agent",
resourceKey: "wiki-maintainer",
},
},
createdAt: now,
updatedAt: now,
};
}
function existingAgent(): Agent {
return {
...wikiMaintainerAgent(),
id: "44444444-4444-4444-8444-444444444444",
name: "Existing Knowledge Agent",
urlKey: "existing-knowledge-agent",
title: "Knowledge Agent",
metadata: {},
};
}
function existingProject(): Project {
const now = new Date();
return {
id: "55555555-5555-4555-8555-555555555555",
companyId: COMPANY_ID,
urlKey: "existing-wiki-project",
goalId: null,
goalIds: [],
goals: [],
name: "Existing Wiki Project",
description: "Existing project selected for wiki operations.",
status: "in_progress",
leadAgentId: null,
targetDate: null,
color: "#0f766e",
env: null,
pauseReason: null,
pausedAt: null,
executionWorkspacePolicy: null,
codebase: {
workspaceId: null,
repoUrl: null,
repoRef: null,
defaultRef: null,
repoName: null,
localFolder: null,
managedFolder: "/tmp/existing-wiki-project",
effectiveLocalFolder: "/tmp/existing-wiki-project",
origin: "managed_checkout",
},
workspaces: [],
primaryWorkspace: null,
managedByPlugin: null,
archivedAt: null,
createdAt: now,
updatedAt: now,
};
}
function paperclipIssue(overrides: Partial<Issue> = {}): Issue {
const now = new Date();
return {
id: "66666666-6666-4666-8666-666666666666",
companyId: COMPANY_ID,
projectId: null,
projectWorkspaceId: null,
goalId: null,
parentId: null,
title: "Design event ingestion controls",
description: "Decide which Paperclip issues, comments, and documents can be ingested into the wiki.",
status: "todo",
workMode: "standard",
priority: "medium",
assigneeAgentId: null,
assigneeUserId: null,
checkoutRunId: null,
executionRunId: null,
executionAgentNameKey: null,
executionLockedAt: null,
createdByAgentId: null,
createdByUserId: null,
issueNumber: 3204,
identifier: "PAP-3204",
originId: null,
originRunId: null,
originFingerprint: null,
requestDepth: 0,
billingCode: null,
assigneeAdapterOverrides: null,
executionPolicy: null,
executionState: null,
executionWorkspaceId: null,
executionWorkspacePreference: null,
executionWorkspaceSettings: null,
startedAt: null,
completedAt: null,
cancelledAt: null,
hiddenAt: null,
createdAt: now,
updatedAt: now,
...overrides,
};
}
function wikiSpaceRow(space: Record<string, unknown>) {
return {
id: space.id,
company_id: space.companyId ?? COMPANY_ID,
wiki_id: space.wikiId ?? "default",
slug: space.slug,
display_name: space.displayName,
space_type: space.spaceType ?? "local_folder",
folder_mode: space.folderMode ?? "managed_subfolder",
root_folder_key: space.rootFolderKey ?? "wiki-root",
path_prefix: space.pathPrefix ?? `spaces/${space.slug}`,
configured_root_path: space.configuredRootPath ?? null,
access_scope: space.accessScope ?? "shared",
owner_user_id: space.ownerUserId ?? null,
owner_agent_id: space.ownerAgentId ?? null,
team_key: space.teamKey ?? null,
settings: space.settings ?? {},
status: space.status ?? "active",
created_at: space.createdAt ?? null,
updated_at: space.updatedAt ?? null,
};
}
function defaultWikiSpaceRow() {
return wikiSpaceRow({
id: "77777777-7777-4777-8777-7777777777d0",
companyId: COMPANY_ID,
wikiId: "default",
slug: "default",
displayName: "default",
pathPrefix: null,
accessScope: "shared",
settings: {},
});
}
function mockPersistedWikiSpace(harness: ReturnType<typeof createTestHarness>, space: Record<string, unknown>) {
const row = wikiSpaceRow(space);
const originalQuery = harness.ctx.db.query.bind(harness.ctx.db);
harness.ctx.db.query = async <T,>(sql: string, params?: unknown[]) => {
if (sql.includes("wiki_spaces") && params?.[2] === row.slug) {
return [row] as T[];
}
if (sql.includes("wiki_spaces") && sql.includes("ORDER BY CASE WHEN slug = 'default'")) {
return [defaultWikiSpaceRow(), row] as T[];
}
return originalQuery<T>(sql, params);
};
}
describe("LLM Wiki plugin scaffold", () => {
it("declares standalone plugin surfaces without core wiki coupling", () => {
expect(manifest.id).toBe("paperclipai.plugin-llm-wiki");
expect(manifest.entrypoints.worker).toBe("./dist/worker.js");
expect(manifest.entrypoints.ui).toBe("./dist/ui");
expect(manifest.database?.namespaceSlug).toBe("llm_wiki");
expect(manifest.localFolders?.[0]?.requiredDirectories).toContain("wiki/projects");
expect(manifest.localFolders?.[0]?.requiredDirectories).not.toContain("projects");
expect(manifest.localFolders?.[0]?.requiredFiles).toEqual([
"AGENTS.md",
"IDEA.md",
"wiki/index.md",
"wiki/log.md",
]);
expect(manifest.agents?.[0]?.agentKey).toBe("wiki-maintainer");
expect(manifest.agents?.[0]?.adapterType).toBe("claude_local");
expect(manifest.agents?.[0]?.adapterConfig).toMatchObject({
dangerouslySkipPermissions: false,
dangerouslyBypassApprovalsAndSandbox: false,
sandbox: true,
});
expect(manifest.agents?.[0]?.instructions?.entryFile).toBe("AGENTS.md");
expect(manifest.agents?.[0]?.instructions?.content).toContain("You are the maintainer of this personal wiki");
expect(manifest.agents?.[0]?.instructions?.files?.["AGENTS.md"]).toContain("{{localFolders.wiki-root.path}}");
expect(manifest.agents?.[0]?.instructions?.assetPath).toBe("agents/wiki-maintainer");
expect(manifest.projects?.[0]?.projectKey).toBe("llm-wiki");
expect(manifest.routines?.map((routine) => routine.routineKey)).toEqual([
CURSOR_WINDOW_ROUTINE_KEY,
NIGHTLY_LINT_ROUTINE_KEY,
INDEX_REFRESH_ROUTINE_KEY,
]);
expect(manifest.routines).toEqual(
WIKI_MAINTENANCE_ROUTINE_KEYS.map((routineKey) => expect.objectContaining({
routineKey,
assigneeRef: { resourceKind: "agent", resourceKey: WIKI_MAINTAINER_AGENT_KEY },
projectRef: { resourceKind: "project", resourceKey: WIKI_PROJECT_KEY },
concurrencyPolicy: "skip_if_active",
catchUpPolicy: "skip_missed",
issueTemplate: expect.objectContaining({
surfaceVisibility: "plugin_operation",
billingCode: expect.stringMatching(/^plugin-llm-wiki:/),
}),
})),
);
for (const routine of manifest.routines ?? []) {
expect(routine.description).toContain("Run procedure:");
expect(routine.description).toContain("Target space: default (slug: default)");
expect(routine.description).toContain("spaceSlug `default`");
expect(routine.description).toContain("AGENTS.md");
expect(routine.description).toContain("wiki/log.md");
}
expect(manifest.tools?.map((tool) => tool.name)).toEqual([
"wiki_search",
"wiki_read_page",
"wiki_write_page",
"wiki_propose_patch",
"wiki_list_sources",
"wiki_read_source",
"wiki_append_log",
"wiki_update_index",
"wiki_list_backlinks",
"wiki_list_pages",
]);
expect(manifest.ui?.slots?.map((slot) => slot.type)).toEqual([
"sidebar",
"page",
"routeSidebar",
]);
expect(manifest.capabilities).not.toContain("instance.settings.register");
expect(manifest.instanceConfigSchema).toBeUndefined();
const routeSidebarSlot = manifest.ui?.slots?.find((slot) => slot.type === "routeSidebar");
expect(routeSidebarSlot).toMatchObject({
id: "wiki-route-sidebar",
exportName: "WikiRouteSidebar",
routePath: "wiki",
});
expect(packageJson.dependencies).toBeUndefined();
expect(packageJson.devDependencies?.react).toBeUndefined();
expect(packageJson.devDependencies?.["react-dom"]).toBeDefined();
expect(packageJson.devDependencies?.["@types/react-dom"]).toBeDefined();
expect(packageJson.peerDependencies?.react).toBe(">=18");
});
it("renders a host-aligned sidebar link with an open-book icon", () => {
const markup = renderToStaticMarkup(createElement(SidebarLink, {
context: { companyId: COMPANY_ID, companyPrefix: "PAP" },
} as never));
expect(markup).toContain('href="/PAP/wiki"');
expect(markup).toContain("gap-2.5 px-3 py-2 text-[13px] font-medium");
expect(markup).toContain("hover:bg-accent/50 hover:text-foreground");
expect(markup).toContain("<svg");
expect(markup).toContain("M12 7v14");
expect(markup).not.toContain("Wiki plugin");
expect(markup).not.toContain("border-radius:999");
expect(markup).not.toContain("📖");
});
it("ships Karpathy-pattern schema and workflow prompts by default", () => {
expect(DEFAULT_WIKI_SCHEMA).toContain("You are the maintainer of this personal wiki");
expect(DEFAULT_WIKI_SCHEMA).toContain("raw/");
expect(DEFAULT_WIKI_SCHEMA).toContain("wiki/projects/<project-slug>/standup.md");
expect(DEFAULT_WIKI_SCHEMA).toContain("wiki/projects/<project-slug>/index.md");
expect(DEFAULT_WIKI_SCHEMA).toContain("Do not create a top-level `projects/` directory");
expect(DEFAULT_WIKI_SCHEMA).not.toContain("\n├── projects/");
expect(DEFAULT_WIKI_SCHEMA).toContain("wiki/");
expect(DEFAULT_WIKI_SCHEMA).toContain("AGENTS.md");
expect(DEFAULT_IDEA).toContain("persistent, compounding artifact");
expect(DEFAULT_AGENT_INSTRUCTIONS).toContain("You are the maintainer of this personal wiki");
expect(DEFAULT_AGENT_INSTRUCTIONS).toContain("ingest, query, lint, index, or maintenance work");
expect(DEFAULT_AGENT_INSTRUCTIONS).toContain("dedicated LLM Wiki skill installed on this agent");
expect(DEFAULT_AGENT_INSTRUCTIONS).not.toContain("skills/<name>/SKILL.md");
expect(DEFAULT_AGENT_INSTRUCTION_FILES["skills/wiki-ingest/SKILL.md"]).toBeUndefined();
expect(manifest.skills?.map((skill) => skill.skillKey)).toEqual([...WIKI_MANAGED_SKILL_KEYS]);
expect(manifest.agents?.[0]?.adapterConfig?.paperclipSkillSync).toEqual({
desiredSkills: WIKI_MANAGED_SKILL_CANONICAL_KEYS,
});
expect(QUERY_PROMPT).toContain("wiki-query skill");
expect(QUERY_PROMPT).not.toContain("skills/wiki-query/SKILL.md");
expect(QUERY_PROMPT).toContain("filed back into wiki/");
expect(LINT_PROMPT).toContain("wiki-lint skill");
expect(LINT_PROMPT).not.toContain("skills/wiki-lint/SKILL.md");
expect(LINT_PROMPT).toContain("severity");
});
it("renders the route-scoped Wiki sidebar with tool actions, page navigation, and a back link", () => {
const markup = renderToStaticMarkup(createElement(WikiRouteSidebar, {
context: { companyId: COMPANY_ID, companyPrefix: "PAP" },
} as never));
expect(markup).toContain('href="/PAP/dashboard"');
expect(markup).toContain("PAP");
expect(markup).toContain('href="/PAP/wiki/query"');
expect(markup).not.toContain('href="/PAP/wiki/lint"');
expect(markup).toContain('href="/PAP/wiki/history"');
expect(markup).toContain('href="/PAP/wiki/settings"');
expect(markup).not.toContain('href="/PAP/wiki/operations"');
// Add Content reuses the legacy /wiki/ingest route so deep links still work.
expect(markup).toContain('href="/PAP/wiki/ingest"');
expect(markup).toContain('aria-label="Wiki primary"');
expect(markup).toContain('aria-label="Wiki secondary"');
for (const label of ["Ask", "Add Content", "History", "Settings", "Shared Spaces", "default", "raw", "wiki", "AGENTS.md", "IDEA.md"]) {
expect(markup).toContain(label);
}
expect(markup).not.toContain(">Lint</span>");
expect(markup).not.toContain(">Ingest</span>");
expect(markup).not.toContain(">Operations</span>");
expect(markup).not.toContain('text-sm font-bold text-foreground">Wiki');
expect(markup).not.toContain("Browse");
expect(markup).not.toContain(">Query<");
expect(markup).toContain('role="tree"');
expect(markup).toContain('data-selected-file=""');
expect(markup).toContain('data-wrap-labels="false"');
expect(markup).toContain('data-has-file-badges="false"');
});
it("routes legacy Wiki operations URLs to the History issue table", () => {
mockPathname = "/PAP/wiki/operations";
const markup = renderToStaticMarkup(createElement(WikiPage, {
context: { companyId: COMPANY_ID, companyPrefix: "PAP" },
} as never));
expect(markup).toContain("Issues table · project-1 · plugin:paperclipai.plugin-llm-wiki:operation");
expect(markup).not.toContain("Recent runs");
expect(markup).not.toContain(">Operations</h2>");
});
it("loads AGENTS.md from the Wiki page and exposes an edit affordance", () => {
mockPathname = "/PAP/wiki/page/templates/AGENTS.md";
const markup = renderToStaticMarkup(createElement(WikiPage, {
context: { companyId: COMPANY_ID, companyPrefix: "PAP" },
} as never));
expect(markup).toContain("AGENTS");
expect(markup).toContain(">AGENTS.md</h1>");
expect(markup).not.toContain(">LLM Wiki Maintainer</h1>");
expect(markup).toContain("You are the maintainer of this personal wiki");
expect(markup).toContain("wiki-root `AGENTS.md`");
expect(markup).toContain("Edit page");
expect(markup).toContain("Updated —");
expect(markup).not.toContain("0 backlinks");
expect(markup).not.toContain("0 sources");
expect(markup).not.toContain("abc123");
expect(markup).not.toContain("+ Ingest");
expect(markup).not.toContain("Folder healthy");
});
it("does not render page footer sources and backlinks", () => {
mockPathname = "/PAP/wiki/page/wiki/projects/control-plane/index.md";
mockPageContentsByPath["wiki/projects/control-plane/index.md"] = "# Control plane\n\nCurrent project state.";
mockPageMetadataByPath["wiki/projects/control-plane/index.md"] = {
backlinks: ["wiki/backlinks/hidden-footer-link.md"],
sourceRefs: [{ kind: "issue", issueIdentifier: "PAP-FOOTER-1" }],
};
const markup = renderToStaticMarkup(createElement(WikiPage, {
context: { companyId: COMPANY_ID, companyPrefix: "PAP" },
} as never));
expect(markup).toContain("Current project state.");
expect(markup).not.toContain(">Sources</");
expect(markup).not.toContain(">Backlinks</");
expect(markup).not.toContain("PAP-FOOTER-1");
expect(markup).not.toContain("hidden-footer-link");
});
it("renders YAML frontmatter as foldable properties without duplicating title", () => {
mockPathname = "/PAP/wiki/page/wiki/concepts/sidebar-navigation.md";
mockPageContentsByPath["wiki/concepts/sidebar-navigation.md"] = `---
title: Sidebar navigation
type: concept
tags: [paperclip, wiki]
sources:
- raw/sidebar-notes.md
created: 2026-05-04
updated: 2026-05-04
---
# Sidebar navigation
Route sidebar state stays attached to the selected wiki page.
`;
const markup = renderToStaticMarkup(createElement(WikiPage, {
context: { companyId: COMPANY_ID, companyPrefix: "PAP" },
} as never));
expect(markup).toContain("<summary");
expect(markup).toContain("Properties");
expect(markup).toContain(">type</dt>");
expect(markup).toContain("concept");
expect(markup).toContain(">tags</dt>");
expect(markup).toContain("paperclip");
expect(markup).toContain("wiki");
expect(markup).toContain(">sources</dt>");
expect(markup).toContain("raw/sidebar-notes.md");
expect(markup).toContain("Route sidebar state");
expect(markup).not.toContain("title: Sidebar navigation");
expect(markup).not.toContain("title</dt>");
expect(markup).not.toContain("---");
});
it("renders a foldable on-this-page pane from wiki page headings", () => {
mockPathname = "/PAP/wiki/page/wiki/concepts/sidebar-navigation.md";
mockPageContentsByPath["wiki/concepts/sidebar-navigation.md"] = `# Sidebar navigation
## Why it matters
Route sidebar state stays attached to the selected wiki page.
### Deep link behavior
Wiki links preserve normal browser navigation.
\`\`\`md
## Ignored code heading
\`\`\`
## Why it matters
Duplicate headings receive stable suffixes.
`;
const markup = renderToStaticMarkup(createElement(WikiPage, {
context: { companyId: COMPANY_ID, companyPrefix: "PAP" },
} as never));
expect(markup).toContain('aria-label="On this page"');
expect(markup).toContain('aria-expanded="true"');
expect(markup).toContain('aria-current="location"');
expect(markup).toContain('href="#why-it-matters"');
expect(markup).toContain('href="#deep-link-behavior"');
expect(markup).toContain('href="#why-it-matters-2"');
expect(markup).not.toContain('href="#ignored-code-heading"');
const tocMarkup = markup.slice(
markup.indexOf('aria-label="On this page"'),
markup.indexOf("</aside>", markup.indexOf('aria-label="On this page"')),
);
expect(tocMarkup).toContain("position:sticky");
expect(tocMarkup).toContain("top:88px");
expect(tocMarkup).not.toContain("background:color-mix");
expect(tocMarkup).not.toContain("border-radius");
});
it("shows folder repair instead of reading pages when the wiki root is stale", () => {
mockPathname = "/PAP/wiki/page/AGENTS.md";
mockOverviewFolder = {
configured: true,
path: "/tmp/deleted-wiki-root",
realPath: null,
access: "readWrite",
readable: false,
writable: false,
requiredDirectories: ["raw", "wiki"],
requiredFiles: ["AGENTS.md"],
missingDirectories: ["raw", "wiki"],
missingFiles: ["AGENTS.md"],
healthy: false,
problems: [
{ code: "missing", message: "Configured local folder cannot be inspected.", path: "/tmp/deleted-wiki-root" },
],
checkedAt: new Date().toISOString(),
};
const markup = renderToStaticMarkup(createElement(WikiPage, {
context: { companyId: COMPANY_ID, companyPrefix: "PAP" },
} as never));
expect(markup).toContain("Repair wiki root folder");
expect(markup).toContain("/tmp/deleted-wiki-root");
expect(markup).toContain("Configured local folder cannot be inspected.");
expect(markup).toContain("Repair &amp; bootstrap");
expect(markup).not.toContain("Failed to read AGENTS.md");
expect(markup).not.toContain(">AGENTS.md</h1>");
});
it("serializes root template pages as regular path segments", () => {
mockAutoSelectFile = "AGENTS.md";
renderToStaticMarkup(createElement(WikiRouteSidebar, {
context: { companyId: COMPANY_ID, companyPrefix: "PAP" },
} as never));
expect(mockNavigatedTo).toBe("/wiki/page/AGENTS.md");
});
it("highlights Settings for legacy lint links after lint moved under Settings", () => {
mockPathname = "/PAP/wiki/lint";
const markup = renderToStaticMarkup(createElement(WikiRouteSidebar, {
context: { companyId: COMPANY_ID, companyPrefix: "PAP" },
} as never));
expect(markup).not.toContain('href="/PAP/wiki/lint"');
const settingsAnchor = markup.match(/<a[^>]*href="\/PAP\/wiki\/settings"[^>]*>/);
expect(settingsAnchor?.[0]).toContain('aria-current="page"');
expect(settingsAnchor?.[0]).toContain("text-foreground");
expect(settingsAnchor?.[0]).not.toContain("bg-accent");
const askAnchor = markup.match(/<a[^>]*href="\/PAP\/wiki\/query"[^>]*>/);
expect(askAnchor?.[0]).not.toContain('aria-current="page"');
});
it("renders the maintainer settings without plugin metadata or inline AGENTS.md editing", () => {
mockPathname = "/PAP/wiki/settings/maintainer";
const markup = renderToStaticMarkup(createElement(WikiPage, {
context: { companyId: COMPANY_ID, companyPrefix: "PAP" },
} as never));
expect(markup).toContain("Wiki Maintainer");
expect(markup).toContain("Adapter: claude local");
expect(markup).toContain("Maintainer");
expect(markup).toContain("Repair");
expect(markup).toContain("Reset to defaults");
expect(markup).not.toContain("Provided maintainer");
expect(markup).not.toContain("Managed by LLM Wiki");
expect(markup).not.toContain("Suggested default");
expect(markup).not.toContain("AGENT INSTRUCTIONS");
expect(markup).not.toContain("Stable key");
expect(markup).not.toContain("Plugin managed default");
});
it("recommends approval when the wiki maintainer is pending board approval", () => {
mockPathname = "/PAP/wiki/settings/maintainer";
mockSettingsManagedAgent = {
status: "created",
source: "managed",
agentId: "agent-1",
resourceKey: "wiki-maintainer",
details: { name: "Wiki Maintainer", status: "pending_approval", adapterType: "claude_local", icon: "book-open", urlKey: "wiki-maintainer" },
};
const markup = renderToStaticMarkup(createElement(WikiPage, {
context: { companyId: COMPANY_ID, companyPrefix: "PAP" },
} as never));
expect(markup).toContain("pending approval");
expect(markup).toContain("Approve the agent");
expect(markup).toContain("Adapter: claude local");
});
it("renders root settings as a compact health checklist with the shared path picker", () => {
mockPathname = "/PAP/wiki/settings";
const markup = renderToStaticMarkup(createElement(WikiPage, {
context: { companyId: COMPANY_ID, companyPrefix: "PAP" },
} as never));
expect(markup).toContain(">Setup</");
expect(markup).toContain("Base Folder");
expect(markup).toContain("Managed Agents");
expect(markup).toContain("Managed Skills");
expect(markup).toContain("Managed Projects");
expect(markup).toContain("Managed Routines");
expect(markup.indexOf(">Managed Agents</h2>")).toBeLessThan(markup.indexOf(">Managed Skills</h2>"));
expect(markup.indexOf(">Managed Skills</h2>")).toBeLessThan(markup.indexOf(">Managed Projects</h2>"));
expect(markup.indexOf(">Managed Projects</h2>")).toBeLessThan(markup.indexOf(">Managed Routines</h2>"));
expect(markup).toContain("Adapter: claude local");
expect(markup).toContain("Status: in progress");
expect(markup).toContain("Wiki root health checklist");
expect(markup).toContain("Health check");
expect(markup).toContain("Wiki agents health checklist");
expect(markup).toContain("Wiki routines health checklist");
expect(markup).toContain("Wiki skills health checklist");
expect(markup).toContain("Wiki projects health checklist");
const routineChecklistStart = markup.indexOf('aria-label="Wiki routines health checklist"');
const routineChecklist = markup.slice(routineChecklistStart);
expect(routineChecklist).toContain("left:8px");
expect(routineChecklist).toContain("background:oklch(0.38 0.09 145)");
expect(routineChecklist).toContain("Process LLM Wiki updates");
expect(routineChecklist).toContain("Run LLM Wiki lint");
expect(routineChecklist).toContain("Refresh LLM Wiki index");
expect(routineChecklist).not.toContain("Wiki Maintainer");
expect(routineChecklist).not.toContain("LLM Wiki project");
const skillChecklistStart = markup.indexOf('aria-label="Wiki skills health checklist"');
const skillChecklist = markup.slice(skillChecklistStart, markup.indexOf('aria-label="Wiki projects health checklist"'));
expect(skillChecklist).toContain("left:8px");
expect(skillChecklist).toContain("background:oklch(0.38 0.09 145)");
for (const headline of ["Path configured", "Readable", "Writable", "Baseline files", "Wiki folders"]) {
expect(markup).toContain(headline);
}
expect(markup).toContain("Local wiki folder");
expect(markup).toContain("Choose");
expect(markup).toContain("Apply path");
expect(markup).not.toContain("AGENTS.md, IDEA.md");
expect(markup).not.toContain("Ready</span>");
expect(markup).not.toContain("Needs attention</span>");
expect(markup).not.toContain("wiki/sources/");
expect(markup).not.toContain("wiki/entities/");
expect(markup).not.toContain("Wiki root folder");
expect(markup).not.toContain("Provided maintainer");
expect(markup).not.toContain(">Project</span>");
expect(markup).toContain("Ingestion Settings");
});
it("shows a top-level fix-all banner when settings configuration has errors", () => {
mockPathname = "/PAP/wiki/settings";
mockSettingsFolder = {
configured: true,
path: "/tmp/company-wiki",
realPath: "/tmp/company-wiki",
access: "readWrite",
readable: true,
writable: true,
requiredDirectories: ["raw", "wiki"],
requiredFiles: ["AGENTS.md"],
missingDirectories: ["raw"],
missingFiles: ["AGENTS.md"],
healthy: false,
problems: [
{ code: "missing_directory", message: "Required directory is missing.", path: "raw" },
{ code: "missing_file", message: "Required file is missing.", path: "AGENTS.md" },
],
checkedAt: new Date().toISOString(),
};
const markup = renderToStaticMarkup(createElement(WikiPage, {
context: { companyId: COMPANY_ID, companyPrefix: "PAP" },
} as never));
expect(markup).toContain("configuration errors detected, fix them all?");
expect(markup).toContain("Wiki root folder");
expect(markup).toContain("Managed routines");
expect(markup).toContain("need attention.");
expect(markup).toContain("Fix them all");
expect(markup.indexOf("configuration errors detected")).toBeLessThan(markup.indexOf(">Base Folder</"));
});
it("shows missing managed skills in setup health with a re-sync action", () => {
mockPathname = "/PAP/wiki/settings";
mockSettingsManagedSkills = [{
status: "missing",
skillId: null,
resourceKey: WIKI_MAINTAINER_SKILL_KEY,
details: {
name: "LLM Wiki Maintainer",
key: WIKI_MAINTAINER_SKILL_CANONICAL_KEY,
description: null,
},
}];
const markup = renderToStaticMarkup(createElement(WikiPage, {
context: { companyId: COMPANY_ID, companyPrefix: "PAP" },
} as never));
expect(markup).toContain("Managed Skills");
expect(markup).toContain("skill issue(s) need attention");
expect(markup).toContain("LLM Wiki Maintainer is not installed in the company skill library.");
expect(markup).toContain("Re-sync skills");
});
it("shows managed skill default drift in setup health", () => {
mockPathname = "/PAP/wiki/settings";
mockSettingsManagedSkills = [{
status: "resolved",
skillId: "skill-1",
resourceKey: WIKI_MAINTAINER_SKILL_KEY,
defaultDrift: { changedFiles: ["SKILL.md"] },
details: {
name: "LLM Wiki Maintainer",
key: WIKI_MAINTAINER_SKILL_CANONICAL_KEY,
description: null,
},
}];
const markup = renderToStaticMarkup(createElement(WikiPage, {
context: { companyId: COMPANY_ID, companyPrefix: "PAP" },
} as never));
expect(markup).toContain("skill issue(s) need attention");
expect(markup).toContain("LLM Wiki Maintainer differs from the plugin default: SKILL.md.");
expect(markup).toContain("Re-sync skills");
});
it("renders host settings directly as the Setup page without an extra plugin heading", () => {
const markup = renderToStaticMarkup(createElement(SettingsPage, {
context: { companyId: COMPANY_ID, companyPrefix: "PAP" },
} as never));
expect(markup).toContain(">Setup</h1>");
expect(markup).toContain("Base Folder");
expect(markup).not.toContain("LLM Wiki Settings");
expect(markup).not.toContain("These settings live inside the plugin");
});
it("renders project settings as a project picker without managed-resource metadata", () => {
mockPathname = "/PAP/wiki/settings/project";
const markup = renderToStaticMarkup(createElement(WikiPage, {
context: { companyId: COMPANY_ID, companyPrefix: "PAP" },
} as never));
expect(markup).toContain("Use existing project");
expect(markup).toContain("LLM Wiki");
expect(markup).toContain("Save project");
expect(markup).toContain("Open project");
expect(markup).toContain("Repair / reconcile");
expect(markup).toContain("Reset to plugin defaults");
expect(markup).not.toContain("Managed by LLM Wiki");
expect(markup).not.toContain("Operations project binding");
expect(markup).not.toContain("Stable key");
expect(markup).not.toContain("Resolved project");
expect(markup).toContain("Status: in progress");
expect(markup).not.toContain("Plugin managed default");
});
it("renders space settings with health line styling and disabled access controls", () => {
mockPathname = "/PAP/wiki/settings/spaces/default";
const markup = renderToStaticMarkup(createElement(WikiPage, {
context: { companyId: COMPANY_ID, companyPrefix: "PAP" },
} as never));
expect(markup).toContain("Space folder health checklist");
expect(markup).toContain("left:8px");
expect(markup).toContain("background:oklch(0.38 0.09 145)");
expect(markup).toContain("Folder readable");
expect(markup).toContain("raw/ present");
expect(markup).toContain("Access");
expect(markup).toContain("Coming soon");
expect(markup).not.toContain("Future enforcement");
expect(markup).not.toContain("stored only");
expect(markup).not.toContain("Permissions are stored but not enforced");
});
it("renders distillation settings with assigned-agent model selection and cheap path without budget controls", () => {
mockPathname = "/PAP/wiki/settings/distillation";
mockDistillationOverviewData = {
counts: { cursors: 1, runningRuns: 0, failedRuns24h: 0, reviewRequired: 0 },
cursors: [{
id: "cursor-1",
projectId: "project-1",
rootIssueId: null,
projectName: "Existing Wiki Project",
rootIssueIdentifier: null,
sourceScope: "project",
scopeKey: "project-1",
}],
runs: [],
};
const markup = renderToStaticMarkup(createElement(WikiPage, {
context: { companyId: COMPANY_ID, companyPrefix: "PAP" },
} as never));
expect(markup).toContain("Agent execution");
expect(markup).toContain("Assigned maintainer");
expect(markup).toContain("Wiki Maintainer · claude local");
expect(markup).toContain("Cheap path");
expect(markup).toContain("assigneeAdapterOverrides.modelProfile = cheap");
expect(markup).toContain("All sections — apply when source hash matches and confidence");
expect(markup).not.toContain("Per-task budget");
expect(markup).not.toContain("Project total budget");
expect(markup).not.toContain("/task");
expect(markup).not.toContain("Model lanes");
expect(markup).not.toContain("Claude Haiku");
expect(markup).not.toContain("Daily plugin cap");
expect(markup).not.toContain("Monthly plugin cap");
});
it("renders managed routines as normal routine rows with run, toggle, and configure controls", () => {
mockPathname = "/PAP/wiki/settings/routines";
mockSettingsManagedRoutines = [{
status: "resolved",
routineId: "routine-1",
resourceKey: "nightly-wiki-lint",
routine: {
id: "routine-1",
title: "Run LLM Wiki lint",
status: "active",
assigneeAgentId: "agent-1",
projectId: "project-1",
lastTriggeredAt: "2026-05-03T12:00:00Z",
managedByPlugin: { pluginDisplayName: "LLM Wiki", resourceKey: "nightly-wiki-lint" },
},
details: { cronExpression: "0 3 * * *" },
}];
const markup = renderToStaticMarkup(createElement(WikiPage, {
context: { companyId: COMPANY_ID, companyPrefix: "PAP" },
} as never));
expect(markup).toContain("Run LLM Wiki lint");
expect(markup).toContain("Run now");
expect(markup).toContain("Configure");
expect(markup).toContain("role=\"switch\"");
expect(markup).toContain("LLM Wiki · Wiki Maintainer");
expect(markup).toContain("href=\"/PAP/routines/routine-1\"");
});
it("alerts when managed routine defaults changed and offers a reset path", () => {
mockPathname = "/PAP/wiki/settings/routines";
mockSettingsManagedRoutines = [{
status: "resolved",
routineId: "routine-1",
resourceKey: "nightly-wiki-lint",
defaultDrift: {
changedFields: ["description"],
defaultTitle: "Run LLM Wiki lint",
defaultDescription: "Updated instructions",
},
routine: {
id: "routine-1",
title: "Run LLM Wiki lint",
status: "active",
assigneeAgentId: "agent-1",
projectId: "project-1",
managedByPlugin: { pluginDisplayName: "LLM Wiki", resourceKey: "nightly-wiki-lint" },
},
details: { cronExpression: "0 3 * * *" },
}];
const markup = renderToStaticMarkup(createElement(WikiPage, {
context: { companyId: COMPANY_ID, companyPrefix: "PAP" },
} as never));
expect(markup).toContain("Routine defaults changed");
expect(markup).toContain("Plugin defaults changed: description");
expect(markup).toContain(">Reset</button>");
});
it("shows managed agent instruction drift in the setup health check", () => {
mockPathname = "/PAP/wiki/settings";
mockSettingsManagedAgent = {
status: "resolved",
source: "managed",
agentId: "agent-1",
resourceKey: "wiki-maintainer",
defaultDrift: { entryFile: "AGENTS.md", changedFiles: ["AGENTS.md"] },
details: { name: "Wiki Maintainer", status: "idle", adapterType: "claude_local", icon: "book-open", urlKey: "wiki-maintainer" },
};
const markup = renderToStaticMarkup(createElement(WikiPage, {
context: { companyId: COMPANY_ID, companyPrefix: "PAP" },
} as never));
expect(markup).toContain("Wiki Maintainer instructions differ from the plugin default: AGENTS.md.");
expect(markup).toContain("Wiki Maintainer instruction defaults changed: AGENTS.md");
});
it("shows one routine repair warning instead of per-routine reconcile controls", () => {
mockPathname = "/PAP/wiki/settings/routines";
mockSettingsManagedRoutines = [{
status: "resolved",
routineId: "routine-1",
resourceKey: "nightly-wiki-lint",
routine: {
id: "routine-1",
title: "Run LLM Wiki lint",
status: "active",
assigneeAgentId: "other-agent",
projectId: "project-1",
managedByPlugin: { pluginDisplayName: "LLM Wiki", resourceKey: "nightly-wiki-lint" },
},
details: { cronExpression: "0 3 * * *" },
}];
const markup = renderToStaticMarkup(createElement(WikiPage, {
context: { companyId: COMPANY_ID, companyPrefix: "PAP" },
} as never));
expect(markup).toContain("Routine setup needs repair");
expect(markup).toContain("Fix routines");
expect(markup).toContain("not assigned to the Wiki Maintainer");
expect(markup).not.toContain("Plugin-managed routine defaults can be reconciled from here");
expect(markup).not.toContain(">Reconcile</button>");
expect(markup).not.toContain(">Reset</button>");
});
it("renders legacy lint routes inside the Wiki settings section", () => {
mockPathname = "/PAP/wiki/lint";
const markup = renderToStaticMarkup(createElement(WikiPage, {
context: { companyId: COMPANY_ID, companyPrefix: "PAP" },
} as never));
expect(markup).toContain("Run lint now");
expect(markup).toContain("Recent lint runs");
expect(markup).toContain("LLM Wiki settings sections");
});
it("does not expose IDEA.md pattern editing as a settings section", () => {
mockPathname = "/PAP/wiki/settings";
const markup = renderToStaticMarkup(createElement(WikiPage, {
context: { companyId: COMPANY_ID, companyPrefix: "PAP" },
} as never));
expect(markup).toContain("LLM Wiki settings sections");
expect(markup).not.toContain(">Pattern</span>");
expect(markup).not.toContain("Pattern · IDEA.md");
expect(markup).not.toContain("IDEA.md skeleton reference");
});
it("does not expose plugin capabilities as a settings section", () => {
mockPathname = "/PAP/wiki/settings";
const markup = renderToStaticMarkup(createElement(WikiPage, {
context: { companyId: COMPANY_ID, companyPrefix: "PAP" },
} as never));
expect(markup).toContain("LLM Wiki settings sections");
expect(markup).not.toContain("Plugin capabilities");
expect(markup).not.toContain("api.routes.register");
});
it("reconciles managed maintenance routines through stable agent and project refs", async () => {
const harness = createTestHarness({ manifest });
const writes: Array<{ path: string; contents: string }> = [];
harness.ctx.localFolders.writeTextAtomic = async (_companyId, _folderKey, relativePath, contents) => {
writes.push({ path: relativePath, contents });
return harness.ctx.localFolders.status(COMPANY_ID, "wiki-root");
};
await plugin.definition.setup(harness.ctx);
const missing = await harness.performAction<PluginManagedRoutineResolution>("reconcile-managed-routine", {
companyId: COMPANY_ID,
routineKey: NIGHTLY_LINT_ROUTINE_KEY,
});
expect(missing.status).toBe("missing_refs");
expect(missing.missingRefs).toEqual([
expect.objectContaining({ resourceKind: "agent", resourceKey: WIKI_MAINTAINER_AGENT_KEY }),
expect.objectContaining({ resourceKind: "project", resourceKey: WIKI_PROJECT_KEY }),
]);
await harness.performAction("bootstrap-root", { companyId: COMPANY_ID, path: "/tmp/company-wiki" });
const reconciled = await Promise.all(
WIKI_MAINTENANCE_ROUTINE_KEYS.map((routineKey) =>
harness.performAction<PluginManagedRoutineResolution>("reconcile-managed-routine", {
companyId: COMPANY_ID,
routineKey,
})),
);
expect(reconciled.map((routine) => routine.resourceKey)).toEqual([...WIKI_MAINTENANCE_ROUTINE_KEYS]);
expect(reconciled).toEqual(
expect.arrayContaining([
expect.objectContaining({
resourceKey: NIGHTLY_LINT_ROUTINE_KEY,
routine: expect.objectContaining({
projectId: expect.any(String),
assigneeAgentId: expect.any(String),
managedByPlugin: expect.objectContaining({
defaultsJson: expect.objectContaining({
issueTemplate: expect.objectContaining({ surfaceVisibility: "plugin_operation" }),
}),
}),
}),
}),
expect.objectContaining({ resourceKey: INDEX_REFRESH_ROUTINE_KEY, routineId: expect.any(String) }),
]),
);
});
it("requires an explicit managed routine key for single-routine actions", async () => {
const harness = createTestHarness({ manifest });
await plugin.definition.setup(harness.ctx);
await expect(harness.performAction("reconcile-managed-routine", {
companyId: COMPANY_ID,
})).rejects.toThrow("routineKey is required");
});
it("repairs all managed maintenance routines through one action", async () => {
const harness = createTestHarness({ manifest });
await plugin.definition.setup(harness.ctx);
await harness.performAction("bootstrap-root", { companyId: COMPANY_ID, path: "/tmp/company-wiki" });
const repaired = await harness.performAction<{
managedRoutines: PluginManagedRoutineResolution[];
}>("reconcile-managed-routines", { companyId: COMPANY_ID });
expect(repaired.managedRoutines).toHaveLength(WIKI_MAINTENANCE_ROUTINE_KEYS.length);
expect(repaired.managedRoutines.map((routine) => routine.resourceKey)).toEqual([...WIKI_MAINTENANCE_ROUTINE_KEYS]);
for (const routine of repaired.managedRoutines) {
expect(routine.routine).toEqual(expect.objectContaining({
assigneeAgentId: expect.any(String),
projectId: expect.any(String),
}));
expect(routine.missingRefs).toEqual([]);
}
});
it("installs and resets managed company skills through setup actions", async () => {
const harness = createTestHarness({ manifest });
await plugin.definition.setup(harness.ctx);
const before = await harness.getData<{ managedSkills: WikiSkillResource[] }>("settings", {
companyId: COMPANY_ID,
});
expect(before.managedSkills.map((skill) => skill.resourceKey)).toEqual([...WIKI_MANAGED_SKILL_KEYS]);
expect(before.managedSkills[0]).toMatchObject({
status: "missing",
skillId: null,
});
const repaired = await harness.performAction<{
managedSkills: WikiSkillResource[];
}>("reconcile-managed-skills", { companyId: COMPANY_ID });
expect(repaired.managedSkills).toHaveLength(WIKI_MANAGED_SKILL_KEYS.length);
expect(repaired.managedSkills[0]).toMatchObject({
status: "created",
skillId: expect.any(String),
resourceKey: WIKI_MAINTAINER_SKILL_KEY,
details: {
name: "LLM Wiki Maintainer",
key: WIKI_MAINTAINER_SKILL_CANONICAL_KEY,
},
});
const resolved = await harness.getData<{ managedSkills: WikiSkillResource[] }>("settings", {
companyId: COMPANY_ID,
});
expect(resolved.managedSkills[0]).toMatchObject({
status: "resolved",
resourceKey: WIKI_MAINTAINER_SKILL_KEY,
details: { key: WIKI_MAINTAINER_SKILL_CANONICAL_KEY },
});
const reset = await harness.performAction<{
managedSkills: WikiSkillResource[];
}>("reset-managed-skills", { companyId: COMPANY_ID });
expect(reset.managedSkills[0]).toMatchObject({
status: "reset",
skillId: expect.any(String),
resourceKey: WIKI_MAINTAINER_SKILL_KEY,
});
});
it("registers worker data, actions, and tools", async () => {
const harness = createTestHarness({ manifest });
await plugin.definition.setup(harness.ctx);
const overview = await harness.getData<{ status: string; operationCount: number; eventIngestion: { enabled: boolean } }>("overview", {
companyId: COMPANY_ID,
});
expect(overview.status).toBe("ok");
expect(overview.operationCount).toBe(0);
expect(overview.eventIngestion.enabled).toBe(false);
const pages = await harness.executeTool<{ content?: string }>("wiki_list_pages", {
companyId: COMPANY_ID,
wikiId: "default",
});
expect(pages.content).toBe("No pages indexed yet.");
});
it("filters stale page and raw source rows out of browse data", async () => {
const harness = createTestHarness({ manifest });
const files = new Map<string, string>([
["wiki/concepts/live.md", "# Live Page\n"],
["raw/live-source.md", "# Live Source\n"],
]);
const now = new Date().toISOString();
harness.ctx.localFolders.readText = async (_companyId, _folderKey, relativePath) => {
const contents = files.get(relativePath);
if (contents == null) throw new Error(`missing ${relativePath}`);
return contents;
};
harness.ctx.db.query = async <T = Record<string, unknown>>(sql: string, params?: unknown[]) => {
harness.dbQueries.push({ sql, params });
if (sql.includes("wiki_pages")) {
return [
{
path: "wiki/concepts/live.md",
title: "Live Page",
page_type: "concepts",
backlinks: [],
source_refs: [],
content_hash: "live",
updated_at: now,
},
{
path: "wiki/concepts/stale.md",
title: "Stale Page",
page_type: "concepts",
backlinks: [],
source_refs: [],
content_hash: "stale",
updated_at: now,
},
] as T[];
}
if (sql.includes("wiki_sources")) {
return [
{
raw_path: "raw/missing-source.md",
title: "Missing Source",
source_type: "text",
url: null,
status: "captured",
created_at: now,
},
{
raw_path: "raw/live-source.md",
title: "Live Source",
source_type: "text",
url: null,
status: "captured",
created_at: now,
},
] as T[];
}
return [];
};
await plugin.definition.setup(harness.ctx);
const result = await harness.getData<{
pages: Array<{ path: string }>;
sources: Array<{ rawPath: string }>;
}>("pages", {
companyId: COMPANY_ID,
wikiId: "default",
includeRaw: true,
});
expect(result.pages.map((page) => page.path)).toEqual(["wiki/concepts/live.md"]);
expect(result.sources.map((source) => source.rawPath)).toEqual(["raw/live-source.md"]);
});
it("includes local wiki files in browse data before metadata is indexed", async () => {
const harness = createTestHarness({ manifest });
const modifiedAt = new Date().toISOString();
harness.ctx.localFolders.list = async (_companyId, folderKey, options) => ({
folderKey,
relativePath: options?.relativePath ?? null,
truncated: false,
entries: options?.relativePath === "wiki"
? [
{ path: "wiki/concepts/agent-memory-layer.md", name: "agent-memory-layer.md", kind: "file", size: 12, modifiedAt },
{ path: "wiki/entities/paperclip.md", name: "paperclip.md", kind: "file", size: 10, modifiedAt },
{ path: "wiki/projects/llm-wiki/standup.md", name: "standup.md", kind: "file", size: 16, modifiedAt },
]
: [
{ path: "raw/2026-04-09-thomas-gieselmann-fundraising-call.md", name: "2026-04-09-thomas-gieselmann-fundraising-call.md", kind: "file", size: 14, modifiedAt },
],
});
harness.ctx.db.query = async <T = Record<string, unknown>>(sql: string, params?: unknown[]) => {
harness.dbQueries.push({ sql, params });
return [] as T[];
};
await plugin.definition.setup(harness.ctx);
const result = await harness.getData<{
pages: Array<{ path: string; title: string | null }>;
sources: Array<{ rawPath: string; title: string | null }>;
}>("pages", {
companyId: COMPANY_ID,
wikiId: "default",
includeRaw: true,
});
expect(result.pages).toEqual([
expect.objectContaining({ path: "wiki/concepts/agent-memory-layer.md", title: null }),
expect.objectContaining({ path: "wiki/entities/paperclip.md", title: null }),
expect.objectContaining({ path: "wiki/projects/llm-wiki/standup.md", title: null }),
]);
expect(result.sources).toEqual([
expect.objectContaining({ rawPath: "raw/2026-04-09-thomas-gieselmann-fundraising-call.md", title: null }),
]);
});
it("does not ingest Paperclip events until operator controls enable them", async () => {
const harness = createTestHarness({ manifest });
const issue = paperclipIssue();
harness.seed({ issues: [issue] });
const writes: Array<{ path: string; contents: string }> = [];
harness.ctx.localFolders.writeTextAtomic = async (_companyId, _folderKey, relativePath, contents) => {
writes.push({ path: relativePath, contents });
return harness.ctx.localFolders.status(COMPANY_ID, "wiki-root");
};
await plugin.definition.setup(harness.ctx);
await harness.emit("issue.created", { identifier: issue.identifier }, {
companyId: COMPANY_ID,
entityId: issue.id,
entityType: "issue",
eventId: "event-disabled-issue-created",
});
expect(writes).toHaveLength(0);
expect(harness.dbExecutes.some((execute) => execute.sql.includes("wiki_sources"))).toBe(false);
expect(harness.dbExecutes.some((execute) => execute.sql.includes("wiki_operations"))).toBe(false);
});
it("records enabled Paperclip issue events as cursor observations without creating ingest operations", async () => {
const harness = createTestHarness({ manifest });
const issue = paperclipIssue();
harness.seed({ issues: [issue] });
const writes: Array<{ path: string; contents: string }> = [];
harness.ctx.localFolders.writeTextAtomic = async (_companyId, _folderKey, relativePath, contents) => {
writes.push({ path: relativePath, contents });
return harness.ctx.localFolders.status(COMPANY_ID, "wiki-root");
};
await plugin.definition.setup(harness.ctx);
const policy = await harness.performAction<{ enabled: boolean; sources: { issues: boolean; comments: boolean; documents: boolean } }>(
"update-event-ingestion-settings",
{
companyId: COMPANY_ID,
enabled: true,
sources: { issues: true, comments: false, documents: false },
},
);
expect(policy).toMatchObject({ enabled: true, sources: { issues: true, comments: false, documents: false } });
await harness.emit("issue.created", { identifier: issue.identifier }, {
companyId: COMPANY_ID,
entityId: issue.id,
entityType: "issue",
eventId: "event-enabled-issue-created",
});
expect(writes).toHaveLength(0);
const operations = await harness.ctx.issues.list({
companyId: COMPANY_ID,
originKindPrefix: String(OPERATION_ORIGIN_KIND),
});
expect(operations).toHaveLength(0);
expect(harness.dbExecutes.some((execute) => execute.sql.includes("wiki_sources"))).toBe(false);
expect(harness.dbExecutes.some((execute) => execute.sql.includes("wiki_operations"))).toBe(false);
const cursorUpsert = harness.dbExecutes.find((execute) => execute.sql.includes("paperclip_distillation_cursors"));
expect(cursorUpsert?.params).toEqual(expect.arrayContaining([
COMPANY_ID,
"default",
"company",
null,
null,
]));
});
it("preserves Paperclip event ingestion sources when only enabled changes", async () => {
const harness = createTestHarness({ manifest });
await plugin.definition.setup(harness.ctx);
await harness.performAction("update-event-ingestion-settings", {
companyId: COMPANY_ID,
enabled: true,
sources: { issues: true, comments: true, documents: true },
});
const disabled = await harness.performAction<{
enabled: boolean;
sources: { issues: boolean; comments: boolean; documents: boolean };
}>("update-event-ingestion-settings", {
companyId: COMPANY_ID,
enabled: false,
});
expect(disabled).toMatchObject({
enabled: false,
sources: { issues: true, comments: true, documents: true },
});
const reenabled = await harness.performAction<{
enabled: boolean;
sources: { issues: boolean; comments: boolean; documents: boolean };
}>("update-event-ingestion-settings", {
companyId: COMPANY_ID,
enabled: true,
});
expect(reenabled).toMatchObject({
enabled: true,
sources: { issues: true, comments: true, documents: true },
});
});
it("keeps Paperclip event cursor observations company scoped and ignores plugin-operation issues", async () => {
const harness = createTestHarness({ manifest });
const visibleIssue = paperclipIssue({ projectId: "77777777-7777-4777-8777-777777777777" });
const otherCompanyIssue = paperclipIssue({
id: "77777777-7777-4777-8777-777777777778",
companyId: OTHER_COMPANY_ID,
projectId: "77777777-7777-4777-8777-777777777779",
identifier: "PAP-9999",
});
const operationIssue = paperclipIssue({
id: "77777777-7777-4777-8777-777777777780",
originKind: `${OPERATION_ORIGIN_KIND}:ingest`,
});
harness.seed({ issues: [visibleIssue, otherCompanyIssue, operationIssue] });
await plugin.definition.setup(harness.ctx);
await harness.performAction("update-event-ingestion-settings", {
companyId: COMPANY_ID,
enabled: true,
sources: { issues: true, comments: true, documents: true },
});
await harness.emit("issue.updated", {}, {
companyId: COMPANY_ID,
entityId: visibleIssue.id,
entityType: "issue",
eventId: "event-visible",
});
await harness.emit("issue.updated", {}, {
companyId: OTHER_COMPANY_ID,
entityId: otherCompanyIssue.id,
entityType: "issue",
eventId: "event-other-company",
});
await harness.emit("issue.updated", {}, {
companyId: COMPANY_ID,
entityId: operationIssue.id,
entityType: "issue",
eventId: "event-plugin-operation",
});
const cursorWrites = harness.dbExecutes.filter((execute) => execute.sql.includes("paperclip_distillation_cursors"));
expect(cursorWrites).toHaveLength(1);
expect(cursorWrites[0].params).toEqual(expect.arrayContaining([
COMPANY_ID,
"default",
"project",
visibleIssue.projectId,
]));
});
it("routes Paperclip issue, comment, and document event cursors only to the default space", async () => {
const harness = createTestHarness({ manifest });
const issue = paperclipIssue({ projectId: "77777777-7777-4777-8777-777777777777" });
harness.seed({ issues: [issue] });
await plugin.definition.setup(harness.ctx);
const created = await harness.performAction<{
space: { id: string; slug: string };
}>("create-space", {
companyId: COMPANY_ID,
displayName: "Team Research",
});
await harness.performAction("update-event-ingestion-settings", {
companyId: COMPANY_ID,
enabled: true,
sources: { issues: true, comments: true, documents: true },
});
await harness.emit("issue.created", {}, {
companyId: COMPANY_ID,
entityId: issue.id,
entityType: "issue",
eventId: "event-default-issue-created",
});
await harness.emit("issue.comment.created", { commentId: "comment-1" }, {
companyId: COMPANY_ID,
entityId: issue.id,
entityType: "issue",
eventId: "event-default-comment-created",
});
await harness.emit("issue.document.updated", { key: "plan", revisionId: "revision-1" }, {
companyId: COMPANY_ID,
entityId: issue.id,
entityType: "issue",
eventId: "event-default-document-updated",
});
const cursorWrites = harness.dbExecutes.filter((execute) => execute.sql.includes("paperclip_distillation_cursors"));
expect(cursorWrites).toHaveLength(3);
expect(cursorWrites.every((execute) => execute.params?.[10] !== created.space.id)).toBe(true);
expect(cursorWrites.map((execute) => execute.params?.[2])).toEqual(["default", "default", "default"]);
expect(String(cursorWrites[0].params?.[9])).toContain('"lastSourceKind":"issues"');
expect(String(cursorWrites[1].params?.[9])).toContain('"lastSourceKind":"comments"');
expect(String(cursorWrites[2].params?.[9])).toContain('"lastSourceKind":"documents"');
});
it("routes Paperclip events into an explicitly enabled shared non-default space", async () => {
const harness = createTestHarness({ manifest });
const project = existingProject();
const issue = paperclipIssue({ projectId: project.id });
harness.seed({ projects: [project], issues: [issue] });
await plugin.definition.setup(harness.ctx);
const created = await harness.performAction<{
space: { id: string; slug: string };
}>("create-space", {
companyId: COMPANY_ID,
displayName: "Engineering Wiki",
accessScope: "shared",
});
mockPersistedWikiSpace(harness, created.space as unknown as Record<string, unknown>);
const enabledProfile = {
version: 1,
enabled: true,
sourceScopes: [{ kind: "selected_projects", projectIds: [project.id] }],
sourceKinds: { issues: true, comments: true, documents: true, attachments: "off", workProducts: "off" },
cursor: { maxWindowCharacters: 60000, maxCharactersPerSource: 12000, minSourceAgeMinutes: 15, maxWindowsPerRun: 6, staleAfterHours: 72 },
backfill: { requireManualQueue: true },
};
await harness.performAction("update-paperclip-ingestion-profile", {
companyId: COMPANY_ID,
spaceSlug: created.space.slug,
profile: enabledProfile,
});
mockPersistedWikiSpace(harness, { ...(created.space as unknown as Record<string, unknown>), settings: { paperclipIngestion: enabledProfile } });
await harness.emit("issue.created", {}, {
companyId: COMPANY_ID,
entityId: issue.id,
entityType: "issue",
eventId: "event-non-default-enabled",
});
const cursorWrites = harness.dbExecutes.filter((execute) => execute.sql.includes("paperclip_distillation_cursors"));
expect(cursorWrites.some((execute) => execute.params?.[10] === created.space.id)).toBe(true);
});
it("stops new non-default observations after the per-space profile is disabled", async () => {
const harness = createTestHarness({ manifest });
const project = existingProject();
const issue = paperclipIssue({ projectId: project.id });
harness.seed({ projects: [project], issues: [issue] });
await plugin.definition.setup(harness.ctx);
const created = await harness.performAction<{
space: { id: string; slug: string };
}>("create-space", {
companyId: COMPANY_ID,
displayName: "Support Wiki",
accessScope: "shared",
});
mockPersistedWikiSpace(harness, created.space as unknown as Record<string, unknown>);
const enabledProfile = {
version: 1,
enabled: true,
sourceScopes: [{ kind: "selected_projects", projectIds: [project.id] }],
sourceKinds: { issues: true, comments: false, documents: false, attachments: "off", workProducts: "off" },
cursor: { maxWindowCharacters: 60000, maxCharactersPerSource: 12000, minSourceAgeMinutes: 15, maxWindowsPerRun: 6, staleAfterHours: 72 },
backfill: { requireManualQueue: true },
};
await harness.performAction("update-paperclip-ingestion-profile", {
companyId: COMPANY_ID,
spaceSlug: created.space.slug,
profile: enabledProfile,
});
mockPersistedWikiSpace(harness, { ...(created.space as unknown as Record<string, unknown>), settings: { paperclipIngestion: enabledProfile } });
await harness.emit("issue.created", {}, {
companyId: COMPANY_ID,
entityId: issue.id,
entityType: "issue",
eventId: "event-before-disable",
});
await harness.performAction("update-paperclip-ingestion-profile", {
companyId: COMPANY_ID,
spaceSlug: created.space.slug,
profile: { ...enabledProfile, enabled: false },
});
mockPersistedWikiSpace(harness, { ...(created.space as unknown as Record<string, unknown>), settings: { paperclipIngestion: { ...enabledProfile, enabled: false } } });
await harness.emit("issue.updated", {}, {
companyId: COMPANY_ID,
entityId: issue.id,
entityType: "issue",
eventId: "event-after-disable",
});
const nonDefaultCursorWrites = harness.dbExecutes.filter((execute) =>
execute.sql.includes("paperclip_distillation_cursors") && execute.params?.[10] === created.space.id);
expect(nonDefaultCursorWrites).toHaveLength(1);
});
it("assembles deterministic Paperclip source bundles with issue, document, and comment provenance", async () => {
const harness = createTestHarness({ manifest });
const root = paperclipIssue({
id: "77777777-7777-4777-8777-777777777781",
identifier: "PAP-4000",
title: "Root distillation issue",
projectId: "77777777-7777-4777-8777-777777777777",
updatedAt: new Date("2026-05-01T10:00:00Z"),
});
const child = paperclipIssue({
id: "77777777-7777-4777-8777-777777777782",
identifier: "PAP-4001",
title: "Child source issue",
parentId: root.id,
projectId: root.projectId,
description: "Child issue has a decision and implementation notes.",
updatedAt: new Date("2026-05-02T10:00:00Z"),
});
harness.seed({
issues: [root, child],
issueComments: [{
id: "77777777-7777-4777-8777-777777777783",
companyId: COMPANY_ID,
issueId: child.id,
authorType: "user",
authorAgentId: null,
authorUserId: null,
body: "Comment evidence for the source bundle.",
presentation: null,
metadata: null,
createdAt: new Date("2026-05-03T10:00:00Z"),
updatedAt: new Date("2026-05-03T10:00:00Z"),
}],
});
await plugin.definition.setup(harness.ctx);
await harness.ctx.issues.documents.upsert({
companyId: COMPANY_ID,
issueId: child.id,
key: "plan",
title: "Plan",
body: "Document evidence for the source bundle.",
});
const first = await harness.performAction<{
markdown: string;
sourceRefs: Array<{ kind: string; issueIdentifier: string | null; documentKey?: string; commentId?: string }>;
sourceHash: string;
sourceWindowEnd: string | null;
}>("assemble-paperclip-source-bundle", {
companyId: COMPANY_ID,
rootIssueId: root.id,
maxCharacters: 20000,
});
const second = await harness.performAction<typeof first>("assemble-paperclip-source-bundle", {
companyId: COMPANY_ID,
rootIssueId: root.id,
maxCharacters: 20000,
});
expect(second.sourceHash).toBe(first.sourceHash);
expect(first.markdown).toContain("Root distillation issue");
expect(first.markdown).toContain("Child issue has a decision");
expect(first.markdown).toContain("Document evidence for the source bundle.");
expect(first.markdown).toContain("Comment evidence for the source bundle.");
expect(first.sourceRefs).toEqual(expect.arrayContaining([
expect.objectContaining({ kind: "issue", issueIdentifier: "PAP-4001" }),
expect.objectContaining({ kind: "document", documentKey: "plan" }),
expect.objectContaining({ kind: "comment", commentId: "77777777-7777-4777-8777-777777777783" }),
]));
expect(first.sourceWindowEnd).toEqual(expect.any(String));
});
it("suppresses secret-like comment and document bodies before storing distillation snapshots", async () => {
const harness = createTestHarness({ manifest });
const issue = paperclipIssue({
id: "77777777-7777-4777-8777-777777777784",
identifier: "PAP-4002",
title: "Sensitive source issue",
projectId: "77777777-7777-4777-8777-777777777777",
description: "Keep the project page current without copying credential material into the wiki.",
updatedAt: new Date("2026-05-04T10:00:00Z"),
});
harness.seed({
issues: [issue],
issueComments: [{
id: "77777777-7777-4777-8777-777777777785",
companyId: COMPANY_ID,
issueId: issue.id,
authorType: "user",
authorAgentId: null,
authorUserId: null,
body: "Authorization: Bearer ghp_supersecretcommenttoken1234567890",
presentation: null,
metadata: null,
createdAt: new Date("2026-05-04T11:00:00Z"),
updatedAt: new Date("2026-05-04T11:00:00Z"),
}],
});
await plugin.definition.setup(harness.ctx);
await harness.ctx.issues.documents.upsert({
companyId: COMPANY_ID,
issueId: issue.id,
key: "plan",
title: "Plan",
body: "OPENAI_API_KEY=sk-supersecretdocumentvalue1234567890",
});
const run = await harness.performAction<{
bundle: {
markdown: string;
warnings: string[];
sourceRefs: Array<Record<string, unknown>>;
};
}>("create-paperclip-distillation-run", {
companyId: COMPANY_ID,
projectId: issue.projectId,
maxCharacters: 20000,
});
expect(run.bundle.markdown).toContain("Suppressed by LLM Wiki distillation security policy");
expect(run.bundle.markdown).not.toContain("ghp_supersecretcommenttoken1234567890");
expect(run.bundle.markdown).not.toContain("sk-supersecretdocumentvalue1234567890");
expect(run.bundle.warnings).toEqual(expect.arrayContaining([
expect.stringContaining("Suppressed comment content"),
expect.stringContaining("Suppressed document content"),
]));
expect(run.bundle.sourceRefs).toEqual(expect.arrayContaining([
expect.objectContaining({ kind: "comment", redactionStatus: "suppressed_sensitive_content" }),
expect.objectContaining({ kind: "document", redactionStatus: "suppressed_sensitive_content" }),
]));
const snapshotInsert = harness.dbExecutes.find((execute) => execute.sql.includes("paperclip_source_snapshots"));
const storedSourceRefs = String(snapshotInsert?.params?.[9] ?? "");
const storedMarkdown = String(snapshotInsert?.params?.[10] ?? "");
expect(storedSourceRefs).toContain("suppressed_sensitive_content");
expect(storedMarkdown).toContain("Suppressed by LLM Wiki distillation security policy");
expect(storedMarkdown).not.toContain("ghp_supersecretcommenttoken1234567890");
expect(storedMarkdown).not.toContain("sk-supersecretdocumentvalue1234567890");
});
it("creates source snapshots and only advances cursors after successful distillation outcomes", async () => {
const harness = createTestHarness({ manifest });
const issue = paperclipIssue({
projectId: "77777777-7777-4777-8777-777777777777",
updatedAt: new Date("2026-05-02T10:00:00Z"),
});
harness.seed({ issues: [issue] });
await plugin.definition.setup(harness.ctx);
const run = await harness.performAction<{
runId: string;
cursorId: string;
snapshotId: string;
bundle: { sourceHash: string; sourceWindowEnd: string };
}>("create-paperclip-distillation-run", {
companyId: COMPANY_ID,
projectId: issue.projectId,
});
expect(run.snapshotId).toEqual(expect.any(String));
expect(harness.dbExecutes.some((execute) => execute.sql.includes("paperclip_source_snapshots"))).toBe(true);
const failed = await harness.performAction<{ cursorAdvanced: boolean }>("record-paperclip-distillation-outcome", {
companyId: COMPANY_ID,
runId: run.runId,
cursorId: run.cursorId,
status: "failed",
sourceHash: run.bundle.sourceHash,
sourceWindowEnd: run.bundle.sourceWindowEnd,
warning: "writer failed",
});
expect(failed.cursorAdvanced).toBe(false);
const cursorUpdatesAfterFailure = harness.dbExecutes.filter((execute) =>
execute.sql.trim().startsWith("UPDATE") && execute.sql.includes("paperclip_distillation_cursors"));
expect(cursorUpdatesAfterFailure).toHaveLength(0);
const succeeded = await harness.performAction<{ cursorAdvanced: boolean }>("record-paperclip-distillation-outcome", {
companyId: COMPANY_ID,
runId: run.runId,
cursorId: run.cursorId,
status: "succeeded",
sourceHash: run.bundle.sourceHash,
sourceWindowEnd: run.bundle.sourceWindowEnd,
});
expect(succeeded.cursorAdvanced).toBe(true);
const cursorSuccessUpdate = harness.dbExecutes.find((execute) =>
execute.sql.trim().startsWith("UPDATE") && execute.sql.includes("paperclip_distillation_cursors"));
expect(cursorSuccessUpdate?.params).toEqual(expect.arrayContaining([
COMPANY_ID,
"default",
run.runId,
run.bundle.sourceWindowEnd,
run.bundle.sourceHash,
run.cursorId,
]));
});
it("uses the existing distillation cursor id after an upsert conflict", async () => {
const harness = createTestHarness({ manifest });
const project = existingProject();
const issue = paperclipIssue({
id: "77777777-7777-4777-8777-777777777800",
identifier: "PAP-4099",
title: "Existing cursor target",
projectId: project.id,
status: "in_progress",
});
const existingCursorId = "77777777-7777-4777-8777-777777777899";
const originalQuery = harness.ctx.db.query.bind(harness.ctx.db);
harness.ctx.db.query = async <T,>(sql: string, params?: unknown[]) => {
if (sql.includes("SELECT id") && sql.includes("paperclip_distillation_cursors")) {
return [{ id: existingCursorId }] as T[];
}
return originalQuery<T>(sql, params);
};
harness.seed({ projects: [project], issues: [issue] });
await plugin.definition.setup(harness.ctx);
const result = await harness.performAction<{ cursorId: string }>("create-paperclip-distillation-run", {
companyId: COMPANY_ID,
projectId: project.id,
});
expect(result.cursorId).toBe(existingCursorId);
const runInsert = harness.dbExecutes.find((execute) =>
execute.sql.includes("paperclip_distillation_runs") && execute.sql.includes("'source_ready'"));
expect(runInsert?.params?.[3]).toBe(existingCursorId);
});
it("creates explicit distillation work items for manual, retry, and backfill lanes", async () => {
const harness = createTestHarness({ manifest });
await plugin.definition.setup(harness.ctx);
await harness.performAction("create-paperclip-distillation-work-item", {
companyId: COMPANY_ID,
kind: "manual",
projectId: "77777777-7777-4777-8777-777777777777",
idempotencyKey: "manual:project:77777777-7777-4777-8777-777777777777",
});
await harness.performAction("create-paperclip-distillation-work-item", {
companyId: COMPANY_ID,
kind: "retry",
rootIssueId: "77777777-7777-4777-8777-777777777781",
priority: "high",
idempotencyKey: "retry:run:1",
});
await harness.performAction("create-paperclip-distillation-work-item", {
companyId: COMPANY_ID,
kind: "backfill",
projectId: "77777777-7777-4777-8777-777777777777",
priority: "low",
metadata: { window: "last-30-days" },
idempotencyKey: "backfill:last-30-days",
});
const workItemWrites = harness.dbExecutes.filter((execute) => execute.sql.includes("paperclip_distillation_work_items"));
expect(workItemWrites).toHaveLength(3);
expect(workItemWrites.map((write) => write.params?.[3])).toEqual(["manual", "retry", "backfill"]);
expect(String(workItemWrites[0].params?.[9])).toContain('"sourceScope":"project"');
expect(String(workItemWrites[1].params?.[9])).toContain('"sourceScope":"root_issue"');
expect(String(workItemWrites[2].params?.[9])).toContain('"sourceScope":"project"');
await expect(harness.performAction("create-paperclip-distillation-work-item", {
companyId: COMPANY_ID,
kind: "backfill",
idempotencyKey: "backfill:company",
})).rejects.toThrow("whole-company backfill is not allowed");
});
it("records estimated Paperclip distillation cost without refusing on legacy cost config", async () => {
const harness = createTestHarness({
manifest,
config: {
maxPaperclipRoutineRunCostCents: 1,
maxPaperclipDistillationTaskCostCents: 1,
maxPaperclipDistillationProjectCostCents: 1,
paperclipCostCentsPerThousandSourceCharacters: 100,
},
});
const project = existingProject();
const issue = paperclipIssue({
id: "77777777-7777-4777-8777-777777777795",
identifier: "PAP-4104",
title: "Large source bundle",
description: `Accepted plan. ${"Detailed implementation note. ".repeat(160)}`,
projectId: project.id,
status: "in_progress",
});
harness.seed({ projects: [project], issues: [issue] });
await plugin.definition.setup(harness.ctx);
const result = await harness.performAction<{
status: string;
estimatedCostCents: number;
snapshotId: string | null;
}>("create-paperclip-distillation-run", {
companyId: COMPANY_ID,
projectId: project.id,
routineRun: true,
});
expect(result.status).toBe("source_ready");
expect(result.estimatedCostCents).toBeGreaterThan(1);
expect(result.snapshotId).toEqual(expect.any(String));
const readyRun = harness.dbExecutes.find((execute) =>
execute.sql.includes("paperclip_distillation_runs") && execute.sql.includes("'source_ready'"));
expect(readyRun?.params).toEqual(expect.arrayContaining([
COMPANY_ID,
"default",
expect.any(String),
expect.any(String),
null,
project.id,
]));
expect(harness.dbExecutes.some((execute) => execute.sql.includes("paperclip_source_snapshots"))).toBe(true);
expect(harness.dbExecutes.some((execute) => execute.sql.includes("refused_cost_cap"))).toBe(false);
});
it("queues visible manual distill operation issues for a company-wide stale cursor scan", async () => {
const harness = createTestHarness({ manifest });
const project = existingProject();
const issue = paperclipIssue({
id: "77777777-7777-4777-8777-777777777796",
identifier: "PAP-4105",
title: "Manual distillation target",
description: "Implemented enough evidence to manually distill into the wiki.",
status: "done",
projectId: project.id,
});
harness.seed({ agents: [wikiMaintainerAgent()], projects: [project], issues: [issue] });
await plugin.definition.setup(harness.ctx);
const result = await harness.performAction<{
status: string;
operation: { issue: { originKind: string; billingCode: string | null; assigneeAgentId: string | null; assigneeAdapterOverrides: { modelProfile?: string } | null; description: string | null } };
workItem: { kind: string; workItemId: string };
}>("distill-paperclip-now", {
companyId: COMPANY_ID,
autoApply: false,
useCheapModelProfile: true,
includeSupportingPages: false,
});
expect(result.status).toBe("queued");
expect(result.workItem.kind).toBe("manual");
expect(result.operation.issue.originKind).toBe(`${OPERATION_ORIGIN_KIND}:distill`);
expect(result.operation.issue.billingCode).toBe("plugin-llm-wiki:default");
expect(result.operation.issue.assigneeAgentId).toBe(wikiMaintainerAgent().id);
expect(result.operation.issue.assigneeAdapterOverrides).toEqual({ modelProfile: "cheap" });
expect(result.operation.issue.description).toContain("Prompt source: LLM Wiki plugin action `distill-paperclip-now`");
expect(result.operation.issue.description).toContain(`Required skill: use the installed \`${PAPERCLIP_DISTILL_SKILL_KEY}\` skill`);
expect(result.operation.issue.description).toContain("Do not hardcode a single project");
expect(result.operation.issue.description).not.toContain(`Source project ID: ${project.id}`);
const workItemInsert = harness.dbExecutes.find((execute) =>
execute.sql.includes("paperclip_distillation_work_items") && execute.params?.[3] === "manual");
expect(workItemInsert?.params).toEqual(expect.arrayContaining([
COMPANY_ID,
"default",
"manual",
"medium",
null,
null,
]));
const runInsert = harness.dbExecutes.find((execute) =>
execute.sql.includes("paperclip_distillation_runs") && execute.sql.includes("operation_issue_id"));
expect(runInsert).toBeUndefined();
});
it("enables distillation cursors for the most recently active non-plugin projects", async () => {
const harness = createTestHarness({ manifest });
const recentProject = {
...existingProject(),
id: "77777777-7777-4777-8777-777777777801",
name: "Recent Active Project",
status: "in_progress" as const,
updatedAt: new Date("2026-05-04T18:00:00Z"),
};
const olderProject = {
...existingProject(),
id: "77777777-7777-4777-8777-777777777802",
name: "Older Active Project",
status: "in_progress" as const,
updatedAt: new Date("2026-05-03T18:00:00Z"),
};
const overflowProject = {
...existingProject(),
id: "77777777-7777-4777-8777-777777777803",
name: "Overflow Active Project",
status: "in_progress" as const,
updatedAt: new Date("2026-05-02T18:00:00Z"),
};
const completedProject = {
...existingProject(),
id: "77777777-7777-4777-8777-777777777804",
name: "Completed Project",
status: "completed" as const,
updatedAt: new Date("2026-05-04T19:00:00Z"),
};
const pluginProject = {
...existingProject(),
id: "77777777-7777-4777-8777-777777777805",
name: "LLM Wiki",
status: "in_progress" as const,
updatedAt: new Date("2026-05-04T20:00:00Z"),
managedByPlugin: {
id: "77777777-7777-4777-8777-777777777806",
pluginId: "plugin-instance-1",
pluginKey: manifest.id,
pluginDisplayName: manifest.displayName,
resourceKind: "project" as const,
resourceKey: WIKI_PROJECT_KEY,
defaultsJson: {},
createdAt: new Date("2026-05-04T00:00:00Z"),
updatedAt: new Date("2026-05-04T00:00:00Z"),
},
};
harness.seed({ projects: [recentProject, olderProject, overflowProject, completedProject, pluginProject] });
await plugin.definition.setup(harness.ctx);
const result = await harness.performAction<{
selectedProjects: Array<{ id: string; observedAt: string | null }>;
eventIngestion: { enabled: boolean; sources: { issues: boolean; comments: boolean; documents: boolean } };
}>("enable-paperclip-distillation-active-projects", {
companyId: COMPANY_ID,
limit: 2,
});
expect(result.selectedProjects.map((project) => project.id)).toEqual([recentProject.id, olderProject.id]);
expect(result.eventIngestion).toMatchObject({
enabled: true,
sources: { issues: true, comments: true, documents: true },
});
const cursorWrites = harness.dbExecutes.filter((execute) => execute.sql.includes("paperclip_distillation_cursors"));
expect(cursorWrites).toHaveLength(2);
expect(cursorWrites.map((execute) => execute.params?.[5])).toEqual([recentProject.id, olderProject.id]);
expect(cursorWrites.map((execute) => execute.params?.[8])).toEqual([1, 1]);
expect(String(cursorWrites[0]?.params?.[9])).toContain('"configuredBy":"enable-active-projects"');
});
it("backfills only the selected Paperclip project and date window", async () => {
const harness = createTestHarness({ manifest });
const project = existingProject();
const inWindow = paperclipIssue({
id: "77777777-7777-4777-8777-777777777797",
identifier: "PAP-4106",
title: "Backfill in-window decision",
description: "Accepted historical decision that should appear in the backfill page.",
status: "done",
projectId: project.id,
updatedAt: new Date("2026-04-15T12:00:00Z"),
});
const outOfWindow = paperclipIssue({
id: "77777777-7777-4777-8777-777777777798",
identifier: "PAP-4107",
title: "Backfill out-of-window decision",
description: "This old decision must not be included in the selected date window.",
status: "done",
projectId: project.id,
updatedAt: new Date("2026-03-01T12:00:00Z"),
});
const otherProject = paperclipIssue({
id: "77777777-7777-4777-8777-777777777799",
identifier: "PAP-4108",
title: "Other project decision",
description: "This issue belongs to a different project and must not be included.",
status: "done",
projectId: "88888888-8888-4888-8888-888888888888",
updatedAt: new Date("2026-04-16T12:00:00Z"),
});
harness.seed({ agents: [wikiMaintainerAgent()], projects: [project], issues: [inWindow, outOfWindow, otherProject] });
await plugin.definition.setup(harness.ctx);
const result = await harness.performAction<{
status: string;
patches: Array<{ operationType: string; proposedContents: string }>;
workItem: { kind: string };
operation: { issue: { originKind: string } };
}>("backfill-paperclip-distillation", {
companyId: COMPANY_ID,
projectId: project.id,
backfillStartAt: "2026-04-01T00:00:00Z",
backfillEndAt: "2026-04-30T23:59:59Z",
autoApply: false,
includeSupportingPages: false,
});
expect(result.status).toBe("review_required");
expect(result.workItem.kind).toBe("backfill");
expect(result.operation.issue.originKind).toBe(`${OPERATION_ORIGIN_KIND}:backfill`);
const projectPatch = result.patches.find((patch) => patch.operationType === "project_page_distill");
expect(projectPatch?.proposedContents).toContain("PAP-4106");
expect(projectPatch?.proposedContents).not.toContain("PAP-4107");
expect(projectPatch?.proposedContents).not.toContain("PAP-4108");
const workItemInsert = harness.dbExecutes.find((execute) =>
execute.sql.includes("paperclip_distillation_work_items") && execute.params?.[3] === "backfill");
expect(String(workItemInsert?.params?.[9])).toContain('"backfillStartAt":"2026-04-01T00:00:00Z"');
});
it("generates review-required Paperclip project page patches with provenance, index, and log updates", async () => {
const harness = createTestHarness({ manifest });
const project = existingProject();
const issue = paperclipIssue({
id: "77777777-7777-4777-8777-777777777791",
identifier: "PAP-4100",
title: "Approved project page distillation plan",
description: "Accepted plan: write stable project overview sections with source provenance.",
status: "in_progress",
projectId: project.id,
updatedAt: new Date("2026-05-03T10:00:00Z"),
});
const files = new Map<string, string>([
["wiki/index.md", DEFAULT_INDEX],
["wiki/log.md", DEFAULT_LOG],
]);
const writes: Array<{ path: string; contents: string }> = [];
harness.seed({ projects: [project], issues: [issue] });
harness.ctx.localFolders.readText = async (_companyId, _folderKey, relativePath) => {
const contents = files.get(relativePath);
if (contents == null) throw new Error(`missing ${relativePath}`);
return contents;
};
harness.ctx.localFolders.writeTextAtomic = async (_companyId, _folderKey, relativePath, contents) => {
writes.push({ path: relativePath, contents });
files.set(relativePath, contents);
return harness.ctx.localFolders.status(COMPANY_ID, "wiki-root");
};
await plugin.definition.setup(harness.ctx);
const result = await harness.performAction<{
status: string;
patches: Array<{ pagePath: string; operationType: string; currentHash: string | null; proposedContents: string; sourceRefs: Array<{ issueIdentifier: string | null }> }>;
warnings: string[];
}>("distill-paperclip-project-page", {
companyId: COMPANY_ID,
projectId: project.id,
autoApply: false,
maxCharacters: 20000,
includeSupportingPages: false,
});
expect(result.status).toBe("review_required");
expect(writes).toHaveLength(0);
expect(result.patches.map((patch) => patch.operationType)).toEqual([
"standup_update",
"project_page_distill",
"index_refresh",
"log_append",
]);
const standupPatch = result.patches[0];
expect(standupPatch.pagePath).toBe("wiki/projects/existing-wiki-project/standup.md");
expect(standupPatch.proposedContents).toContain("## Executive Readout");
expect(standupPatch.proposedContents).toContain("## What Changed");
const projectPatch = result.patches[1];
expect(projectPatch.currentHash).toBeNull();
expect(projectPatch.pagePath).toBe("wiki/projects/existing-wiki-project/index.md");
expect(projectPatch.proposedContents).toContain("## Workstreams");
expect(projectPatch.proposedContents).toContain("PAP-4100");
expect(projectPatch.sourceRefs).toEqual([expect.objectContaining({ issueIdentifier: "PAP-4100" })]);
expect(result.patches[2].proposedContents).toContain("[[wiki/projects/existing-wiki-project/index.md]]");
expect(result.patches[2].proposedContents).toContain("[[wiki/projects/existing-wiki-project/standup.md]]");
expect(result.patches[3].proposedContents).toContain("paperclip-distill | proposed");
expect(result.warnings).toContain("Auto-apply policy disabled; proposed patches require review.");
});
it("keeps suppressed secret-like source content out of generated wiki patches", async () => {
const harness = createTestHarness({ manifest });
const project = existingProject();
const issue = paperclipIssue({
id: "77777777-7777-4777-8777-777777777796",
identifier: "PAP-4104",
title: "Distill sanitized provenance",
description: "Publish enough project state for a reviewable project page without leaking credentials.",
status: "in_progress",
projectId: project.id,
updatedAt: new Date("2026-05-04T10:00:00Z"),
});
const files = new Map<string, string>([
["wiki/index.md", DEFAULT_INDEX],
["wiki/log.md", DEFAULT_LOG],
]);
harness.seed({
projects: [project],
issues: [issue],
issueComments: [{
id: "77777777-7777-4777-8777-777777777797",
companyId: COMPANY_ID,
issueId: issue.id,
authorType: "user",
authorAgentId: null,
authorUserId: null,
body: "Authorization: Bearer ghp_patchsecretcommenttoken1234567890",
presentation: null,
metadata: null,
createdAt: new Date("2026-05-04T11:00:00Z"),
updatedAt: new Date("2026-05-04T11:00:00Z"),
}],
});
harness.ctx.localFolders.readText = async (_companyId, _folderKey, relativePath) => {
const contents = files.get(relativePath);
if (contents == null) throw new Error(`missing ${relativePath}`);
return contents;
};
harness.ctx.localFolders.writeTextAtomic = async (_companyId, _folderKey, relativePath, contents) => {
files.set(relativePath, contents);
return harness.ctx.localFolders.status(COMPANY_ID, "wiki-root");
};
await plugin.definition.setup(harness.ctx);
await harness.ctx.issues.documents.upsert({
companyId: COMPANY_ID,
issueId: issue.id,
key: "plan",
title: "Plan",
body: "OPENAI_API_KEY=sk-patchsecretdocumentvalue1234567890",
});
const result = await harness.performAction<{
status: string;
patches: Array<{ operationType: string; proposedContents: string }>;
}>("distill-paperclip-project-page", {
companyId: COMPANY_ID,
projectId: project.id,
maxCharacters: 20000,
includeSupportingPages: false,
});
expect(result.status).toBe("review_required");
const combinedPatchContents = result.patches.map((patch) => patch.proposedContents).join("\n");
expect(combinedPatchContents).toContain("redaction=suppressed_sensitive_content");
expect(combinedPatchContents).toContain("redaction_reasons=secret_like_token");
expect(combinedPatchContents).not.toContain("ghp_patchsecretcommenttoken1234567890");
expect(combinedPatchContents).not.toContain("sk-patchsecretdocumentvalue1234567890");
});
it("auto-applies Paperclip project page patches by default when policy allows and records page bindings", async () => {
const harness = createTestHarness({ manifest });
const project = existingProject();
const issue = paperclipIssue({
id: "77777777-7777-4777-8777-777777777792",
identifier: "PAP-4101",
title: "Implement project page writer",
description: "Implementation completed enough to publish the generated project page.",
status: "done",
projectId: project.id,
updatedAt: new Date("2026-05-04T10:00:00Z"),
});
const files = new Map<string, string>([
["wiki/index.md", DEFAULT_INDEX],
["wiki/log.md", DEFAULT_LOG],
]);
harness.seed({ projects: [project], issues: [issue] });
harness.ctx.localFolders.readText = async (_companyId, _folderKey, relativePath) => {
const contents = files.get(relativePath);
if (contents == null) throw new Error(`missing ${relativePath}`);
return contents;
};
harness.ctx.localFolders.writeTextAtomic = async (_companyId, _folderKey, relativePath, contents) => {
files.set(relativePath, contents);
return harness.ctx.localFolders.status(COMPANY_ID, "wiki-root");
};
await plugin.definition.setup(harness.ctx);
const result = await harness.performAction<{
status: string;
appliedPages: string[];
patches: Array<{ pagePath: string; sourceHash: string }>;
}>("distill-paperclip-project-page", {
companyId: COMPANY_ID,
projectId: project.id,
autoApply: true,
maxCharacters: 20000,
includeSupportingPages: false,
});
expect(result.status).toBe("applied");
expect(result.appliedPages).toEqual([
"wiki/projects/existing-wiki-project/standup.md",
"wiki/projects/existing-wiki-project/index.md",
"wiki/index.md",
"wiki/log.md",
]);
expect(files.get("wiki/projects/existing-wiki-project/standup.md")).toContain("## Executive Readout");
expect(files.get("wiki/projects/existing-wiki-project/index.md")).toContain("## Current Direction");
expect(files.get("wiki/projects/existing-wiki-project/index.md")).toContain("## References");
expect(files.get("wiki/index.md")).toContain("wiki/projects/existing-wiki-project/index.md");
expect(files.get("wiki/log.md")).toContain("paperclip-distill | proposed");
const bindingWrites = harness.dbExecutes.filter((execute) => execute.sql.includes("paperclip_page_bindings"));
expect(bindingWrites).toHaveLength(4);
expect(bindingWrites[0].params).toEqual(expect.arrayContaining([
COMPANY_ID,
"default",
project.id,
null,
"wiki/projects/existing-wiki-project/standup.md",
result.patches[0].sourceHash,
]));
});
it("refuses auto-apply Paperclip project page patches in authenticated/public deployments", async () => {
process.env.PAPERCLIP_DEPLOYMENT_MODE = "authenticated";
process.env.PAPERCLIP_DEPLOYMENT_EXPOSURE = "public";
const harness = createTestHarness({ manifest, config: { autoApplyIngestPatches: true } });
const project = existingProject();
const issue = paperclipIssue({
id: "77777777-7777-4777-8777-77777777779a",
identifier: "PAP-4101",
title: "Implement project page writer",
description: "Implementation completed enough to publish the generated project page.",
status: "done",
projectId: project.id,
updatedAt: new Date("2026-05-04T10:00:00Z"),
});
const files = new Map<string, string>([
["wiki/index.md", DEFAULT_INDEX],
["wiki/log.md", DEFAULT_LOG],
]);
const writes: string[] = [];
harness.seed({ projects: [project], issues: [issue] });
harness.ctx.localFolders.readText = async (_companyId, _folderKey, relativePath) => {
const contents = files.get(relativePath);
if (contents == null) throw new Error(`missing ${relativePath}`);
return contents;
};
harness.ctx.localFolders.writeTextAtomic = async (_companyId, _folderKey, relativePath, contents) => {
writes.push(relativePath);
files.set(relativePath, contents);
return harness.ctx.localFolders.status(COMPANY_ID, "wiki-root");
};
await plugin.definition.setup(harness.ctx);
const result = await harness.performAction<{
status: string;
appliedPages: string[];
warnings: string[];
}>("distill-paperclip-project-page", {
companyId: COMPANY_ID,
projectId: project.id,
autoApply: true,
maxCharacters: 20000,
includeSupportingPages: false,
});
expect(result.status).toBe("review_required");
expect(result.appliedPages).toEqual([]);
expect(writes).toHaveLength(0);
expect(result.warnings).toContain(
"Authenticated/public deployments always require manual review before wiki writes.",
);
});
it("refuses stale project page hashes before writing generated Paperclip pages", async () => {
const harness = createTestHarness({ manifest, config: { autoApplyIngestPatches: true } });
const project = existingProject();
const issue = paperclipIssue({
id: "77777777-7777-4777-8777-777777777793",
identifier: "PAP-4102",
title: "Publish project page",
description: "Ready to publish.",
status: "done",
projectId: project.id,
});
const files = new Map<string, string>([
["wiki/projects/existing-wiki-project/index.md", "# Existing\n"],
["wiki/index.md", DEFAULT_INDEX],
["wiki/log.md", DEFAULT_LOG],
]);
const writes: string[] = [];
harness.seed({ projects: [project], issues: [issue] });
harness.ctx.localFolders.readText = async (_companyId, _folderKey, relativePath) => {
const contents = files.get(relativePath);
if (contents == null) throw new Error(`missing ${relativePath}`);
return contents;
};
harness.ctx.localFolders.writeTextAtomic = async (_companyId, _folderKey, relativePath, contents) => {
writes.push(relativePath);
files.set(relativePath, contents);
return harness.ctx.localFolders.status(COMPANY_ID, "wiki-root");
};
await plugin.definition.setup(harness.ctx);
await expect(harness.performAction("distill-paperclip-project-page", {
companyId: COMPANY_ID,
projectId: project.id,
autoApply: true,
expectedProjectPageHash: "stale",
includeSupportingPages: false,
})).rejects.toThrow("Refusing to overwrite");
expect(writes).toHaveLength(0);
});
it("skips low-signal Paperclip source windows without proposing wiki writes", async () => {
const harness = createTestHarness({ manifest });
const project = existingProject();
const issue = paperclipIssue({
id: "77777777-7777-4777-8777-777777777794",
identifier: "PAP-4103",
title: "Routine heartbeat",
description: "",
status: "todo",
projectId: project.id,
});
const writes: string[] = [];
harness.seed({ projects: [project], issues: [issue] });
harness.ctx.localFolders.writeTextAtomic = async (_companyId, _folderKey, relativePath, contents) => {
writes.push(relativePath);
return harness.ctx.localFolders.status(COMPANY_ID, "wiki-root");
};
await plugin.definition.setup(harness.ctx);
const result = await harness.performAction<{ status: string; reason: string; patches: unknown[] }>("distill-paperclip-project-page", {
companyId: COMPANY_ID,
projectId: project.id,
maxCharacters: 20000,
});
expect(result.status).toBe("skipped");
expect(result.reason).toBe("low_signal");
expect(result.patches).toEqual([]);
expect(writes).toHaveLength(0);
});
it("bootstraps required local wiki files through the local folder API", async () => {
const harness = createTestHarness({ manifest });
const writes: Array<{ path: string; contents: string }> = [];
harness.ctx.localFolders.writeTextAtomic = async (_companyId, _folderKey, relativePath, contents) => {
writes.push({ path: relativePath, contents });
return harness.ctx.localFolders.status(COMPANY_ID, "wiki-root");
};
await plugin.definition.setup(harness.ctx);
const result = await harness.performAction<{ writtenFiles: string[]; managedSkills: WikiSkillResource[] }>("bootstrap-root", {
companyId: COMPANY_ID,
path: "/tmp/company-wiki",
});
expect(result.writtenFiles).toContain("AGENTS.md");
expect(result.writtenFiles).toContain("IDEA.md");
expect(result.managedSkills[0]).toMatchObject({
status: "created",
resourceKey: WIKI_MAINTAINER_SKILL_KEY,
details: { key: WIKI_MAINTAINER_SKILL_CANONICAL_KEY },
});
expect(writes.map((write) => write.path)).toEqual([
".gitignore",
"AGENTS.md",
"IDEA.md",
"wiki/index.md",
"wiki/log.md",
"raw/.gitkeep",
"wiki/sources/.gitkeep",
"wiki/projects/.gitkeep",
"wiki/entities/.gitkeep",
"wiki/concepts/.gitkeep",
"wiki/synthesis/.gitkeep",
]);
expect(writes.find((write) => write.path === "AGENTS.md")?.contents).toContain("LLM Wiki Schema");
expect(writes.find((write) => write.path === "AGENTS.md")?.contents).toContain("wiki/projects/<project-slug>/index.md");
expect(writes.find((write) => write.path === "AGENTS.md")?.contents).toContain("wiki/projects/<project-slug>/standup.md");
});
it("creates a managed space with an immediately readable baseline skeleton", async () => {
const harness = createTestHarness({ manifest });
const files = new Map<string, string>();
harness.ctx.localFolders.readText = async (_companyId, _folderKey, relativePath) => {
const value = files.get(relativePath);
if (value == null) throw new Error(`missing ${relativePath}`);
return value;
};
harness.ctx.localFolders.writeTextAtomic = async (_companyId, _folderKey, relativePath, contents) => {
files.set(relativePath, contents);
return harness.ctx.localFolders.status(COMPANY_ID, "wiki-root");
};
await plugin.definition.setup(harness.ctx);
const created = await harness.performAction<{
space: { slug: string; pathPrefix: string | null };
}>("create-space", {
companyId: COMPANY_ID,
displayName: "QA Space",
});
expect(created.space).toMatchObject({
slug: "qa-space",
pathPrefix: "spaces/qa-space",
});
await expect(harness.ctx.localFolders.readText(
COMPANY_ID,
"wiki-root",
"spaces/qa-space/AGENTS.md",
)).resolves.toContain("LLM Wiki Schema");
expect(files.get("spaces/qa-space/IDEA.md")).toBe(DEFAULT_IDEA);
expect(files.has("spaces/qa-space/raw/.gitkeep")).toBe(true);
expect(files.has("spaces/qa-space/projects/.gitkeep")).toBe(false);
expect(files.has("spaces/qa-space/wiki/projects/.gitkeep")).toBe(true);
expect(files.has("spaces/qa-space/wiki/index.md")).toBe(true);
});
it("prevents the default space from being archived through update-space", async () => {
const harness = createTestHarness({ manifest });
await plugin.definition.setup(harness.ctx);
await expect(harness.performAction("update-space", {
companyId: COMPANY_ID,
spaceSlug: "default",
status: "archived",
})).rejects.toThrow("The default LLM Wiki space cannot be archived.");
const defaultSpaceInsert = harness.dbExecutes.find((execute) =>
execute.sql.includes("INSERT INTO") && execute.sql.includes("wiki_spaces"));
expect(defaultSpaceInsert?.params?.[0]).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-8[0-9a-f]{3}-[0-9a-f]{12}$/);
expect(harness.dbExecutes.some((execute) =>
execute.sql.includes("UPDATE") &&
execute.sql.includes("wiki_spaces") &&
execute.params?.includes("archived"))).toBe(false);
});
it("archives a non-default space through update-space without re-resolving it as active", async () => {
const harness = createTestHarness({ manifest });
const spaceRow = wikiSpaceRow({
id: "77777777-7777-4777-8777-7777777777b1",
slug: "qa-space",
displayName: "QA Space",
pathPrefix: "spaces/qa-space",
status: "active",
settings: { owner: "qa" },
});
let archived = false;
const originalQuery = harness.ctx.db.query.bind(harness.ctx.db);
harness.ctx.db.query = async <T,>(sql: string, params?: unknown[]) => {
harness.dbQueries.push({ sql, params });
if (sql.includes("wiki_spaces") && params?.[2] === "qa-space") {
return archived && sql.includes("status <> 'archived'") ? [] as T[] : [spaceRow] as T[];
}
return originalQuery<T>(sql, params);
};
const originalExecute = harness.ctx.db.execute.bind(harness.ctx.db);
harness.ctx.db.execute = async (sql: string, params?: unknown[]) => {
if (sql.includes("UPDATE") && sql.includes("wiki_spaces") && params?.includes("archived")) archived = true;
return originalExecute(sql, params);
};
await plugin.definition.setup(harness.ctx);
const updated = await harness.performAction<{
status: string;
space: { slug: string; displayName: string; status: string; settings: Record<string, unknown> };
}>("update-space", {
companyId: COMPANY_ID,
spaceSlug: "qa-space",
displayName: "Archived QA",
settings: { archivedBy: "test" },
status: "archived",
});
expect(updated.status).toBe("ok");
expect(updated.space).toMatchObject({
slug: "qa-space",
displayName: "Archived QA",
status: "archived",
settings: { owner: "qa", archivedBy: "test" },
});
expect(archived).toBe(true);
});
it("restores an archived non-default space through update-space", async () => {
const harness = createTestHarness({ manifest });
const spaceRow = wikiSpaceRow({
id: "77777777-7777-4777-8777-7777777777b2",
slug: "qa-space",
displayName: "QA Space",
pathPrefix: "spaces/qa-space",
status: "archived",
});
let restored = false;
const originalQuery = harness.ctx.db.query.bind(harness.ctx.db);
harness.ctx.db.query = async <T,>(sql: string, params?: unknown[]) => {
harness.dbQueries.push({ sql, params });
if (sql.includes("wiki_spaces") && params?.[2] === "qa-space") {
if (!restored && sql.includes("status <> 'archived'")) return [] as T[];
return [{
...spaceRow,
status: restored ? "active" : "archived",
}] as T[];
}
return originalQuery<T>(sql, params);
};
const originalExecute = harness.ctx.db.execute.bind(harness.ctx.db);
harness.ctx.db.execute = async (sql: string, params?: unknown[]) => {
if (sql.includes("UPDATE") && sql.includes("wiki_spaces") && params?.includes("active")) restored = true;
return originalExecute(sql, params);
};
await plugin.definition.setup(harness.ctx);
const updated = await harness.performAction<{
status: string;
space: { slug: string; status: string };
}>("update-space", {
companyId: COMPANY_ID,
spaceSlug: "qa-space",
status: "active",
});
expect(updated.status).toBe("ok");
expect(updated.space).toMatchObject({
slug: "qa-space",
status: "active",
});
expect(restored).toBe(true);
});
it("rejects unknown space statuses through update-space", async () => {
const harness = createTestHarness({ manifest });
await plugin.definition.setup(harness.ctx);
await expect(harness.performAction("update-space", {
companyId: COMPANY_ID,
spaceSlug: "default",
status: "suspended",
})).rejects.toThrow("LLM Wiki space status must be active or archived.");
expect(harness.dbExecutes.some((execute) =>
execute.sql.includes("UPDATE") &&
execute.sql.includes("wiki_spaces") &&
execute.params?.includes("suspended"))).toBe(false);
});
it("omits archived spaces from the spaces data API", async () => {
const harness = createTestHarness({ manifest });
const activeRow = wikiSpaceRow({
id: "77777777-7777-4777-8777-7777777777a1",
slug: "team-research",
displayName: "Team Research",
pathPrefix: "spaces/team-research",
status: "active",
});
const archivedRow = wikiSpaceRow({
id: "77777777-7777-4777-8777-7777777777a2",
slug: "qa-team-lock",
displayName: "QA Team Lock",
pathPrefix: "spaces/qa-team-lock",
status: "archived",
});
harness.ctx.db.query = async <T,>(sql: string, params?: unknown[]) => {
harness.dbQueries.push({ sql, params });
if (sql.includes("wiki_spaces") && sql.includes("ORDER BY CASE WHEN slug = 'default'")) {
const rows = [defaultWikiSpaceRow(), activeRow];
if (!sql.includes("status <> 'archived'")) rows.push(archivedRow);
return rows as T[];
}
if (sql.includes("wiki_spaces") && sql.includes("slug = 'default'")) {
return [defaultWikiSpaceRow()] as T[];
}
return [] as T[];
};
await plugin.definition.setup(harness.ctx);
const result = await harness.getData<{ spaces: Array<{ slug: string }> }>("spaces", {
companyId: COMPANY_ID,
wikiId: "default",
});
expect(result.spaces.map((space) => space.slug)).toEqual(["default", "team-research"]);
expect(harness.dbQueries.some((query) => query.sql.includes("status <> 'archived'"))).toBe(true);
});
it("captures raw sources into local files and plugin metadata", async () => {
const harness = createTestHarness({ manifest });
const writes: Array<{ path: string; contents: string }> = [];
harness.ctx.localFolders.writeTextAtomic = async (_companyId, _folderKey, relativePath, contents) => {
writes.push({ path: relativePath, contents });
return harness.ctx.localFolders.status(COMPANY_ID, "wiki-root");
};
await plugin.definition.setup(harness.ctx);
const result = await harness.performAction<{ rawPath: string; hash: string }>("capture-source", {
companyId: COMPANY_ID,
wikiId: "default",
title: "Plugin Boundaries",
contents: "# Plugin Boundaries\n\nKeep wiki logic in the plugin.",
});
expect(result.rawPath).toMatch(/^raw\/\d{4}-\d{2}-\d{2}-plugin-boundaries-/);
expect(result.hash).toHaveLength(64);
expect(writes[0]).toMatchObject({ path: result.rawPath });
expect(harness.dbExecutes.some((execute) => execute.sql.includes("wiki_sources"))).toBe(true);
});
it("preserves manual source ingest for non-default spaces while refusing Paperclip distillation there", async () => {
const harness = createTestHarness({ manifest });
const writes: Array<{ path: string; contents: string }> = [];
harness.ctx.localFolders.writeTextAtomic = async (_companyId, _folderKey, relativePath, contents) => {
writes.push({ path: relativePath, contents });
return harness.ctx.localFolders.status(COMPANY_ID, "wiki-root");
};
harness.seed({
agents: [wikiMaintainerAgent()],
projects: [existingProject()],
});
const spaces = new Map<string, Record<string, unknown>>();
const originalQuery = harness.ctx.db.query.bind(harness.ctx.db);
harness.ctx.db.query = async <T,>(sql: string, params?: unknown[]) => {
if (sql.includes("wiki_spaces")) {
const slug = typeof params?.[2] === "string" ? params[2] : null;
if (slug && spaces.has(slug)) return [spaces.get(slug)] as T[];
}
return originalQuery<T>(sql, params);
};
await plugin.definition.setup(harness.ctx);
const created = await harness.performAction<{
space: { id: string; companyId: string; wikiId: string; slug: string; displayName: string; pathPrefix: string | null };
}>("create-space", {
companyId: COMPANY_ID,
displayName: "Team Research",
});
spaces.set(created.space.slug, {
id: created.space.id,
company_id: created.space.companyId,
wiki_id: created.space.wikiId,
slug: created.space.slug,
display_name: created.space.displayName,
space_type: "local_folder",
folder_mode: "managed_subfolder",
root_folder_key: "wiki-root",
path_prefix: created.space.pathPrefix,
configured_root_path: null,
access_scope: "shared",
owner_user_id: null,
owner_agent_id: null,
team_key: null,
settings: {},
status: "active",
created_at: null,
updated_at: null,
});
const source = await harness.performAction<{ rawPath: string; spaceSlug: string }>("capture-source", {
companyId: COMPANY_ID,
spaceSlug: created.space.slug,
title: "Team notes",
contents: "# Team notes\n\nManual source ingest still belongs to the selected space.",
});
expect(source.spaceSlug).toBe(created.space.slug);
expect(writes.map((write) => write.path)).toContain(`spaces/${created.space.slug}/${source.rawPath}`);
await expect(harness.performAction("distill-paperclip-now", {
companyId: COMPANY_ID,
spaceSlug: created.space.slug,
projectId: existingProject().id,
})).rejects.toThrow("Paperclip ingestion policy denied queue");
});
it("fails closed for direct Paperclip ingestion actions against restricted spaces", async () => {
const harness = createTestHarness({ manifest });
harness.seed({
agents: [wikiMaintainerAgent()],
projects: [existingProject()],
});
await plugin.definition.setup(harness.ctx);
const created = await harness.performAction<{
space: { slug: string; accessScope: string };
}>("create-space", {
companyId: COMPANY_ID,
displayName: "Private Notes",
accessScope: "personal",
});
expect(created.space.accessScope).toBe("personal");
const originalQuery = harness.ctx.db.query.bind(harness.ctx.db);
harness.ctx.db.query = async <T,>(sql: string, params?: unknown[]) => {
if (sql.includes("wiki_spaces") && params?.[2] === created.space.slug) {
return [{
id: "77777777-7777-4777-8777-7777777777b2",
company_id: COMPANY_ID,
wiki_id: "default",
slug: created.space.slug,
display_name: "Private Notes",
space_type: "local_folder",
folder_mode: "managed_subfolder",
root_folder_key: "wiki-root",
path_prefix: `spaces/${created.space.slug}`,
configured_root_path: null,
access_scope: "personal",
owner_user_id: null,
owner_agent_id: null,
team_key: null,
settings: {},
status: "active",
created_at: null,
updated_at: null,
}] as T[];
}
return originalQuery<T>(sql, params);
};
await expect(harness.performAction("distill-paperclip-now", {
companyId: COMPANY_ID,
spaceSlug: created.space.slug,
projectId: existingProject().id,
})).rejects.toThrow("Paperclip ingestion policy denied queue");
const operations = await harness.ctx.issues.list({
companyId: COMPANY_ID,
originKindPrefix: String(OPERATION_ORIGIN_KIND),
});
expect(operations).toHaveLength(0);
expect(harness.dbExecutes.some((execute) => execute.sql.includes("paperclip_distillation_work_items"))).toBe(false);
});
it("re-checks Paperclip ingestion policy at execution time for queued work", async () => {
const harness = createTestHarness({ manifest });
const project = existingProject();
const issue = paperclipIssue({
id: "77777777-7777-4777-8777-7777777777b0",
identifier: "PAP-4111",
title: "Queued distillation source",
description: "Accepted queued work should not run after policy changes.",
projectId: project.id,
status: "done",
});
harness.seed({ agents: [wikiMaintainerAgent()], projects: [project], issues: [issue] });
await plugin.definition.setup(harness.ctx);
const queued = await harness.performAction<{ status: string }>("distill-paperclip-now", {
companyId: COMPANY_ID,
projectId: project.id,
});
expect(queued.status).toBe("queued");
const originalQuery = harness.ctx.db.query.bind(harness.ctx.db);
harness.ctx.db.query = async <T,>(sql: string, params?: unknown[]) => {
if (sql.includes("wiki_spaces") && sql.includes("slug = 'default'")) {
return [{
id: "77777777-7777-4777-8777-7777777777b1",
company_id: COMPANY_ID,
wiki_id: "default",
slug: "default",
display_name: "default",
space_type: "local_folder",
folder_mode: "managed_subfolder",
root_folder_key: "wiki-root",
path_prefix: null,
configured_root_path: null,
access_scope: "personal",
owner_user_id: null,
owner_agent_id: null,
team_key: null,
settings: {},
status: "active",
created_at: null,
updated_at: null,
}] as T[];
}
return originalQuery<T>(sql, params);
};
await expect(harness.performAction("create-paperclip-distillation-run", {
companyId: COMPANY_ID,
projectId: project.id,
})).rejects.toThrow("personal spaces cannot ingest Paperclip sources");
expect(harness.dbExecutes.some((execute) =>
execute.sql.includes("paperclip_distillation_runs") && execute.sql.includes("'source_ready'"))).toBe(false);
});
it("queues Paperclip ingestion backfills for every selected project scope", async () => {
const harness = createTestHarness({ manifest });
await plugin.definition.setup(harness.ctx);
const queued = await harness.performAction<{
status: string;
workItemId: string;
issueId: string;
workItems: Array<{ workItemId: string; issueId: string; projectId: string | null; rootIssueId: string | null }>;
}>("queue-paperclip-ingestion-backfill", {
companyId: COMPANY_ID,
sourceScope: {
kind: "selected_projects",
projectIds: [
"77777777-7777-4777-8777-7777777777a1",
"77777777-7777-4777-8777-7777777777a2",
],
},
backfillStartAt: "2026-05-01T00:00:00.000Z",
backfillEndAt: "2026-05-02T00:00:00.000Z",
});
expect(queued.status).toBe("queued");
expect(queued.workItems).toHaveLength(2);
expect(queued.workItemId).toBe(queued.workItems[0]?.workItemId);
expect(queued.issueId).toBe(queued.workItems[0]?.issueId);
expect(queued.workItems.map((item) => item.projectId)).toEqual([
"77777777-7777-4777-8777-7777777777a1",
"77777777-7777-4777-8777-7777777777a2",
]);
expect(harness.dbExecutes.filter((execute) => execute.sql.includes("paperclip_distillation_work_items"))).toHaveLength(2);
});
it("rejects oversized Paperclip ingestion profile and source-scope payloads", async () => {
const harness = createTestHarness({ manifest });
await plugin.definition.setup(harness.ctx);
await expect(harness.performAction("update-event-ingestion-settings", {
companyId: COMPANY_ID,
enabled: true,
maxCharacters: 20001,
sources: { issues: true },
})).rejects.toThrow("maxCharacters exceeds the hard Paperclip ingestion cap");
await expect(harness.performAction("enable-paperclip-distillation-active-projects", {
companyId: COMPANY_ID,
limit: 26,
})).rejects.toThrow("fan-out exceeds the hard cap");
await expect(harness.performAction("assemble-paperclip-source-bundle", {
companyId: COMPANY_ID,
projectId: "77777777-7777-4777-8777-777777777777",
rootIssueId: "77777777-7777-4777-8777-777777777778",
})).rejects.toThrow("either projectId or rootIssueId");
await expect(harness.performAction("assemble-paperclip-source-bundle", {
companyId: COMPANY_ID,
projectId: "77777777-7777-4777-8777-777777777777",
maxCharacters: 60001,
})).rejects.toThrow("maxCharacters exceeds the hard Paperclip ingestion cap");
});
it("keeps default-space files at the root and isolates managed spaces under slug prefixes", async () => {
const harness = createTestHarness({ manifest });
const files = new Map<string, string>();
const writes: Array<{ path: string; contents: string }> = [];
harness.ctx.localFolders.readText = async (_companyId, _folderKey, relativePath) => {
const value = files.get(relativePath);
if (value == null) throw new Error(`missing ${relativePath}`);
return value;
};
harness.ctx.localFolders.writeTextAtomic = async (_companyId, _folderKey, relativePath, contents) => {
writes.push({ path: relativePath, contents });
files.set(relativePath, contents);
return harness.ctx.localFolders.status(COMPANY_ID, "wiki-root");
};
const spaces = new Map<string, Record<string, unknown>>();
const originalQuery = harness.ctx.db.query.bind(harness.ctx.db);
harness.ctx.db.query = async <T,>(sql: string, params?: unknown[]) => {
if (sql.includes("wiki_spaces")) {
const slug = typeof params?.[2] === "string" ? params[2] : null;
if (slug && spaces.has(slug)) return [spaces.get(slug)] as T[];
}
return originalQuery<T>(sql, params);
};
await plugin.definition.setup(harness.ctx);
const created = await harness.performAction<{
space: { id: string; companyId: string; wikiId: string; slug: string; displayName: string; pathPrefix: string | null };
}>("create-space", {
companyId: COMPANY_ID,
displayName: "Research Space",
});
spaces.set(created.space.slug, {
id: created.space.id,
company_id: created.space.companyId,
wiki_id: created.space.wikiId,
slug: created.space.slug,
display_name: created.space.displayName,
space_type: "local_folder",
folder_mode: "managed_subfolder",
root_folder_key: "wiki-root",
path_prefix: created.space.pathPrefix,
configured_root_path: null,
access_scope: "shared",
owner_user_id: null,
owner_agent_id: null,
team_key: null,
settings: {},
status: "active",
created_at: null,
updated_at: null,
});
await harness.performAction("bootstrap-space", {
companyId: COMPANY_ID,
spaceSlug: created.space.slug,
});
await harness.performAction("write-page", {
companyId: COMPANY_ID,
wikiId: "default",
path: "wiki/concepts/shared.md",
contents: "# Default Shared\n",
});
await harness.performAction("write-page", {
companyId: COMPANY_ID,
wikiId: "default",
spaceSlug: created.space.slug,
path: "wiki/concepts/shared.md",
contents: "# Space Shared\n",
});
await harness.performAction("capture-source", {
companyId: COMPANY_ID,
wikiId: "default",
rawPath: "raw/shared.md",
title: "Shared Source",
contents: "# Default Raw\n",
});
await harness.performAction("capture-source", {
companyId: COMPANY_ID,
wikiId: "default",
spaceSlug: created.space.slug,
rawPath: "raw/shared.md",
title: "Shared Source",
contents: "# Space Raw\n",
});
expect(created.space).toMatchObject({
slug: "research-space",
pathPrefix: "spaces/research-space",
});
expect(files.get("wiki/concepts/shared.md")).toBe("# Default Shared\n");
expect(files.get("spaces/research-space/wiki/concepts/shared.md")).toBe("# Space Shared\n");
expect(files.get("raw/shared.md")).toBe("# Default Raw\n");
expect(files.get("spaces/research-space/raw/shared.md")).toBe("# Space Raw\n");
expect(writes.map((write) => write.path)).not.toContain("spaces/default/wiki/concepts/shared.md");
const pageWrites = harness.dbExecutes.filter((execute) => execute.sql.includes("wiki_pages"));
const sourceWrites = harness.dbExecutes.filter((execute) => execute.sql.includes("wiki_sources"));
expect(pageWrites.every((write) => write.sql.includes("space_id"))).toBe(true);
expect(sourceWrites.every((write) => write.sql.includes("space_id"))).toBe(true);
});
it("ingests source metadata and creates a hidden plugin-operation issue", async () => {
const harness = createTestHarness({ manifest });
harness.seed({ agents: [wikiMaintainerAgent()] });
const writes: Array<{ path: string; contents: string }> = [];
harness.ctx.localFolders.writeTextAtomic = async (_companyId, _folderKey, relativePath, contents) => {
writes.push({ path: relativePath, contents });
return harness.ctx.localFolders.status(COMPANY_ID, "wiki-root");
};
await plugin.definition.setup(harness.ctx);
const result = await harness.performAction<{
source: { rawPath: string; title: string; hash: string };
operation: { operationId: string; issue: { originKind: string; originId: string | null; billingCode: string | null; assigneeAgentId: string | null } };
}>("ingest-source", {
companyId: COMPANY_ID,
wikiId: "engineering",
sourceType: "url",
title: "Standalone Plugin Notes",
url: "https://example.test/wiki",
contents: "# Standalone Plugin Notes\n\nKeep wiki behavior in the plugin package.",
rawPath: "raw/standalone-plugin-notes.md",
metadata: { importedBy: "alpha-verification" },
});
expect(result.source.rawPath).toBe("raw/standalone-plugin-notes.md");
expect(result.source.title).toBe("Standalone Plugin Notes");
expect(result.source.hash).toHaveLength(64);
expect(writes).toEqual([
expect.objectContaining({
path: "raw/standalone-plugin-notes.md",
contents: expect.stringContaining("Keep wiki behavior in the plugin package."),
}),
]);
expect(result.operation.issue.originKind).toBe(`${OPERATION_ORIGIN_KIND}:ingest`);
expect(result.operation.issue.originId).toBe(`wiki:engineering:operation:${result.operation.operationId}`);
expect(result.operation.issue.billingCode).toBe("plugin-llm-wiki:engineering");
expect(result.operation.issue.assigneeAgentId).toBe(wikiMaintainerAgent().id);
const sourceInsert = harness.dbExecutes.find((execute) => execute.sql.includes("wiki_sources"));
expect(sourceInsert?.params).toEqual(expect.arrayContaining([
COMPANY_ID,
"engineering",
"url",
"Standalone Plugin Notes",
"https://example.test/wiki",
"raw/standalone-plugin-notes.md",
JSON.stringify({ importedBy: "alpha-verification" }),
]));
const operationInsert = harness.dbExecutes.find((execute) => execute.sql.includes("wiki_operations"));
expect(operationInsert?.params).toEqual(expect.arrayContaining([
result.operation.operationId,
COMPANY_ID,
"engineering",
"ingest",
"queued",
]));
});
it("rejects oversized source capture before raw writes or operation creation", async () => {
const harness = createTestHarness({ manifest, config: { maxSourceBytes: 16 } });
harness.seed({ agents: [wikiMaintainerAgent()] });
const writes: Array<{ path: string; contents: string }> = [];
harness.ctx.localFolders.writeTextAtomic = async (_companyId, _folderKey, relativePath, contents) => {
writes.push({ path: relativePath, contents });
return harness.ctx.localFolders.status(COMPANY_ID, "wiki-root");
};
await plugin.definition.setup(harness.ctx);
await expect(harness.performAction("ingest-source", {
companyId: COMPANY_ID,
wikiId: "default",
sourceType: "text",
title: "Oversized source",
contents: "x".repeat(17),
})).rejects.toThrow("exceeds the configured LLM Wiki source limit");
expect(writes).toHaveLength(0);
expect(harness.dbExecutes.some((execute) => execute.sql.includes("wiki_sources"))).toBe(false);
expect(harness.dbExecutes.some((execute) => execute.sql.includes("wiki_operations"))).toBe(false);
const operations = await harness.ctx.issues.list({
companyId: COMPANY_ID,
originKindPrefix: String(OPERATION_ORIGIN_KIND),
});
expect(operations).toHaveLength(0);
});
it("writes pages atomically, records metadata, and rejects stale hashes", async () => {
const harness = createTestHarness({ manifest });
const files = new Map<string, string>([
["wiki/concepts/plugin-boundaries.md", "# Old Title\n"],
]);
harness.ctx.localFolders.readText = async (_companyId, _folderKey, relativePath) => {
const value = files.get(relativePath);
if (value == null) throw new Error("missing");
return value;
};
harness.ctx.localFolders.writeTextAtomic = async (_companyId, _folderKey, relativePath, contents) => {
files.set(relativePath, contents);
return harness.ctx.localFolders.status(COMPANY_ID, "wiki-root");
};
await plugin.definition.setup(harness.ctx);
const staleWrite = harness.executeTool("wiki_write_page", {
companyId: COMPANY_ID,
wikiId: "default",
path: "wiki/concepts/plugin-boundaries.md",
contents: "# New Title\n",
expectedHash: "stale",
});
await expect(staleWrite).rejects.toThrow("Refusing to overwrite");
const result = await harness.executeTool<{ data?: { hash: string } }>("wiki_write_page", {
companyId: COMPANY_ID,
wikiId: "default",
path: "wiki/concepts/plugin-boundaries.md",
contents: "# Plugin Boundaries\n\nSee [Knowledge](wiki/areas/knowledge.md).",
});
expect(result.data?.hash).toHaveLength(64);
expect(files.get("wiki/concepts/plugin-boundaries.md")).toContain("Plugin Boundaries");
expect(harness.dbExecutes.some((execute) => execute.sql.includes("wiki_pages"))).toBe(true);
expect(harness.dbExecutes.some((execute) => execute.sql.includes("wiki_page_revisions"))).toBe(true);
});
it("blocks agent-tool writes to AGENTS.md but allows explicit board edits", async () => {
const harness = createTestHarness({ manifest });
const files = new Map<string, string>([
["AGENTS.md", "# LLM Wiki Maintainer\n\nOriginal instructions.\n"],
]);
harness.ctx.localFolders.readText = async (_companyId, _folderKey, relativePath) => {
const value = files.get(relativePath);
if (value == null) throw new Error("missing");
return value;
};
harness.ctx.localFolders.writeTextAtomic = async (_companyId, _folderKey, relativePath, contents) => {
files.set(relativePath, contents);
return harness.ctx.localFolders.status(COMPANY_ID, "wiki-root");
};
await plugin.definition.setup(harness.ctx);
await expect(harness.executeTool("wiki_write_page", {
companyId: COMPANY_ID,
wikiId: "default",
path: "AGENTS.md",
contents: "# LLM Wiki Maintainer\n\nCompromised instructions.\n",
})).rejects.toThrow("Refusing to overwrite protected wiki control file AGENTS.md");
const result = await harness.performAction<{ hash: string }>("write-page", {
companyId: COMPANY_ID,
wikiId: "default",
path: "AGENTS.md",
contents: "# LLM Wiki Maintainer\n\nBoard-updated instructions.\n",
});
expect(result.hash).toHaveLength(64);
expect(files.get("AGENTS.md")).toContain("Board-updated instructions.");
});
it("creates plugin-operation issues for LLM workflows", async () => {
const harness = createTestHarness({ manifest });
harness.seed({ agents: [wikiMaintainerAgent()] });
await plugin.definition.setup(harness.ctx);
const result = await harness.performAction<{ issue: { originKind: string; billingCode: string | null } }>(
"create-operation",
{
companyId: COMPANY_ID,
operationType: "query",
title: "Ask the wiki about plugin boundaries",
prompt: "Which files own wiki behavior?",
},
);
expect(result.issue.originKind).toBe(`${OPERATION_ORIGIN_KIND}:query`);
expect(result.issue.billingCode).toBe("plugin-llm-wiki:default");
expect(harness.dbExecutes.some((execute) => execute.sql.includes("wiki_resource_bindings"))).toBe(true);
expect(harness.dbExecutes.some((execute) => execute.sql.includes("wiki_operations"))).toBe(true);
});
it("stamps resolved space context into hidden operation issues and operation metadata", async () => {
const harness = createTestHarness({ manifest });
harness.seed({ agents: [wikiMaintainerAgent()] });
const spaces = new Map<string, Record<string, unknown>>();
const originalQuery = harness.ctx.db.query.bind(harness.ctx.db);
harness.ctx.db.query = async <T,>(sql: string, params?: unknown[]) => {
if (sql.includes("wiki_spaces")) {
const slug = typeof params?.[2] === "string" ? params[2] : null;
if (slug && spaces.has(slug)) return [spaces.get(slug)] as T[];
}
return originalQuery<T>(sql, params);
};
await plugin.definition.setup(harness.ctx);
const created = await harness.performAction<{
space: { id: string; companyId: string; wikiId: string; slug: string; displayName: string; pathPrefix: string | null };
}>("create-space", {
companyId: COMPANY_ID,
displayName: "Research Space",
});
spaces.set(created.space.slug, {
id: created.space.id,
company_id: created.space.companyId,
wiki_id: created.space.wikiId,
slug: created.space.slug,
display_name: created.space.displayName,
space_type: "local_folder",
folder_mode: "managed_subfolder",
root_folder_key: "wiki-root",
path_prefix: created.space.pathPrefix,
configured_root_path: null,
access_scope: "shared",
owner_user_id: null,
owner_agent_id: null,
team_key: null,
settings: {},
status: "active",
created_at: null,
updated_at: null,
});
const result = await harness.performAction<{
operationId: string;
issue: { title: string; description: string | null; billingCode: string | null; originId: string | null };
}>("create-operation", {
companyId: COMPANY_ID,
operationType: "lint",
title: "Run LLM Wiki lint",
prompt: "Audit wiki structure.",
spaceSlug: created.space.slug,
});
expect(result.issue.title).toBe("Run LLM Wiki lint [space: Research Space / research-space]");
expect(result.issue.description).toContain("Space: Research Space (research-space)");
expect(result.issue.description).toContain("Space root: wiki-root/spaces/research-space");
expect(result.issue.description).toContain("Pass wikiId `default` and spaceSlug `research-space`");
expect(result.issue.description).toContain("Manual ingest, query, lint, index, and file-as-page operations follow the named destination space");
expect(result.issue.billingCode).toBe("plugin-llm-wiki:default:research-space");
expect(result.issue.originId).toBe(`wiki:default:space:research-space:operation:${result.operationId}`);
const operationInsert = harness.dbExecutes.find((execute) =>
execute.sql.includes("wiki_operations") && execute.params?.[0] === result.operationId);
const metadata = JSON.parse(String(operationInsert?.params?.[8]));
expect(metadata).toMatchObject({
operationType: "lint",
operationId: result.operationId,
wikiId: "default",
spaceId: created.space.id,
spaceSlug: "research-space",
spaceName: "Research Space",
spaceRoot: "wiki-root/spaces/research-space",
billingCode: "plugin-llm-wiki:default:research-space",
});
});
it("uses selected existing agent and project bindings for new operations", async () => {
const harness = createTestHarness({ manifest });
const agent = existingAgent();
const project = existingProject();
harness.seed({ agents: [agent], projects: [project] });
await plugin.definition.setup(harness.ctx);
const selectedAgent = await harness.performAction<{ source: string; agentId: string }>("select-managed-agent", {
companyId: COMPANY_ID,
agentId: agent.id,
});
const selectedProject = await harness.performAction<{ source: string; projectId: string }>("select-managed-project", {
companyId: COMPANY_ID,
projectId: project.id,
});
expect(selectedAgent).toMatchObject({ source: "selected", agentId: agent.id });
expect(selectedProject).toMatchObject({ source: "selected", projectId: project.id });
expect(harness.dbExecutes.filter((execute) => execute.sql.includes("wiki_resource_bindings"))).toHaveLength(2);
harness.ctx.db.query = async <T = Record<string, unknown>>(sql: string, params?: unknown[]) => {
harness.dbQueries.push({ sql, params });
if (sql.includes("wiki_resource_bindings") && params?.[2] === "agent") {
return [{ resolved_id: agent.id, metadata: { source: "selected-existing" } }] as T[];
}
if (sql.includes("wiki_resource_bindings") && params?.[2] === "project") {
return [{ resolved_id: project.id, metadata: { source: "selected-existing" } }] as T[];
}
if (sql.includes("wiki_operations")) return [{ count: "0" }] as T[];
return [];
};
const result = await harness.performAction<{
issue: { assigneeAgentId: string | null; projectId: string | null };
}>("create-operation", {
companyId: COMPANY_ID,
operationType: "lint",
title: "Lint selected wiki",
});
expect(result.issue.assigneeAgentId).toBe(agent.id);
expect(result.issue.projectId).toBe(project.id);
});
it("starts query sessions, records run ids, and forwards session events to plugin streams", async () => {
const harness = createTestHarness({ manifest });
harness.seed({ agents: [wikiMaintainerAgent()] });
const streamEvents: unknown[] = [];
harness.ctx.streams.emit = (_channel, event) => {
streamEvents.push(event);
};
await plugin.definition.setup(harness.ctx);
const result = await harness.performAction<{
operationId: string;
querySessionId: string;
sessionId: string;
runId: string;
channel: string;
}>("start-query", {
companyId: COMPANY_ID,
question: "Which files own wiki behavior?",
});
expect(result.querySessionId).toBe(result.operationId);
expect(result.channel).toBe(`llm-wiki:query:${result.operationId}`);
expect(harness.dbExecutes.some((execute) => execute.sql.includes("wiki_query_sessions"))).toBe(true);
expect(harness.dbExecutes.some((execute) => execute.sql.includes("run_ids"))).toBe(true);
harness.simulateSessionEvent(result.sessionId, {
runId: result.runId,
seq: 1,
eventType: "chunk",
stream: "stdout",
message: "Keep wiki behavior in the plugin.",
payload: null,
});
harness.simulateSessionEvent(result.sessionId, {
runId: result.runId,
seq: 2,
eventType: "done",
stream: "system",
message: "Run completed",
payload: null,
});
await new Promise((resolve) => setTimeout(resolve, 0));
expect(streamEvents).toEqual(expect.arrayContaining([
expect.objectContaining({ type: "query.started", operationId: result.operationId }),
expect.objectContaining({ type: "agent.event", message: "Keep wiki behavior in the plugin." }),
expect.objectContaining({ type: "query.done", answer: "Keep wiki behavior in the plugin." }),
]));
expect(harness.dbExecutes.some((execute) =>
execute.sql.includes("wiki_query_sessions") && execute.params?.includes("completed"),
)).toBe(true);
});
it("files a streamed query answer as a page through a hidden file-as-page operation", async () => {
const harness = createTestHarness({ manifest });
harness.seed({ agents: [wikiMaintainerAgent()] });
const writes: Array<{ path: string; contents: string }> = [];
harness.ctx.localFolders.writeTextAtomic = async (_companyId, _folderKey, relativePath, contents) => {
writes.push({ path: relativePath, contents });
return harness.ctx.localFolders.status(COMPANY_ID, "wiki-root");
};
await plugin.definition.setup(harness.ctx);
const result = await harness.performAction<{ path: string; operationId: string; page: { revisionId: string } }>(
"file-as-page",
{
companyId: COMPANY_ID,
querySessionId: "33333333-3333-4333-8333-333333333333",
question: "Where should wiki code live?",
answer: "Wiki-specific code lives in the standalone plugin package.",
path: "wiki/concepts/plugin-boundaries.md",
title: "Plugin Boundaries",
},
);
expect(result.path).toBe("wiki/concepts/plugin-boundaries.md");
expect(writes[0]).toMatchObject({ path: "wiki/concepts/plugin-boundaries.md" });
expect(writes[0]?.contents).toContain("Wiki-specific code lives in the standalone plugin package.");
expect(harness.dbExecutes.some((execute) => execute.sql.includes("wiki_operations"))).toBe(true);
expect(harness.dbExecutes.some((execute) => execute.sql.includes("wiki_page_revisions"))).toBe(true);
expect(harness.dbExecutes.some((execute) => execute.sql.includes("filed_outputs"))).toBe(true);
});
});