Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
fc930bc
feat(onboarding): de-CEO the first-task prompt (welcome→ask→propose→c…
scotttong Aug 6, 2026
a003a00
feat(onboarding): land on first task + stop seeding default helper ag…
scotttong Aug 6, 2026
ba60841
test(onboarding): assert wizard lands on first task, not dashboard
scotttong Aug 6, 2026
cbab3da
feat(onboarding): seed first-task greeting and suppress the descripti…
scotttong Aug 6, 2026
80428ae
fix(onboarding): greet the user by the agent's chosen name
scotttong Aug 6, 2026
84292f5
feat(onboarding): rename first task to "Paperclip onboarding" and ref…
scotttong Aug 6, 2026
0ff6ca8
fix(onboarding): stop page-memory bouncing launch to dashboard (PAP-404)
scotttong Aug 6, 2026
ad3b7ab
feat(task-chat): bring back copy/👍/👎 on the agent bubble footer (PAP-…
scotttong Aug 6, 2026
79b0fe2
fix(task-chat): settle resolved cards to resolution time; hide withdr…
scotttong Aug 6, 2026
1e610ad
feat(onboarding): single checkbox plan-approval card for hires/tasks …
scotttong Aug 6, 2026
a316ad5
feat(interactions): first-class free-text option in ask_user_question…
scotttong Aug 6, 2026
18ec112
feat(task-chat): unify plan-approval CTAs to Approve/Revise…/Reject; …
scotttong Aug 6, 2026
251fce1
fix(onboarding): expose plan in right sidebar on plan card; fix card …
scotttong Aug 7, 2026
aaa2071
fix(task-chat): standardize plan-approval bare-reject to "Reject"; ig…
scotttong Aug 7, 2026
28b7a5f
feat(onboarding): hide Properties sidebar on first task until plan ex…
scotttong Aug 7, 2026
37641d0
feat(task-chat): suppress degenerate ask_user_questions cards (render…
scotttong Aug 7, 2026
0a7e2a0
feat(onboarding): apply PAP-431 wizard edits (copy, spacing, skip fro…
scotttong Aug 7, 2026
f4db9fb
feat(onboarding): drop 'Everything's set up.' from final wizard subti…
scotttong Aug 7, 2026
5f3a2fd
feat(onboarding): rename dropdown "Create new company..." to "Create …
scotttong Aug 7, 2026
35b5c91
feat(onboarding): refine final wizard screen spacing & agent-name siz…
scotttong Aug 7, 2026
5e43696
feat(onboarding): match whitespace above capsule to name→checklist ga…
scotttong Aug 7, 2026
cdac5ff
fix(onboarding): gate first-task marker to human (board) actors
scotttong Aug 7, 2026
ff96f19
fix(onboarding): verify first-task server-side; keep single-option qu…
scotttong Aug 7, 2026
c138779
fix(onboarding): auto-supersede stale sibling ask_user_questions (PAP…
scotttong Aug 7, 2026
07faf8a
fix(ui): remove non-interactive 'Agents may resolve' badge from inter…
scotttong Aug 7, 2026
f73da0b
fix(onboarding): bring back the Show properties button on the first t…
scotttong Aug 7, 2026
7b18563
Change onboarding company label to Name
scotttong Aug 8, 2026
4241c24
Remove settings from company selector
scotttong Aug 8, 2026
e4f3d77
feat(ui): render live task output with transcript view
scotttong Aug 8, 2026
849efe5
fix(ui): stop midstream transcript loss — byte-budget trimming + stab…
scotttong Aug 8, 2026
c8b3b6f
feat(ui): port default-view streaming presentation to experimental li…
scotttong Aug 8, 2026
5061839
fix(ui): streaming resilience — poll-gap grace + keep transcript thro…
scotttong Aug 8, 2026
b9d7d2d
feat(ui): render experimental live tail via transcriptToTaskChatItems…
scotttong Aug 8, 2026
44d9c62
feat: remove enableTaskChatRedesign flag — chat-style tasks are the d…
scotttong Aug 8, 2026
b3a6a0b
test(e2e): update onboarding + composer specs for chat-style default UI
scotttong Aug 9, 2026
1be41d7
test(adapter-claude-local): retry temp-root cleanup to fix ENOTEMPTY …
scotttong Aug 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/adapter-utils/src/server-utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -887,6 +887,9 @@ describe("renderPaperclipWakePrompt", () => {
expect(DEFAULT_PAPERCLIP_AGENT_PROMPT_TEMPLATE).not.toContain(
"for request_confirmation this resumes only after acceptance",
);
expect(DEFAULT_PAPERCLIP_AGENT_PROMPT_TEMPLATE).toContain(
"Never create probe or throwaway issue-thread interactions to discover the interactions API shape or your permissions",
);
expect(DEFAULT_PAPERCLIP_AGENT_PROMPT_TEMPLATE).toContain("confirmation:{issueId}:plan:{revisionId}");
expect(DEFAULT_PAPERCLIP_AGENT_PROMPT_TEMPLATE).toContain("Wait for acceptance before creating implementation subtasks");
expect(DEFAULT_PAPERCLIP_AGENT_PROMPT_TEMPLATE).toContain(
Expand Down
1 change: 1 addition & 0 deletions packages/adapter-utils/src/server-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ export const DEFAULT_PAPERCLIP_AGENT_PROMPT_TEMPLATE = [
"- Create child issues directly when you know what needs to be done; use issue-thread interactions when the board/user must choose suggested tasks, answer structured questions, or confirm a proposal.",
"- Use `PAPERCLIP_SCRATCH_DIR` / `PAPERCLIP_RUN_SCRATCH_DIR` for temporary scratch files instead of ad hoc `/tmp` paths; Paperclip removes that run-owned directory after the run ends.",
"- To ask for that input, create an interaction on the current issue with POST /api/issues/{issueId}/interactions using kind suggest_tasks, ask_user_questions, or request_confirmation. Use continuationPolicy wake_assignee when you need to resume after a response (it wakes on acceptance and rejection alike; only expiry does not wake); use wake_assignee_on_accept when you want to resume only after acceptance.",
"- Never create probe or throwaway issue-thread interactions to discover the interactions API shape or your permissions; schema discovery goes through the OpenAPI spec and explicit validation errors, not placeholder cards. Every ask_user_questions, suggest_tasks, or request_confirmation you post must carry a real, answerable prompt; withdraw one you no longer need instead of leaving it pending.",
"- When you intentionally restart follow-up work on a completed assigned issue, include structured `resume: true` with the POST /api/issues/{issueId}/comments or PATCH /api/issues/{issueId} comment payload. Generic agent comments on closed issues are inert by default.",
"- For plan approval, update the plan document first, then create request_confirmation targeting the latest plan revision with idempotencyKey confirmation:{issueId}:plan:{revisionId}. Wait for acceptance before creating implementation subtasks, and create a fresh confirmation after superseding board/user comments if approval is still needed.",
"- If blocked, mark the issue blocked and name the unblock owner and action.",
Expand Down
9 changes: 8 additions & 1 deletion packages/adapters/claude-local/src/server/acp.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,14 @@ afterEach(async () => {
if (value === undefined) delete process.env[key];
else process.env[key] = value;
}
await Promise.all(tempRoots.splice(0).map((root) => fs.rm(root, { recursive: true, force: true })));
// The sandbox process-session bridge writes event files asynchronously; on slow
// CI shards a final write can race the recursive rm (ENOTEMPTY on the events
// dir), so let fs.rm retry until the writer has quiesced.
await Promise.all(
tempRoots
.splice(0)
.map((root) => fs.rm(root, { recursive: true, force: true, maxRetries: 10, retryDelay: 200 })),
);
});

class FakeRuntime {
Expand Down
5 changes: 5 additions & 0 deletions packages/shared/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,10 @@ export type IssueThreadInteractionContinuationPolicy =

export const TASK_WATCHDOG_PRODUCT_BUG_ORIGIN_KIND = "task_watchdog_product_bug";

// Marks the single onboarding "first task" so surfaces can special-case it
// (e.g. suppress the seeded-description bubble and rely on a seeded greeting).
export const ONBOARDING_FIRST_TASK_ORIGIN_KIND = "onboarding_first_task";

export const ISSUE_ORIGIN_KINDS = [
"manual",
"routine_execution",
Expand All @@ -304,6 +308,7 @@ export const ISSUE_ORIGIN_KINDS = [
"stranded_issue_recovery",
"task_watchdog",
TASK_WATCHDOG_PRODUCT_BUG_ORIGIN_KIND,
ONBOARDING_FIRST_TASK_ORIGIN_KIND,
] as const;
export type BuiltInIssueOriginKind = (typeof ISSUE_ORIGIN_KINDS)[number];
export type PluginIssueOriginKind = `plugin:${string}`;
Expand Down
8 changes: 0 additions & 8 deletions packages/shared/src/feature-catalog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,6 @@ export const INSTANCE_FEATURE_CATALOG: Record<InstanceFeatureKey, FeatureCatalog
cloudDefault: false,
selfHostedDefault: false,
},
enableTaskChatRedesign: {
title: "Chat-Style Tasks",
description:
"Reimagines the task detail page as a live conversation with your agents: chat bubbles for people and agents, streaming activity — thinking, tool calls, diffs — that folds into a one-line summary when a turn finishes, inline plan/question/permission cards, a three-mode composer (Agent · Plan · Ask), and a resizable Properties · Plan · Artifacts pane.",
tier: "preference",
cloudDefault: false,
selfHostedDefault: false,
},
enableTaskWatchdogs: {
title: "Task Watchdogs",
description:
Expand Down
1 change: 1 addition & 0 deletions packages/shared/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ export {
ISSUE_THREAD_INTERACTION_CONTINUATION_POLICIES,
ISSUE_ORIGIN_KINDS,
TASK_WATCHDOG_PRODUCT_BUG_ORIGIN_KIND,
ONBOARDING_FIRST_TASK_ORIGIN_KIND,
ISSUE_WATCHDOG_DISCOVERY_KINDS,
ISSUE_SURFACE_VISIBILITIES,
ISSUE_RECOVERY_ACTION_KINDS,
Expand Down
1 change: 0 additions & 1 deletion packages/shared/src/types/instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ export interface InstanceExperimentalSettings {
enablePipelines: boolean;
enableCases: boolean;
enableConferenceRoomChat: boolean;
enableTaskChatRedesign: boolean;
enableTaskWatchdogs: boolean;
enableIssuePlanDecompositions: boolean;
enableExperimentalFileViewer: boolean;
Expand Down
13 changes: 12 additions & 1 deletion packages/shared/src/types/issue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1077,6 +1077,14 @@ export interface AskUserQuestionsQuestionOption {
id: string;
label: string;
description?: string | null;
/**
* When true, selecting this option reveals an inline free-text field instead
* of acting as an inert choice. The typed answer is submitted as the
* question's `otherText`. Author at most one free-text option per question and
* do not add dead "I'll describe it" options that only duplicate the built-in
* free-text affordance.
*/
freeText?: boolean;
}

export interface AskUserQuestionsQuestion {
Expand Down Expand Up @@ -1109,8 +1117,11 @@ export interface AskUserQuestionsResult {
answers: AskUserQuestionsAnswer[];
cancelled?: true;
cancellationReason?: string | null;
expirationReason?: "superseded_by_comment";
expirationReason?: "superseded_by_comment" | "superseded_by_newer_interaction";
commentId?: string | null;
// Set with expirationReason "superseded_by_newer_interaction": the newer
// sibling ask_user_questions that replaced this one (PAP-437).
supersededByInteractionId?: string | null;
summaryMarkdown?: string | null;
}

Expand Down
1 change: 0 additions & 1 deletion packages/shared/src/validators/instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ export const instanceExperimentalSettingsSchema = z.object({
enablePipelines: z.boolean().default(false),
enableCases: z.boolean().default(false),
enableConferenceRoomChat: z.boolean().default(false),
enableTaskChatRedesign: z.boolean().default(false),
enableTaskWatchdogs: z.boolean().default(false),
enableIssuePlanDecompositions: z.boolean().default(false),
enableExperimentalFileViewer: z.boolean().default(false),
Expand Down
35 changes: 33 additions & 2 deletions packages/shared/src/validators/issue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -491,13 +491,24 @@ const createIssueDuplicateGuardSchema = {
.default(false),
};

// Narrow intent flag set by the onboarding wizard on the single first task. The
// server owns the resulting origin kind (clients cannot set arbitrary origin
// kinds) and uses it to seed the agent greeting instead of an LLM welcome step.
const onboardingFirstTaskMarkerSchema = {
onboardingFirstTask: z.boolean().optional(),
};

export const createIssueInputSchema = createIssueBaseSchema.extend({
status: createIssueBaseSchema.shape.status.optional(),
...createIssueDuplicateGuardSchema,
...onboardingFirstTaskMarkerSchema,
});

export const createIssueSchema = withCreateIssueStatusDefault(
createIssueBaseSchema.extend(createIssueDuplicateGuardSchema),
createIssueBaseSchema.extend({
...createIssueDuplicateGuardSchema,
...onboardingFirstTaskMarkerSchema,
}),
).superRefine(requireBlockedStatusForUnblockDescriptor);

export type CreateIssue = z.infer<typeof createIssueSchema>;
Expand Down Expand Up @@ -759,6 +770,12 @@ export const askUserQuestionsQuestionOptionSchema = z.object({
id: z.string().trim().min(1).max(120),
label: z.string().trim().min(1).max(120),
description: z.string().trim().max(500).nullable().optional(),
freeText: z
.boolean()
.optional()
.describe(
"When true, selecting this option reveals an inline text field; the typed value is returned as the question's otherText. Use this for a real \"I'll describe it\" choice instead of authoring a dead option that does nothing. At most one free-text option per question.",
),
});

export const askUserQuestionsQuestionSchema = z.object({
Expand Down Expand Up @@ -789,6 +806,7 @@ export const askUserQuestionsPayloadSchema = z.object({
seenQuestionIds.add(question.id);

const seenOptionIds = new Set<string>();
let freeTextOptionCount = 0;
for (const [optionIndex, option] of question.options.entries()) {
if (seenOptionIds.has(option.id)) {
ctx.addIssue({
Expand All @@ -798,6 +816,16 @@ export const askUserQuestionsPayloadSchema = z.object({
});
}
seenOptionIds.add(option.id);
if (option.freeText) {
freeTextOptionCount += 1;
if (freeTextOptionCount > 1) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "A question may declare at most one free-text option",
path: ["questions", questionIndex, "options", optionIndex, "freeText"],
});
}
}
}
}
});
Expand All @@ -815,8 +843,11 @@ export const askUserQuestionsResultSchema = z.object({
answers: z.array(askUserQuestionsAnswerSchema).max(20),
cancelled: z.literal(true).optional(),
cancellationReason: z.string().trim().max(4000).nullable().optional(),
expirationReason: z.literal("superseded_by_comment").optional(),
expirationReason: z.enum(["superseded_by_comment", "superseded_by_newer_interaction"]).optional(),
commentId: z.string().uuid().nullable().optional(),
// Set alongside expirationReason "superseded_by_newer_interaction": the id of
// the newer sibling ask_user_questions that replaced this one (PAP-437).
supersededByInteractionId: z.string().uuid().nullable().optional(),
summaryMarkdown: z.string().max(20000).nullable().optional(),
});

Expand Down
56 changes: 38 additions & 18 deletions server/src/__tests__/built-in-agents.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,7 @@ describeEmbeddedPostgres("built-in agents", () => {
});
});

it("auto-provisions a paused Reflection Coach bundle with skill sync and a disabled routine", async () => {
it("reconciles an enabled Reflection Coach bundle with skill sync and a disabled routine", async () => {
const companyId = await seedCompany({ requireApproval: false });
const root = await agentService(db).create(companyId, {
name: "CEO",
Expand All @@ -581,6 +581,17 @@ describeEmbeddedPostgres("built-in agents", () => {
permissions: {},
});

// The Reflection Coach is opt-in (not auto-created). Enabling it on demand
// materializes its managed bundle in a single pass.
const enabled = await builtInAgentService(db).ensure(companyId, "reflection-coach");
expect(enabled.agent?.adapterConfig).toMatchObject({
instructionsBundleMode: "managed",
instructionsEntryFile: "AGENTS.md",
});
expect(enabled.agent?.adapterConfig).not.toMatchObject({ model: "gpt-5.4", apiKey: "do-not-copy" });

// Startup reconcile keeps the enabled bundle tracking stock and re-grants
// the root/company default permissions.
const result = await reconcileBuiltInAgentsOnStartup(db);
expect(result.autoEnsured).toBeGreaterThanOrEqual(1);
expect(result.defaultGrantsEnsured).toBeGreaterThanOrEqual(4);
Expand All @@ -606,11 +617,6 @@ describeEmbeddedPostgres("built-in agents", () => {
},
},
});
expect(state.agent?.adapterConfig).toMatchObject({
instructionsBundleMode: "managed",
instructionsEntryFile: "AGENTS.md",
});
expect(state.agent?.adapterConfig).not.toMatchObject({ model: "gpt-5.4", apiKey: "do-not-copy" });
expect(state.resources.map((resource) => [resource.resourceKind, resource.stockStatus])).toEqual([
["instructions", "stock_current"],
["skill", "stock_current"],
Expand Down Expand Up @@ -693,7 +699,7 @@ describeEmbeddedPostgres("built-in agents", () => {
)).size).toBe(3);
});

it("preserves new-agent approval gates during automatic Reflection Coach provisioning", async () => {
it("preserves new-agent approval gates during on-demand Reflection Coach provisioning", async () => {
const companyId = await seedCompany({ requireApproval: true });
const root = await agentService(db).create(companyId, {
name: "CEO",
Expand All @@ -710,12 +716,11 @@ describeEmbeddedPostgres("built-in agents", () => {
applyInSeparateFollowUpRun: true,
};

const result = await reconcileBuiltInAgentsOnStartup(db);

expect(result).toMatchObject({
autoEnsured: 2,
pendingApprovals: 2,
});
// The Reflection Coach is opt-in, so it's enabled on demand. With board
// approval required, provisioning it must leave a pending agent + a
// hire_agent approval rather than an active agent.
const provisioned = await builtInAgentService(db).provision(companyId, "reflection-coach");
expect(provisioned.approval).not.toBeNull();
const state = await builtInAgentService(db).get(companyId, "reflection-coach");
expect(state).toMatchObject({
status: "pending_approval",
Expand Down Expand Up @@ -751,7 +756,7 @@ describeEmbeddedPostgres("built-in agents", () => {
});

const pendingReconcile = await reconcileBuiltInAgentsOnStartup(db);
expect(pendingReconcile.pendingApprovals).toBe(2);
expect(pendingReconcile.pendingApprovals).toBe(1);
const stillPending = await builtInAgentService(db).get(companyId, "reflection-coach");
expect(stillPending).toMatchObject({
status: "pending_approval",
Expand Down Expand Up @@ -787,7 +792,7 @@ describeEmbeddedPostgres("built-in agents", () => {
const agentRows = await db.select().from(agents).where(eq(agents.companyId, companyId));
expect(agentRows.filter((row) => readBuiltInAgentMarker(row.metadata)?.key === "reflection-coach")).toHaveLength(1);
const approvalRows = await db.select().from(approvals).where(eq(approvals.companyId, companyId));
expect(approvalRows).toHaveLength(2);
expect(approvalRows).toHaveLength(1);
});

it("preserves Reflection Coach instruction drift on reconcile and restores it on reset", async () => {
Expand Down Expand Up @@ -1062,7 +1067,21 @@ describeEmbeddedPostgres("built-in agents", () => {
const { olderId, newerId } = await seedLegacyDuplicateBriefs(affectedCompanyId);
// A second company created after the affected one — previously skipped
// entirely because the duplicate error escaped the reconciliation loop.
// Give it a drifted built-in row so we can prove reconcile still reached it.
const healthyCompanyId = await seedCompany({ requireApproval: false });
const healthyBriefsId = randomUUID();
await db.insert(agents).values({
id: healthyBriefsId,
companyId: healthyCompanyId,
name: "Stale Briefs",
role: "engineer",
status: "idle",
adapterType: "codex_local",
adapterConfig: { model: "gpt-5.4" },
runtimeConfig: {},
permissions: {},
metadata: withBuiltInAgentMarker({}, { key: "briefs", featureKeys: ["briefs"] }),
});

const result = await reconcileBuiltInAgentsOnStartup(db);
expect(result.companyFailures).toBe(0);
Expand All @@ -1077,9 +1096,10 @@ describeEmbeddedPostgres("built-in agents", () => {
),
).toHaveLength(1);

// The company after the affected one still had its bundled agents provisioned.
const healthyCoach = await builtInAgentService(db).get(healthyCompanyId, "reflection-coach");
expect(healthyCoach.agentId).toBeTruthy();
// The company after the affected one was still reconciled (its drifted
// built-in row was repaired to stock) rather than skipped.
const [healthyBriefs] = await db.select().from(agents).where(eq(agents.id, healthyBriefsId));
expect(healthyBriefs?.name).toBe("Briefs Agent");
});

it("automatically materializes the Reflection Coach bundle without enabling background work", async () => {
Expand Down
29 changes: 17 additions & 12 deletions server/src/__tests__/companies-service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
} from "./helpers/embedded-postgres.js";
import { companyService } from "../services/companies.js";
import { readBuiltInAgentMarker } from "../services/built-in-agent-metadata.js";
import { reconcileBuiltInAgentsOnStartup } from "../services/built-in-agents.js";
import { builtInAgentService, reconcileBuiltInAgentsOnStartup } from "../services/built-in-agents.js";

const embeddedPostgresSupport = await getEmbeddedPostgresTestSupport();
const describeEmbeddedPostgres = embeddedPostgresSupport.supported ? describe : describe.skip;
Expand Down Expand Up @@ -81,19 +81,28 @@ describeEmbeddedPostgres("companyService", () => {
expect(rows.map((row) => row.issuePrefix).sort()).toEqual(["ARO", "AROA"]);
});

it("auto-provisions one paused Reflection Coach bundle for a freshly created company", async () => {
it("does not auto-provision bundled built-in agents for a freshly created company", async () => {
const created = await companyService(db).create({
name: "Fresh Company",
});

// A new company starts clean: the Reflection Coach and Summarizer are
// opt-in, not seeded by default for a new user.
const agentRows = await db.select().from(agents).where(eq(agents.companyId, created.id));
const reflectionRows = agentRows.filter((row) => readBuiltInAgentMarker(row.metadata)?.key === "reflection-coach");
expect(reflectionRows).toHaveLength(1);
expect(reflectionRows[0]).toMatchObject({
expect(agentRows.filter((row) => readBuiltInAgentMarker(row.metadata))).toHaveLength(0);

// Startup reconcile leaves a fresh company untouched — nothing is created.
await reconcileBuiltInAgentsOnStartup(db);
const afterReconcileRows = await db.select().from(agents).where(eq(agents.companyId, created.id));
expect(afterReconcileRows.filter((row) => readBuiltInAgentMarker(row.metadata))).toHaveLength(0);

// The Reflection Coach remains available to enable on demand, and enabling
// it materializes its bundled skill + paused routine.
const enabled = await builtInAgentService(db).ensure(created.id, "reflection-coach");
expect(enabled.agent).toMatchObject({
name: "Reflection Coach",
status: "paused",
budgetMonthlyCents: 0,
spentMonthlyCents: 0,
});

const [skill] = await db
Expand All @@ -110,10 +119,10 @@ describeEmbeddedPostgres("companyService", () => {
const [routine] = await db
.select()
.from(routines)
.where(and(eq(routines.companyId, created.id), eq(routines.assigneeAgentId, reflectionRows[0]!.id)));
.where(and(eq(routines.companyId, created.id), eq(routines.assigneeAgentId, enabled.agentId!)));
expect(routine).toMatchObject({
status: "paused",
assigneeAgentId: reflectionRows[0]!.id,
assigneeAgentId: enabled.agentId,
originKind: "built_in_agent_bundle",
originId: "reflection-coach:recent-agent-reflection",
});
Expand All @@ -122,10 +131,6 @@ describeEmbeddedPostgres("companyService", () => {
kind: "schedule",
enabled: false,
});

await reconcileBuiltInAgentsOnStartup(db);
const afterReconcileRows = await db.select().from(agents).where(eq(agents.companyId, created.id));
expect(afterReconcileRows.filter((row) => readBuiltInAgentMarker(row.metadata)?.key === "reflection-coach")).toHaveLength(1);
});

it("archives companies by pausing runnable agents and cancelling active runs", async () => {
Expand Down
1 change: 0 additions & 1 deletion server/src/__tests__/instance-settings-service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ describe("instance settings service", () => {
enableStreamlinedLeftNavigation: true,
enableApps: false,
enableConferenceRoomChat: false,
enableTaskChatRedesign: false,
enableExternalObjects: false,
enableSmokeLab: false,
enablePipelines: false,
Expand Down
Loading
Loading