mirror of
https://github.com/alkimake/paperclip.git
synced 2026-06-14 01:50:39 +09:00
## Thinking Path > - Paperclip orchestrates AI agents through a server-side control plane > - That control plane depends on reliable issue state transitions, plugin lifecycle behavior, import limits, and startup/shutdown handling > - Several small runtime fixes had accumulated on the working branch and were mixed with larger feature work > - Keeping them separate makes the correctness fixes reviewable and mergeable without waiting for cloud-sync UI work > - This pull request groups the server/runtime control-plane fixes into one standalone branch > - The benefit is a tighter, safer runtime baseline for retries, imports, plugin migrations, feedback flushing, and trusted cloud import handling ## What Changed - Fixed updated issue list pagination sorting and scheduled retry comment handling. - Re-applied pending plugin migrations during hot reload and fixed plugin-schema worktree seed restore. - Hardened public tenant DB startup, portable import body limits, trusted cloud import errors, and trusted cloud tenant import mutation access. - Expired stale request confirmations after user comments. - Added feedback export shutdown hardening so database-unavailable flush loops stop cleanly. - Guarded plugin worker `error` event emission when no listener is registered. ## Verification - `pnpm install --frozen-lockfile --ignore-scripts` - `pnpm --filter @paperclipai/plugin-sdk build` - `npm run install --prefix node_modules/.pnpm/sqlite3@5.1.7/node_modules/sqlite3` - `pnpm exec vitest run server/src/__tests__/issues-service.test.ts server/src/__tests__/plugin-lifecycle-restart.test.ts server/src/__tests__/server-startup-feedback-export.test.ts server/src/__tests__/issue-comment-reopen-routes.test.ts server/src/__tests__/issue-thread-interactions-service.test.ts server/src/__tests__/issue-thread-interaction-routes.test.ts server/src/__tests__/body-limits.test.ts server/src/__tests__/feedback-flush-controller.test.ts server/src/__tests__/error-handler.test.ts server/src/__tests__/board-mutation-guard.test.ts packages/db/src/backup-lib.test.ts` initially exposed local setup issues and two 5s test timeouts. - Rerun after local prereq build: `pnpm exec vitest run --testTimeout 15000 server/src/__tests__/issue-comment-reopen-routes.test.ts server/src/__tests__/issue-thread-interaction-routes.test.ts server/src/__tests__/feedback-flush-controller.test.ts server/src/__tests__/server-startup-feedback-export.test.ts` passed. - Some embedded Postgres-backed tests skipped on this host because local Postgres init was unavailable. ## Risks - Runtime-touching branch: startup/shutdown and issue interaction behavior should be reviewed carefully. - The feedback export change disables repeated flush attempts only for database connection-refused failures; other upload failures still log normally. - The plugin worker error guard avoids process crashes from unhandled EventEmitter errors but may hide errors from code paths that expected an emitted listener. > 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 Codex, GPT-5-based coding agent with local shell/git/tool use. Exact hosted model ID and context-window size are not exposed by the local Paperclip adapter runtime. ## 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 tests locally and they pass - [x] I have added or updated tests where applicable - [x] 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 --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
82 lines
2.5 KiB
TypeScript
82 lines
2.5 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
const mockApi = vi.hoisted(() => ({
|
|
get: vi.fn(),
|
|
post: vi.fn(),
|
|
}));
|
|
|
|
vi.mock("./client", () => ({
|
|
api: mockApi,
|
|
}));
|
|
|
|
import { issuesApi } from "./issues";
|
|
|
|
describe("issuesApi.list", () => {
|
|
beforeEach(() => {
|
|
mockApi.get.mockReset();
|
|
mockApi.post.mockReset();
|
|
mockApi.get.mockResolvedValue([]);
|
|
mockApi.post.mockResolvedValue({});
|
|
});
|
|
|
|
it("passes parentId through to the company issues endpoint", async () => {
|
|
await issuesApi.list("company-1", { parentId: "issue-parent-1", limit: 25 });
|
|
|
|
expect(mockApi.get).toHaveBeenCalledWith(
|
|
"/companies/company-1/issues?parentId=issue-parent-1&limit=25",
|
|
);
|
|
});
|
|
|
|
it("passes descendantOf through to the company issues endpoint", async () => {
|
|
await issuesApi.list("company-1", { descendantOf: "issue-root-1", includeBlockedBy: true, limit: 25 });
|
|
|
|
expect(mockApi.get).toHaveBeenCalledWith(
|
|
"/companies/company-1/issues?descendantOf=issue-root-1&includeBlockedBy=true&limit=25",
|
|
);
|
|
});
|
|
|
|
it("passes generic workspaceId filters through to the company issues endpoint", async () => {
|
|
await issuesApi.list("company-1", { workspaceId: "workspace-1", limit: 1000 });
|
|
|
|
expect(mockApi.get).toHaveBeenCalledWith(
|
|
"/companies/company-1/issues?workspaceId=workspace-1&limit=1000",
|
|
);
|
|
});
|
|
|
|
it("passes pagination offsets through to the company issues endpoint", async () => {
|
|
await issuesApi.list("company-1", { limit: 500, offset: 1500 });
|
|
|
|
expect(mockApi.get).toHaveBeenCalledWith(
|
|
"/companies/company-1/issues?limit=500&offset=1500",
|
|
);
|
|
});
|
|
|
|
it("passes issue list sort options through to the company issues endpoint", async () => {
|
|
await issuesApi.list("company-1", {
|
|
limit: 500,
|
|
sortField: "updated",
|
|
sortDir: "desc",
|
|
});
|
|
|
|
expect(mockApi.get).toHaveBeenCalledWith(
|
|
"/companies/company-1/issues?limit=500&sortField=updated&sortDir=desc",
|
|
);
|
|
});
|
|
|
|
it("posts recovery action resolution to the source issue endpoint", async () => {
|
|
await issuesApi.resolveRecoveryAction("issue-1", {
|
|
actionId: "00000000-0000-0000-0000-0000000000aa",
|
|
outcome: "restored",
|
|
sourceIssueStatus: "done",
|
|
});
|
|
|
|
expect(mockApi.post).toHaveBeenCalledWith(
|
|
"/issues/issue-1/recovery-actions/resolve",
|
|
{
|
|
actionId: "00000000-0000-0000-0000-0000000000aa",
|
|
outcome: "restored",
|
|
sourceIssueStatus: "done",
|
|
},
|
|
);
|
|
});
|
|
});
|