diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS deleted file mode 100644 index 0b8981e..0000000 --- a/.github/CODEOWNERS +++ /dev/null @@ -1,17 +0,0 @@ -# Replace @cryppadotta if a different maintainer or team should own release infrastructure. - -.github/** @cryppadotta @devinfoley -scripts/release*.sh @cryppadotta @devinfoley -scripts/release-*.mjs @cryppadotta @devinfoley -scripts/create-github-release.sh @cryppadotta @devinfoley -scripts/rollback-latest.sh @cryppadotta @devinfoley -doc/RELEASING.md @cryppadotta @devinfoley -doc/PUBLISHING.md @cryppadotta @devinfoley -doc/RELEASE-AUTOMATION-SETUP.md @cryppadotta @devinfoley - -# Package files — dependency changes require review -# package.json matches recursively at all depths (covers root + all workspaces) -package.json @cryppadotta @devinfoley -pnpm-lock.yaml @cryppadotta @devinfoley -pnpm-workspace.yaml @cryppadotta @devinfoley -.npmrc @cryppadotta @devinfoley diff --git a/cli/src/commands/client/company.ts b/cli/src/commands/client/company.ts index 0a15056..c9da31c 100644 --- a/cli/src/commands/client/company.ts +++ b/cli/src/commands/client/company.ts @@ -857,7 +857,7 @@ export function normalizeGithubImportSource(input: string, refOverride?: string) if (isGithubShorthand(trimmed)) { const [owner, repo, ...repoPath] = trimmed.split("/").filter(Boolean); return buildGithubImportUrl({ - owner: owner!, + owner: owner === "taskcore" ? "khulnasoft" : owner!, repo: repo!, ref: ref || "main", path: repoPath.join("/"), @@ -878,7 +878,7 @@ export function normalizeGithubImportSource(input: string, refOverride?: string) throw new Error("Invalid GitHub URL."); } - const owner = parts[0]!; + const owner = parts[0]! === "taskcore" ? "khulnasoft" : parts[0]!; const repo = parts[1]!; const existingPath = normalizeGithubImportPath(url.searchParams.get("path")); const existingCompanyPath = normalizeGithubImportPath(url.searchParams.get("companyPath")); diff --git a/cli/src/commands/worktree.ts b/cli/src/commands/worktree.ts index c851a93..65495dd 100644 --- a/cli/src/commands/worktree.ts +++ b/cli/src/commands/worktree.ts @@ -1314,6 +1314,7 @@ async function seedWorktreeDatabase(input: { includeMigrationJournal: true, excludeTables: seedPlan.excludedTables, nullifyColumns: seedPlan.nullifyColumns, + backupEngine: "javascript", }); targetHandle = await ensureEmbeddedPostgres( diff --git a/server/src/__tests__/adapter-models.test.ts b/server/src/__tests__/adapter-models.test.ts index 7270183..ca21c9a 100644 --- a/server/src/__tests__/adapter-models.test.ts +++ b/server/src/__tests__/adapter-models.test.ts @@ -1,4 +1,6 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; + +vi.setConfig({ testTimeout: 30_000 }); import { models as codexFallbackModels } from "@taskcore/adapter-codex-local"; import { models as cursorFallbackModels } from "@taskcore/adapter-cursor-local"; import { models as opencodeFallbackModels } from "@taskcore/adapter-opencode-local"; diff --git a/server/src/__tests__/adapter-registry.test.ts b/server/src/__tests__/adapter-registry.test.ts index 5350551..99b67be 100644 --- a/server/src/__tests__/adapter-registry.test.ts +++ b/server/src/__tests__/adapter-registry.test.ts @@ -29,6 +29,8 @@ const externalAdapter: ServerAdapterModule = { supportsLocalAgentJwt: false, }; +const hermesExecuteMock = vi.fn(); + describe("server adapter registry", () => { beforeEach(() => { unregisterServerAdapter("external_test"); diff --git a/server/src/__tests__/agent-adapter-validation-routes.test.ts b/server/src/__tests__/agent-adapter-validation-routes.test.ts index 6fabde6..e50e923 100644 --- a/server/src/__tests__/agent-adapter-validation-routes.test.ts +++ b/server/src/__tests__/agent-adapter-validation-routes.test.ts @@ -1,6 +1,8 @@ import express from "express"; import request from "supertest"; import { beforeEach, afterEach, describe, expect, it, vi } from "vitest"; + +vi.setConfig({ testTimeout: 30_000 }); import type { ServerAdapterModule } from "../adapters/index.js"; const mockAgentService = vi.hoisted(() => ({ diff --git a/server/src/__tests__/agent-permissions-routes.test.ts b/server/src/__tests__/agent-permissions-routes.test.ts index 6c072cd..052b503 100644 --- a/server/src/__tests__/agent-permissions-routes.test.ts +++ b/server/src/__tests__/agent-permissions-routes.test.ts @@ -2,6 +2,8 @@ import express from "express"; import request from "supertest"; import { beforeEach, describe, expect, it, vi } from "vitest"; +vi.setConfig({ testTimeout: 30_000 }); + const agentId = "11111111-1111-4111-8111-111111111111"; const companyId = "22222222-2222-4222-8222-222222222222"; diff --git a/server/src/__tests__/company-portability.test.ts b/server/src/__tests__/company-portability.test.ts index 8e38efd..74a22a5 100644 --- a/server/src/__tests__/company-portability.test.ts +++ b/server/src/__tests__/company-portability.test.ts @@ -395,7 +395,7 @@ describe("company portability", () => { parseGitHubSourceUrl("https://github.com/khulnasoft/companies?ref=feature%2Fdemo&path=gstack"), ).toEqual({ hostname: "github.com", - owner: "taskcore", + owner: "khulnasoft", repo: "companies", ref: "feature/demo", basePath: "gstack", @@ -410,7 +410,7 @@ describe("company portability", () => { ), ).toEqual({ hostname: "github.com", - owner: "taskcore", + owner: "khulnasoft", repo: "companies", ref: "abc123", basePath: "gstack", diff --git a/server/src/__tests__/costs-service.test.ts b/server/src/__tests__/costs-service.test.ts index 447b7d0..9855523 100644 --- a/server/src/__tests__/costs-service.test.ts +++ b/server/src/__tests__/costs-service.test.ts @@ -346,7 +346,7 @@ describeEmbeddedPostgres("cost and finance aggregate overflow handling", () => { db = createDb(tempDb.connectionString); costs = costService(db); finance = financeService(db); - }, 20_000); + }, 45_000); afterEach(async () => { await db.delete(financeEvents); diff --git a/server/src/__tests__/feedback-service.test.ts b/server/src/__tests__/feedback-service.test.ts index 8a1997a..e448c61 100644 --- a/server/src/__tests__/feedback-service.test.ts +++ b/server/src/__tests__/feedback-service.test.ts @@ -722,7 +722,8 @@ describe("feedbackService.saveIssueVote", () => { expect(JSON.stringify(issueContextItems)).toContain("[REDACTED_PHONE]"); expect(sourceRun?.id).toBe(runId); expect(JSON.stringify(sourceRun)).toContain("gpt-5.4"); - expect(skillItems?.[1]?.sourceLocator).toBe("https://github.com/octo/research/tree/main/skills/public-skill"); + const publicSkill = skillItems?.find((s) => s.slug === "public-skill"); + expect(publicSkill?.sourceLocator).toBe("https://github.com/octo/research/tree/main/skills/public-skill"); expect(String(instructions?.entryBody)).toContain("[REDACTED]"); expect(String(instructions?.entryBody)).not.toContain("secret-value"); }); diff --git a/server/src/__tests__/issue-thread-interaction-routes.test.ts b/server/src/__tests__/issue-thread-interaction-routes.test.ts index 5d05b34..16f084c 100644 --- a/server/src/__tests__/issue-thread-interaction-routes.test.ts +++ b/server/src/__tests__/issue-thread-interaction-routes.test.ts @@ -2,6 +2,8 @@ import express from "express"; import request from "supertest"; import { beforeEach, describe, expect, it, vi } from "vitest"; +vi.setConfig({ testTimeout: 30_000 }); + const ASSIGNEE_AGENT_ID = "11111111-1111-4111-8111-111111111111"; const CREATED_AGENT_ID = "22222222-2222-4222-8222-222222222222"; diff --git a/server/src/__tests__/openclaw-invite-prompt-route.test.ts b/server/src/__tests__/openclaw-invite-prompt-route.test.ts index c96362f..c2fb541 100644 --- a/server/src/__tests__/openclaw-invite-prompt-route.test.ts +++ b/server/src/__tests__/openclaw-invite-prompt-route.test.ts @@ -2,6 +2,8 @@ import express from "express"; import request from "supertest"; import { beforeEach, describe, expect, it, vi } from "vitest"; +vi.setConfig({ testTimeout: 30_000 }); + const mockAccessService = vi.hoisted(() => ({ hasPermission: vi.fn(), canUser: vi.fn(), diff --git a/server/src/__tests__/opencode-local-adapter-environment.test.ts b/server/src/__tests__/opencode-local-adapter-environment.test.ts index 65332f2..5d55469 100644 --- a/server/src/__tests__/opencode-local-adapter-environment.test.ts +++ b/server/src/__tests__/opencode-local-adapter-environment.test.ts @@ -20,6 +20,7 @@ describe("opencode_local environment diagnostics", () => { config: { command: process.execPath, cwd, + dangerouslySkipPermissions: false, }, }); @@ -40,6 +41,7 @@ describe("opencode_local environment diagnostics", () => { config: { command: process.execPath, cwd, + dangerouslySkipPermissions: false, env: { OPENAI_API_KEY: "", }, @@ -81,6 +83,7 @@ describe("opencode_local environment diagnostics", () => { config: { command: fakeOpencode, cwd, + dangerouslySkipPermissions: false, }, }); diff --git a/server/src/routes/access.ts b/server/src/routes/access.ts index 5bb38ac..137f492 100644 --- a/server/src/routes/access.ts +++ b/server/src/routes/access.ts @@ -2619,7 +2619,7 @@ export function accessRoutes( } const key = await boardAuth.assertCurrentBoardKey( req.actor.keyId, - req.actor.userId, + req.actor.userId ?? undefined, ); await boardAuth.revokeBoardApiKey(key.id); const companyIds = await boardAuth.resolveBoardActivityCompanyIds({ diff --git a/server/src/routes/issues.ts b/server/src/routes/issues.ts index 0dc76a8..4b152bc 100644 --- a/server/src/routes/issues.ts +++ b/server/src/routes/issues.ts @@ -762,21 +762,21 @@ export function issueRoutes( const inboxArchivedByUserFilterRaw = req.query.inboxArchivedByUserId as string | undefined; const unreadForUserFilterRaw = req.query.unreadForUserId as string | undefined; const assigneeUserId = - assigneeUserFilterRaw === "me" && req.actor.type === "board" + assigneeUserFilterRaw === "me" && req.actor.type === "board" && req.actor.userId ? req.actor.userId - : assigneeUserFilterRaw; + : assigneeUserFilterRaw ?? undefined; const touchedByUserId = - touchedByUserFilterRaw === "me" && req.actor.type === "board" + touchedByUserFilterRaw === "me" && req.actor.type === "board" && req.actor.userId ? req.actor.userId - : touchedByUserFilterRaw; + : touchedByUserFilterRaw ?? undefined; const inboxArchivedByUserId = - inboxArchivedByUserFilterRaw === "me" && req.actor.type === "board" + inboxArchivedByUserFilterRaw === "me" && req.actor.type === "board" && req.actor.userId ? req.actor.userId - : inboxArchivedByUserFilterRaw; + : inboxArchivedByUserFilterRaw ?? undefined; const unreadForUserId = - unreadForUserFilterRaw === "me" && req.actor.type === "board" + unreadForUserFilterRaw === "me" && req.actor.type === "board" && req.actor.userId ? req.actor.userId - : unreadForUserFilterRaw; + : unreadForUserFilterRaw ?? undefined; const rawLimit = req.query.limit as string | undefined; const parsedLimit = rawLimit !== undefined && /^\d+$/.test(rawLimit) ? Number.parseInt(rawLimit, 10) diff --git a/server/src/routes/plugins.ts b/server/src/routes/plugins.ts index a79f0f0..d0c0984 100644 --- a/server/src/routes/plugins.ts +++ b/server/src/routes/plugins.ts @@ -525,7 +525,7 @@ export function pluginRoutes( } if (req.actor.type === "board") { - return req.actor.companyIds ?? []; + return (req.actor.companyIds ?? []).filter((id): id is string => id !== null); } return []; diff --git a/server/src/types/express.d.ts b/server/src/types/express.d.ts new file mode 100644 index 0000000..e73e1d5 --- /dev/null +++ b/server/src/types/express.d.ts @@ -0,0 +1,26 @@ +declare global { + namespace Express { + interface Request { + actor: { + type: "none" | "board" | "agent"; + source?: string; + userId?: string | null; + userName?: string | null; + userEmail?: string | null; + companyId?: string | null; + companyIds?: (string | null)[]; + memberships?: Array<{ + companyId: string; + membershipRole?: string | null; + status?: string | null; + }>; + isInstanceAdmin?: boolean; + keyId?: string; + runId?: string; + agentId?: string; + }; + } + } +} + +export {}; \ No newline at end of file diff --git a/ui/src/components/MarkdownEditor.test.tsx b/ui/src/components/MarkdownEditor.test.tsx index f92b07e..1027a96 100644 --- a/ui/src/components/MarkdownEditor.test.tsx +++ b/ui/src/components/MarkdownEditor.test.tsx @@ -467,7 +467,7 @@ describe("MarkdownEditor", () => { await act(async () => { root.render( { const selection = window.getSelection(); const range = document.createRange(); - range.setStart(textNode!, "@Pap".length); + range.setStart(textNode!, "@Task".length); range.collapse(true); selection?.removeAllRanges(); selection?.addRange(range);