From 32e67a84eb93cde2ca638014a679bacf90874b2b Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Fri, 28 Aug 2026 21:13:17 +0000 Subject: [PATCH] (janitor/dedupe): consolidate code review terminal reasons onto db enum CODE_REVIEW_TERMINAL_REASONS (packages/db) and CLOUD_AGENT_TERMINAL_REASONS (packages/worker-utils) carried the same 38-literal list of code review terminal reasons, kept in sync manually and guarded by a parity test in apps/web. A mismatch between the two would make the orchestrator send a reason the callback allowlist rejects (or the worker's zod enum silently coerce a valid reason to undefined). The db list is the authoritative persistence enum, and worker-utils already depends on @kilocode/db, so the dependency direction is clean: - packages/db: CODE_REVIEW_TERMINAL_REASONS is now documented as the single source of truth. - packages/worker-utils/cloud-agent-next-client: delete the duplicated array and type; re-export them from @kilocode/db/schema-types under the existing CLOUD_AGENT_TERMINAL_REASONS / CloudAgentTerminalReason names so the public API for code-review-infra is unchanged. - apps/web: drop the now-trivial list parity test. No behavior change: the two lists were byte-identical. --- .../terminal-reason-from-failure.test.ts | 13 ---- packages/db/src/schema-types.ts | 8 ++- .../src/cloud-agent-next-client.ts | 60 ++++--------------- 3 files changed, 15 insertions(+), 66 deletions(-) diff --git a/apps/web/src/lib/code-reviews/terminal-reason-from-failure.test.ts b/apps/web/src/lib/code-reviews/terminal-reason-from-failure.test.ts index 22d38c5f4b6..bcae3403116 100644 --- a/apps/web/src/lib/code-reviews/terminal-reason-from-failure.test.ts +++ b/apps/web/src/lib/code-reviews/terminal-reason-from-failure.test.ts @@ -3,22 +3,9 @@ import { CLOUD_AGENT_FAILURE_CODES, WORKSPACE_FAILURE_SUBTYPES, } from '@kilocode/worker-utils/cloud-agent-failure'; -import { CLOUD_AGENT_TERMINAL_REASONS } from '@kilocode/worker-utils/cloud-agent-next-client'; import { CODE_REVIEW_TERMINAL_REASONS } from '@kilocode/db/schema-types'; import { terminalReasonFromCloudAgentFailure } from './terminal-reason-from-failure'; -describe('terminal reason list parity', () => { - // These two lists live in separate packages that cannot import each other, so - // drift is only caught here. A mismatch makes the orchestrator send a reason - // the callback allowlist rejects, or makes the worker's zod enum silently - // coerce a valid reason to undefined via its `.catch(undefined)`. - it('keeps the db and worker-utils terminal reason lists identical', () => { - expect([...CLOUD_AGENT_TERMINAL_REASONS].sort()).toEqual( - [...CODE_REVIEW_TERMINAL_REASONS].sort() - ); - }); -}); - describe('terminalReasonFromCloudAgentFailure', () => { it('returns undefined without a structured failure', () => { expect(terminalReasonFromCloudAgentFailure(undefined)).toBeUndefined(); diff --git a/packages/db/src/schema-types.ts b/packages/db/src/schema-types.ts index df3510f6b51..cc22107fde5 100644 --- a/packages/db/src/schema-types.ts +++ b/packages/db/src/schema-types.ts @@ -2210,9 +2210,11 @@ export type StripeSubscriptionStatus = /** * Valid values for cloud_agent_code_reviews.terminal_reason. - * KEEP IN SYNC with CloudAgentTerminalReason in - * packages/worker-utils/src/cloud-agent-next-client.ts — both lists must - * contain the same literal values. + * + * Single source of truth for the code review terminal reason enum. Worker-side + * consumers re-export this as CLOUD_AGENT_TERMINAL_REASONS in + * packages/worker-utils/src/cloud-agent-next-client.ts rather than maintaining + * a second copy. */ export const CODE_REVIEW_TERMINAL_REASONS = [ 'billing', diff --git a/packages/worker-utils/src/cloud-agent-next-client.ts b/packages/worker-utils/src/cloud-agent-next-client.ts index a85e74ea0f0..3d15f59722b 100644 --- a/packages/worker-utils/src/cloud-agent-next-client.ts +++ b/packages/worker-utils/src/cloud-agent-next-client.ts @@ -8,6 +8,11 @@ * transport layer and response parsing. */ +import { + CODE_REVIEW_TERMINAL_REASONS, + type CodeReviewTerminalReason as CloudAgentTerminalReason, +} from '@kilocode/db/schema-types'; + // --------------------------------------------------------------------------- // Types — aligned with cloud-agent-next tRPC router contracts // --------------------------------------------------------------------------- @@ -155,57 +160,12 @@ export type CloudAgentInterruptOutput = { * services/code-review-infra/src/types.ts, where a missing value used to be * silently coerced to undefined by a `.catch(undefined)` zod enum. * - * KEEP IN SYNC with CODE_REVIEW_TERMINAL_REASONS in - * packages/db/src/schema-types.ts — both lists must contain the same literal - * values, and a mismatch makes the orchestrator send a reason the callback's - * allowlist rejects. apps/web asserts the two are equal (see - * apps/web/src/lib/code-reviews/terminal-reason-from-failure.test.ts). + * Single source of truth is CODE_REVIEW_TERMINAL_REASONS in + * packages/db/src/schema-types.ts; re-exported here under the worker-side + * name for orchestrator consumers. */ -export const CLOUD_AGENT_TERMINAL_REASONS = [ - 'billing', - 'model_not_found', - 'github_installation_required', - 'github_ip_allow_list', - 'gitlab_project_access_required', - 'byok_invalid_key', - 'selected_model_unavailable', - 'repeated_repository_clone_timeout', - 'user_cancelled', - 'superseded', - 'interrupted', - 'timeout', - 'upstream_error', - 'sandbox_error', - 'workspace_capacity', - 'assistant_failed', - 'assistant_rate_limited', - 'assistant_rate_limited_byok', - 'assistant_rate_limited_managed', - 'assistant_unavailable', - 'assistant_timeout', - 'assistant_unauthorized', - 'assistant_invalid_request', - 'assistant_no_reply', - 'wrapper_failed', - 'runtime_startup_failed', - 'sandbox_connection', - 'delivery_failed', - 'workspace_setup_failed', - 'repository_clone_failed', - 'repository_auth_failed', - 'repository_checkout_failed', - 'session_import_failed', - 'setup_command_failed', - 'container_shutdown', - // Written only by the stale review reaper on the app side, never sent by the - // orchestrator. It is listed here because this enum and the db one are kept - // identical: the callback allowlist is built from this list, so an omission - // would reject the reason if it ever did arrive on a callback. - 'abandoned', - 'unknown', -] as const; - -export type CloudAgentTerminalReason = (typeof CLOUD_AGENT_TERMINAL_REASONS)[number]; +export { CODE_REVIEW_TERMINAL_REASONS as CLOUD_AGENT_TERMINAL_REASONS }; +export type { CloudAgentTerminalReason }; export class CloudAgentNextError extends Error { readonly procedure: string;