chore: clear low-risk lint warnings

This commit is contained in:
ejclaw
2026-04-29 13:31:11 +09:00
parent 7ffd4c65e1
commit 4dcd4037f1
40 changed files with 36 additions and 161 deletions

View File

@@ -18,9 +18,7 @@ import {
updateScheduledTask, updateScheduledTask,
} from './api'; } from './api';
import { import {
LOCALES,
isLocale, isLocale,
languageNames,
localeTags, localeTags,
matchLocale, matchLocale,
messages, messages,
@@ -206,16 +204,6 @@ const ROOM_BOARD_FORMATTERS = {
statusLabel, statusLabel,
}; };
function queueLabel(
pendingTasks: number,
pendingMessages: boolean,
t: Messages,
) {
const parts = [`${pendingTasks} ${t.units.task}`];
if (pendingMessages) parts.push(t.units.messageShort);
return parts.join(' · ');
}
function buildRoomOptions(snapshots: StatusSnapshot[]): RoomOption[] { function buildRoomOptions(snapshots: StatusSnapshot[]): RoomOption[] {
const rooms = new Map<string, RoomOption>(); const rooms = new Map<string, RoomOption>();
for (const snapshot of snapshots) { for (const snapshot of snapshots) {
@@ -234,33 +222,6 @@ function buildRoomOptions(snapshots: StatusSnapshot[]): RoomOption[] {
); );
} }
function LanguageSelector({
locale,
onLocaleChange,
t,
}: {
locale: Locale;
onLocaleChange: (locale: Locale) => void;
t: Messages;
}) {
return (
<label className="language-select">
<span>{t.language.label}</span>
<select
aria-label={t.language.label}
onChange={(event) => onLocaleChange(event.target.value as Locale)}
value={locale}
>
{LOCALES.map((item) => (
<option key={item} value={item}>
{languageNames[item]}
</option>
))}
</select>
</label>
);
}
function LoadingSkeleton({ t }: { t: Messages }) { function LoadingSkeleton({ t }: { t: Messages }) {
return ( return (
<main className="shell shell-loading" aria-busy="true"> <main className="shell shell-loading" aria-busy="true">

View File

@@ -46,7 +46,6 @@ import {
extractAssistantText, extractAssistantText,
normalizeStructuredOutput, normalizeStructuredOutput,
readStdin, readStdin,
type RunnerOutput,
writeOutput, writeOutput,
} from './output-protocol.js'; } from './output-protocol.js';
import { import {
@@ -409,7 +408,6 @@ async function runQuery(
(message as { subtype?: string }).subtype === 'task_progress' (message as { subtype?: string }).subtype === 'task_progress'
) { ) {
const tp = message as Record<string, unknown>; const tp = message as Record<string, unknown>;
const summary = typeof tp.summary === 'string' ? tp.summary : '';
const description = const description =
typeof tp.description === 'string' ? tp.description : ''; typeof tp.description === 'string' ? tp.description : '';
const mapped = buildTaskProgressOutput( const mapped = buildTaskProgressOutput(

View File

@@ -488,7 +488,7 @@ server.tool(
), ),
}, },
async (args) => { async (args) => {
let snapshotId = ''; let snapshotId: string;
try { try {
snapshotId = computeVerificationSnapshotId(REPO_ROOT); snapshotId = computeVerificationSnapshotId(REPO_ROOT);
} catch (error) { } catch (error) {

View File

@@ -231,7 +231,7 @@ export function assertReadonlyWorkspaceRepoConnectivity(
return; return;
} }
let originUrl = ''; let originUrl: string;
try { try {
originUrl = readGitOutput( originUrl = readGitOutput(
['config', '--get', 'remote.origin.url'], ['config', '--get', 'remote.origin.url'],

View File

@@ -81,7 +81,6 @@ async function measure(page: Page, sel: string) {
async function evalExpr(page: Page, expr: string) { async function evalExpr(page: Page, expr: string) {
const result = await page.evaluate((e) => { const result = await page.evaluate((e) => {
// eslint-disable-next-line no-eval
return eval(e); return eval(e);
}, expr); }, expr);
console.log(JSON.stringify(result, null, 2)); console.log(JSON.stringify(result, null, 2));

View File

@@ -155,7 +155,7 @@ function getStoredRoomRoleOverrideRows(
agent_config_json: string | null; agent_config_json: string | null;
created_at: string; created_at: string;
updated_at: string; updated_at: string;
}> = []; }>;
try { try {
rows = database rows = database
.prepare( .prepare(

View File

@@ -191,7 +191,7 @@ export function ensureLinuxReadonlySandboxAppArmorSupport(options?: {
const sysctlContents = const sysctlContents =
'# Managed by EJClaw setup to allow bubblewrap readonly sandboxing.\n' + '# Managed by EJClaw setup to allow bubblewrap readonly sandboxing.\n' +
'kernel.apparmor_restrict_unprivileged_userns=0\n'; 'kernel.apparmor_restrict_unprivileged_userns=0\n';
let existingContents: string | null = null; let existingContents: string | null;
try { try {
existingContents = readFileSyncFn(sysctlPath, 'utf-8'); existingContents = readFileSyncFn(sysctlPath, 'utf-8');

View File

@@ -15,7 +15,6 @@ import {
ensureLinuxReadonlySandboxAppArmorSupport, ensureLinuxReadonlySandboxAppArmorSupport,
getPlatform, getPlatform,
getNodePath, getNodePath,
getServiceManager,
} from './platform.js'; } from './platform.js';
import { getServiceDefs } from './service-defs.js'; import { getServiceDefs } from './service-defs.js';
import { setupLaunchd, setupLinux } from './service-installers.js'; import { setupLaunchd, setupLinux } from './service-installers.js';
@@ -30,7 +29,6 @@ export async function run(_args: string[]): Promise<void> {
const platform = getPlatform(); const platform = getPlatform();
const nodePath = getNodePath(); const nodePath = getNodePath();
const homeDir = os.homedir(); const homeDir = os.homedir();
const serviceManager = getServiceManager();
logger.info({ platform, nodePath, projectRoot }, 'Setting up service'); logger.info({ platform, nodePath, projectRoot }, 'Setting up service');

View File

@@ -22,7 +22,7 @@ vi.mock('./config.js', () => ({
vi.mock('./env.js', () => ({ vi.mock('./env.js', () => ({
readEnvFile: mockReadEnvFile, readEnvFile: mockReadEnvFile,
getEnv: vi.fn((key: string) => undefined), getEnv: vi.fn((_key: string) => undefined),
})); }));
vi.mock('./codex-token-rotation.js', () => ({ vi.mock('./codex-token-rotation.js', () => ({

View File

@@ -487,9 +487,6 @@ export function prepareGroupEnvironment(
const ownerCommonPairedRoomPrompt = isPairedRoom const ownerCommonPairedRoomPrompt = isPairedRoom
? readOptionalPromptFile(projectRoot, 'owner-common-paired-room.md') ? readOptionalPromptFile(projectRoot, 'owner-common-paired-room.md')
: undefined; : undefined;
const claudePairedRoomPrompt = isPairedRoom
? readPairedRoomPrompt('claude-code', projectRoot)
: undefined;
const globalClaudeMemory = const globalClaudeMemory =
!isMain && fs.existsSync(globalClaudeMdPath) !isMain && fs.existsSync(globalClaudeMdPath)
? fs.readFileSync(globalClaudeMdPath, 'utf-8').trim() ? fs.readFileSync(globalClaudeMdPath, 'utf-8').trim()

View File

@@ -13,14 +13,13 @@ import {
prepareGroupEnvironment, prepareGroupEnvironment,
} from './agent-runner-environment.js'; } from './agent-runner-environment.js';
import { runSpawnedAgentProcess } from './agent-runner-process.js'; import { runSpawnedAgentProcess } from './agent-runner-process.js';
import { getEnv } from './env.js';
export { export {
type AvailableGroup, type AvailableGroup,
writeGroupsSnapshot, writeGroupsSnapshot,
writeTasksSnapshot, writeTasksSnapshot,
} from './agent-runner-snapshot.js'; } from './agent-runner-snapshot.js';
import { logger } from './logger.js'; import { logger } from './logger.js';
import { AgentType, RegisteredGroup, RoomRoleContext } from './types.js'; import { RegisteredGroup, RoomRoleContext } from './types.js';
export interface AgentInput { export interface AgentInput {
prompt: string; prompt: string;

View File

@@ -125,8 +125,6 @@ vi.mock('discord.js', () => {
}); });
import { DiscordChannel, DiscordChannelOpts } from './discord.js'; import { DiscordChannel, DiscordChannelOpts } from './discord.js';
import { registerChannel } from './registry.js';
import { getEnv } from '../env.js';
import { logger } from '../logger.js'; import { logger } from '../logger.js';
// --- Test helpers --- // --- Test helpers ---
@@ -787,7 +785,6 @@ describe('DiscordChannel', () => {
await channel.sendMessage('dc:1234567890123456', 'Hello'); await channel.sendMessage('dc:1234567890123456', 'Hello');
const fetchedChannel =
await currentClient().channels.fetch('1234567890123456'); await currentClient().channels.fetch('1234567890123456');
expect(currentClient().channels.fetch).toHaveBeenCalledWith( expect(currentClient().channels.fetch).toHaveBeenCalledWith(
'1234567890123456', '1234567890123456',

View File

@@ -11,12 +11,7 @@ import {
TextChannel, TextChannel,
} from 'discord.js'; } from 'discord.js';
import { import { CACHE_DIR, DATA_DIR } from '../config.js';
ASSISTANT_NAME,
CACHE_DIR,
DATA_DIR,
TRIGGER_PATTERN,
} from '../config.js';
import { getEnv } from '../env.js'; import { getEnv } from '../env.js';
import { logger } from '../logger.js'; import { logger } from '../logger.js';
import { validateOutboundAttachments } from '../outbound-attachments.js'; import { validateOutboundAttachments } from '../outbound-attachments.js';
@@ -449,7 +444,7 @@ export class DiscordChannel implements Channel {
} }
let cleaned = outbound.cleanText let cleaned = outbound.cleanText
.replace(/^[ \t]*[•\-\*][ \t]*$/gm, '') // remove empty bullet lines .replace(/^[ \t]*[•*-][ \t]*$/gm, '') // remove empty bullet lines
.replace(/\n{3,}/g, '\n\n') // collapse excessive blank lines .replace(/\n{3,}/g, '\n\n') // collapse excessive blank lines
.trim(); .trim();

View File

@@ -1,4 +1,4 @@
import { describe, it, expect, beforeEach } from 'vitest'; import { describe, it, expect } from 'vitest';
import { import {
registerChannel, registerChannel,

View File

@@ -179,13 +179,9 @@ export function applyCodexUsageToAccount(
// Select the effective bucket // Select the effective bucket
const primaryBucket = usage.find((l) => l.limitId === 'codex'); const primaryBucket = usage.find((l) => l.limitId === 'codex');
let effective: CodexRateLimit | null = null; const effective = primaryBucket ?? (usage.length === 1 ? usage[0] : null);
if (primaryBucket) { if (!effective) {
effective = primaryBucket;
} else if (usage.length === 1) {
effective = usage[0];
} else {
// Multiple unknown buckets — cannot determine which is authoritative // Multiple unknown buckets — cannot determine which is authoritative
logger.warn( logger.warn(
{ account: accountIndex + 1 }, { account: accountIndex + 1 },

View File

@@ -31,7 +31,6 @@ import {
getEffectiveRuntimeRoomMode, getEffectiveRuntimeRoomMode,
getExplicitRoomMode, getExplicitRoomMode,
getLatestMessageSeqAtOrBefore, getLatestMessageSeqAtOrBefore,
getLatestPairedTaskForChat,
getLatestTurnNumber, getLatestTurnNumber,
getLastRespondingAgentType, getLastRespondingAgentType,
getRegisteredGroup, getRegisteredGroup,
@@ -199,7 +198,7 @@ function getStoredRoleOverridesForLegacyMigration(
agent_config_json: string | null; agent_config_json: string | null;
created_at: string; created_at: string;
updated_at: string; updated_at: string;
}> = []; }>;
try { try {
rows = database rows = database
.prepare( .prepare(

View File

@@ -20,7 +20,7 @@ interface RequiredRoleMetadataInput {
fallbackAgentType?: AgentType | null; fallbackAgentType?: AgentType | null;
} }
interface OptionalRoleMetadataInput extends RequiredRoleMetadataInput {} type OptionalRoleMetadataInput = RequiredRoleMetadataInput;
function resolveFilledRequiredAgentType( function resolveFilledRequiredAgentType(
input: RequiredRoleMetadataInput, input: RequiredRoleMetadataInput,

View File

@@ -20,7 +20,6 @@ import {
import { import {
AgentType, AgentType,
PairedProject, PairedProject,
PairedRoomRole,
PairedTask, PairedTask,
PairedTaskStatus, PairedTaskStatus,
PairedTurnReservationIntentKind, PairedTurnReservationIntentKind,

View File

@@ -1,7 +1,7 @@
import { Database } from 'bun:sqlite'; import { Database } from 'bun:sqlite';
import { buildPairedTurnAttemptId } from './paired-turn-attempts.js'; import { buildPairedTurnAttemptId } from './paired-turn-attempts.js';
import { tableHasColumn, tryExecMigration } from './migrations/helpers.js'; import { tableHasColumn } from './migrations/helpers.js';
// Paired-turn provenance rebuild helpers extracted from the legacy schema // Paired-turn provenance rebuild helpers extracted from the legacy schema
// bundle. These remain runtime helpers because v10 replays them during // bundle. These remain runtime helpers because v10 replays them during

View File

@@ -115,7 +115,7 @@ function getStoredRoomRoleOverrideRows(
agent_config_json: string | null; agent_config_json: string | null;
created_at: string; created_at: string;
updated_at: string; updated_at: string;
}> = []; }>;
try { try {
rows = database rows = database
.prepare( .prepare(

View File

@@ -1,4 +1,4 @@
import { describe, it, expect, beforeEach, vi } from 'vitest'; import { describe, it, expect, beforeEach } from 'vitest';
import { import {
_setRegisteredGroupForTests, _setRegisteredGroupForTests,

View File

@@ -190,7 +190,7 @@ export async function checkGitHubActionsRun(
}; };
} }
let failedJobs: string[] = []; let failedJobs: string[];
try { try {
failedJobs = await fetchFailedJobs(metadata); failedJobs = await fetchFailedJobs(metadata);
} catch { } catch {

View File

@@ -46,7 +46,7 @@ describe('GroupQueue', () => {
let concurrentCount = 0; let concurrentCount = 0;
let maxConcurrent = 0; let maxConcurrent = 0;
const processMessages = vi.fn(async (groupJid: string) => { const processMessages = vi.fn(async (_groupJid: string) => {
concurrentCount++; concurrentCount++;
maxConcurrent = Math.max(maxConcurrent, concurrentCount); maxConcurrent = Math.max(maxConcurrent, concurrentCount);
// Simulate async work // Simulate async work
@@ -282,7 +282,7 @@ describe('GroupQueue', () => {
let maxActive = 0; let maxActive = 0;
const completionCallbacks: Array<() => void> = []; const completionCallbacks: Array<() => void> = [];
const processMessages = vi.fn(async (groupJid: string) => { const processMessages = vi.fn(async (_groupJid: string) => {
activeCount++; activeCount++;
maxActive = Math.max(maxActive, activeCount); maxActive = Math.max(maxActive, activeCount);
await new Promise<void>((resolve) => completionCallbacks.push(resolve)); await new Promise<void>((resolve) => completionCallbacks.push(resolve));
@@ -360,7 +360,7 @@ describe('GroupQueue', () => {
const executionOrder: string[] = []; const executionOrder: string[] = [];
let resolveFirst: () => void; let resolveFirst: () => void;
const processMessages = vi.fn(async (groupJid: string) => { const processMessages = vi.fn(async (_groupJid: string) => {
if (executionOrder.length === 0) { if (executionOrder.length === 0) {
// First call: block until we release it // First call: block until we release it
await new Promise<void>((resolve) => { await new Promise<void>((resolve) => {

View File

@@ -1,10 +1,8 @@
import { import {
ASSISTANT_NAME, ASSISTANT_NAME,
DATA_DIR,
IDLE_TIMEOUT, IDLE_TIMEOUT,
POLL_INTERVAL, POLL_INTERVAL,
SERVICE_ID, SERVICE_ID,
isSessionCommandSenderAllowed,
STATUS_CHANNEL_ID, STATUS_CHANNEL_ID,
STATUS_UPDATE_INTERVAL, STATUS_UPDATE_INTERVAL,
TIMEZONE, TIMEZONE,
@@ -19,14 +17,11 @@ import {
} from './channels/registry.js'; } from './channels/registry.js';
import { writeGroupsSnapshot } from './agent-runner.js'; import { writeGroupsSnapshot } from './agent-runner.js';
import { import {
type AssignRoomInput,
getAllTasks,
hasRecentRestartAnnouncement, hasRecentRestartAnnouncement,
initDatabase, initDatabase,
storeChatMetadata, storeChatMetadata,
storeMessage, storeMessage,
} from './db.js'; } from './db.js';
import { composeDashboardContent } from './dashboard-render.js';
import { GroupQueue } from './group-queue.js'; import { GroupQueue } from './group-queue.js';
import { resolveGroupIpcPath } from './group-folder.js'; import { resolveGroupIpcPath } from './group-folder.js';
import { startIpcWatcher } from './ipc.js'; import { startIpcWatcher } from './ipc.js';
@@ -34,11 +29,7 @@ import {
deliverCanonicalOutboundMessage, deliverCanonicalOutboundMessage,
deliverIpcOutboundMessage, deliverIpcOutboundMessage,
} from './ipc-outbound-delivery.js'; } from './ipc-outbound-delivery.js';
import { import { findChannel, formatOutbound } from './router.js';
findChannel,
formatOutbound,
normalizeMessageForDedupe,
} from './router.js';
import { import {
buildRestartAnnouncement, buildRestartAnnouncement,
buildInterruptedRestartAnnouncement, buildInterruptedRestartAnnouncement,
@@ -50,7 +41,6 @@ import {
} from './restart-context.js'; } from './restart-context.js';
import { import {
isSenderAllowed, isSenderAllowed,
isTriggerAllowed,
loadSenderAllowlist, loadSenderAllowlist,
shouldDropMessage, shouldDropMessage,
} from './sender-allowlist.js'; } from './sender-allowlist.js';

View File

@@ -1,7 +1,7 @@
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import { DATA_DIR, IPC_POLL_INTERVAL, TIMEZONE } from './config.js'; import { DATA_DIR, IPC_POLL_INTERVAL } from './config.js';
import { readJsonFile } from './utils.js'; import { readJsonFile } from './utils.js';
import { logger } from './logger.js'; import { logger } from './logger.js';
import { import {

View File

@@ -1,4 +1,3 @@
import { logger } from './logger.js';
import { import {
handleSessionCommand, handleSessionCommand,
type SessionCommandDeps, type SessionCommandDeps,

View File

@@ -11,7 +11,6 @@ import {
} from './config.js'; } from './config.js';
import { GroupQueue, GroupRunContext } from './group-queue.js'; import { GroupQueue, GroupRunContext } from './group-queue.js';
import { findChannel, formatMessages } from './router.js'; import { findChannel, formatMessages } from './router.js';
import { isTriggerAllowed, loadSenderAllowlist } from './sender-allowlist.js';
import { enqueueGenericFollowUpAfterDeliveryRetry as enqueueDeliveryRetryFollowUp } from './message-runtime-dispatch.js'; import { enqueueGenericFollowUpAfterDeliveryRetry as enqueueDeliveryRetryFollowUp } from './message-runtime-dispatch.js';
import { processOpenWorkItemDelivery } from './message-runtime-delivery.js'; import { processOpenWorkItemDelivery } from './message-runtime-delivery.js';
import { deliverCanonicalOutboundMessage } from './ipc-outbound-delivery.js'; import { deliverCanonicalOutboundMessage } from './ipc-outbound-delivery.js';
@@ -340,7 +339,6 @@ export function createMessageRuntime(deps: MessageRuntimeDeps): {
return true; return true;
} }
const isMainGroup = group.isMain === true;
while (true) { while (true) {
const sinceSeqCursor = deps.getLastAgentTimestamps()[chatJid] || '0'; const sinceSeqCursor = deps.getLastAgentTimestamps()[chatJid] || '0';
const rawMissedMessages = getMessagesSinceSeq( const rawMissedMessages = getMessagesSinceSeq(

View File

@@ -15,10 +15,7 @@ import {
transitionPairedTaskStatus, transitionPairedTaskStatus,
} from './paired-task-status.js'; } from './paired-task-status.js';
import { resolveOwnerCompletionSignal } from './paired-completion-signals.js'; import { resolveOwnerCompletionSignal } from './paired-completion-signals.js';
import { import { hasCodeChangesSinceRef } from './paired-source-ref.js';
hasCodeChangesSinceRef,
resolveCanonicalSourceRef,
} from './paired-source-ref.js';
import { parseVisibleVerdict } from './paired-verdict.js'; import { parseVisibleVerdict } from './paired-verdict.js';
import type { PairedTask } from './types.js'; import type { PairedTask } from './types.js';

View File

@@ -133,7 +133,7 @@ export function handleReviewerCompletion(args: {
return; return;
} }
case 'request_arbiter': case 'request_arbiter': {
const arbiterLogMessage = const arbiterLogMessage =
verdict === 'blocked' || verdict === 'needs_context' verdict === 'blocked' || verdict === 'needs_context'
? 'Reviewer blocked/needs_context — requesting arbiter before escalating' ? 'Reviewer blocked/needs_context — requesting arbiter before escalating'
@@ -152,6 +152,7 @@ export function handleReviewerCompletion(args: {
logContext: { taskId, verdict, summary: summary?.slice(0, 100) }, logContext: { taskId, verdict, summary: summary?.slice(0, 100) },
}); });
return; return;
}
case 'request_owner_changes': case 'request_owner_changes':
transitionPairedTaskStatus({ transitionPairedTaskStatus({

View File

@@ -8,14 +8,12 @@ import {
} from 'ejclaw-runners-shared'; } from 'ejclaw-runners-shared';
import { import {
ARBITER_DEADLOCK_THRESHOLD,
ARBITER_AGENT_TYPE, ARBITER_AGENT_TYPE,
CLAUDE_SERVICE_ID, CLAUDE_SERVICE_ID,
CODEX_MAIN_SERVICE_ID, CODEX_MAIN_SERVICE_ID,
CODEX_REVIEW_SERVICE_ID, CODEX_REVIEW_SERVICE_ID,
DATA_DIR, DATA_DIR,
PAIRED_CARRY_FORWARD_LATEST_OWNER_FINAL, PAIRED_CARRY_FORWARD_LATEST_OWNER_FINAL,
PAIRED_MAX_ROUND_TRIPS,
REVIEWER_AGENT_TYPE, REVIEWER_AGENT_TYPE,
} from './config.js'; } from './config.js';
import { import {
@@ -26,8 +24,6 @@ import {
getPairedTaskById, getPairedTaskById,
getPairedTurnById, getPairedTurnById,
getPairedTurnOutputs, getPairedTurnOutputs,
getPairedWorkspace,
hasActiveCiWatcherForChat,
insertPairedTurnOutput, insertPairedTurnOutput,
releasePairedTaskExecutionLease, releasePairedTaskExecutionLease,
updatePairedTask, updatePairedTask,
@@ -50,11 +46,9 @@ import {
applyPairedTaskPatch, applyPairedTaskPatch,
transitionPairedTaskStatus, transitionPairedTaskStatus,
} from './paired-task-status.js'; } from './paired-task-status.js';
import { requestArbiterOrEscalate } from './paired-arbiter-request.js';
import { resolveCanonicalSourceRef } from './paired-source-ref.js'; import { resolveCanonicalSourceRef } from './paired-source-ref.js';
import { import {
isOwnerWorkspaceRepairNeededError, isOwnerWorkspaceRepairNeededError,
markPairedTaskReviewReady,
prepareReviewerWorkspaceForExecution, prepareReviewerWorkspaceForExecution,
provisionOwnerWorkspaceForPairedTask, provisionOwnerWorkspaceForPairedTask,
} from './paired-workspace-manager.js'; } from './paired-workspace-manager.js';

View File

@@ -16,11 +16,8 @@ import { transitionPairedTaskStatus } from './paired-task-status.js';
import type { PairedTask, PairedWorkspace } from './types.js'; import type { PairedTask, PairedWorkspace } from './types.js';
import { ensureWorkspaceDependenciesInstalled } from './workspace-package-manager.js'; import { ensureWorkspaceDependenciesInstalled } from './workspace-package-manager.js';
const REVIEWER_SNAPSHOT_STALE_BLOCK_MESSAGE =
'Review workspace is out of date after owner changes. Retry the review once to resync against the latest owner workspace.';
const REVIEWER_SNAPSHOT_NOT_READY_BLOCK_MESSAGE = const REVIEWER_SNAPSHOT_NOT_READY_BLOCK_MESSAGE =
'Review workspace is not ready yet. Wait for the owner to complete a turn so the reviewer workspace can be prepared.'; 'Review workspace is not ready yet. Wait for the owner to complete a turn so the reviewer workspace can be prepared.';
const OWNER_WORKSPACE_REPAIR_PREFIX = 'BLOCKED\nOwner workspace needs repair.';
const REVIEWER_SNAPSHOT_DENY_SEGMENTS = new Set([ const REVIEWER_SNAPSHOT_DENY_SEGMENTS = new Set([
'.git', '.git',
'.claude', '.claude',
@@ -139,19 +136,6 @@ function isGitWorktreeClean(repoDir: string): boolean {
return runGit(['status', '--short'], repoDir).length === 0; return runGit(['status', '--short'], repoDir).length === 0;
} }
function buildOwnerWorkspaceRepairBlockMessage(args: {
workspaceDir: string;
currentBranch: string;
targetBranch: string;
reason: string;
}): string {
return `${OWNER_WORKSPACE_REPAIR_PREFIX}
Owner workspace branch mismatch: \`${args.currentBranch}\` -> expected \`${args.targetBranch}\`.
${args.reason}
Workspace: \`${args.workspaceDir}\`
Repair the owner workspace branch, then retry the task.`;
}
function buildOwnerReanchorBackupPrefix(targetBranch: string): string { function buildOwnerReanchorBackupPrefix(targetBranch: string): string {
const groupFolder = targetBranch.startsWith('codex/owner/') const groupFolder = targetBranch.startsWith('codex/owner/')
? targetBranch.slice('codex/owner/'.length) ? targetBranch.slice('codex/owner/'.length)
@@ -286,10 +270,6 @@ function maybeRepairNamedOwnerWorkspaceBranch(args: {
return true; return true;
} }
function ensureCleanDirectory(targetDir: string): void {
fs.mkdirSync(targetDir, { recursive: true });
}
type GitWorktreeEntry = { type GitWorktreeEntry = {
worktreePath: string; worktreePath: string;
head: string | null; head: string | null;

View File

@@ -1,6 +1,6 @@
import { describe, it, expect, beforeEach } from 'vitest'; import { describe, it, expect, beforeEach } from 'vitest';
import { _initTestDatabase, getAllChats, storeChatMetadata } from './db.js'; import { _initTestDatabase, storeChatMetadata } from './db.js';
import { getAvailableGroups, _setRegisteredGroups } from './index.js'; import { getAvailableGroups, _setRegisteredGroups } from './index.js';
beforeEach(() => { beforeEach(() => {

View File

@@ -1,7 +1,7 @@
import fs from 'fs'; import fs from 'fs';
import os from 'os'; import os from 'os';
import path from 'path'; import path from 'path';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { afterEach, beforeEach, describe, expect, it } from 'vitest';
import { import {
isSenderAllowed, isSenderAllowed,

View File

@@ -81,12 +81,6 @@ export interface SessionCommandDeps {
killProcess: () => boolean; killProcess: () => boolean;
} }
function resultToText(result: string | object | null | undefined): string {
if (!result) return '';
const raw = typeof result === 'string' ? result : JSON.stringify(result);
return formatOutbound(raw);
}
function agentResultToText(result: AgentResult): string { function agentResultToText(result: AgentResult): string {
const raw = getAgentOutputText({ const raw = getAgentOutputText({
result: result.result ?? null, result: result.result ?? null,
@@ -126,10 +120,6 @@ export async function handleSessionCommand(opts: {
const command = cmdMsg const command = cmdMsg
? extractSessionCommand(cmdMsg.content, triggerPattern) ? extractSessionCommand(cmdMsg.content, triggerPattern)
: null; : null;
const normalizedCommandText = cmdMsg
? normalizeSessionCommandText(cmdMsg.content, triggerPattern)
: '';
if (!command || !cmdMsg) return { handled: false }; if (!command || !cmdMsg) return { handled: false };
if ( if (

View File

@@ -57,7 +57,6 @@ export interface FastModeSnapshot {
} }
const ROLE_KEYS = ['OWNER', 'REVIEWER', 'ARBITER'] as const; const ROLE_KEYS = ['OWNER', 'REVIEWER', 'ARBITER'] as const;
type RoleKey = (typeof ROLE_KEYS)[number];
function envFilePath(): string { function envFilePath(): string {
return path.join(process.cwd(), '.env'); return path.join(process.cwd(), '.env');
@@ -555,7 +554,7 @@ function readCodexFastMode(): boolean {
if (!fs.existsSync(file)) return false; if (!fs.existsSync(file)) return false;
const content = fs.readFileSync(file, 'utf-8'); const content = fs.readFileSync(file, 'utf-8');
// [features] section, look for fast_mode = true|false // [features] section, look for fast_mode = true|false
const featuresMatch = content.match(/\[features\][\s\S]*?(?=^\[|\Z)/m); const featuresMatch = content.match(/\[features\][\s\S]*?(?=^\[|$)/m);
const block = featuresMatch ? featuresMatch[0] : content; const block = featuresMatch ? featuresMatch[0] : content;
const m = block.match(/^\s*fast_mode\s*=\s*(true|false)\s*$/m); const m = block.match(/^\s*fast_mode\s*=\s*(true|false)\s*$/m);
return m ? m[1] === 'true' : false; return m ? m[1] === 'true' : false;
@@ -663,7 +662,7 @@ export function addClaudeAccountFromToken(token: string): {
if (parts.length < 2) { if (parts.length < 2) {
throw new Error('invalid OAuth token: expected JWT format'); throw new Error('invalid OAuth token: expected JWT format');
} }
let payload: Record<string, unknown> = {}; let payload: Record<string, unknown>;
try { try {
payload = JSON.parse( payload = JSON.parse(
Buffer.from(parts[1], 'base64').toString('utf-8'), Buffer.from(parts[1], 'base64').toString('utf-8'),

View File

@@ -533,11 +533,7 @@ describe('evaluateStreamedOutput', () => {
reason: '429', reason: '429',
}); });
const result = evaluateStreamedOutput( evaluateStreamedOutput(errorOutput('429'), freshState(), claudeOpts);
errorOutput('429'),
freshState(),
claudeOpts,
);
// Claude uses classifyRotationTrigger, not detectCodexRotationTrigger // Claude uses classifyRotationTrigger, not detectCodexRotationTrigger
expect(detectCodexRotationTrigger).not.toHaveBeenCalled(); expect(detectCodexRotationTrigger).not.toHaveBeenCalled();
}); });

View File

@@ -42,11 +42,7 @@ import {
formatSuspensionNotice, formatSuspensionNotice,
suspendTask, suspendTask,
} from './task-suspension.js'; } from './task-suspension.js';
import { import { getTaskQueueJid, isGitHubCiTask } from './task-watch-status.js';
extractWatchCiTarget,
getTaskQueueJid,
isGitHubCiTask,
} from './task-watch-status.js';
import { ScheduledTask } from './types.js'; import { ScheduledTask } from './types.js';
import { import {
hasTaskExceededMaxDuration, hasTaskExceededMaxDuration,
@@ -163,13 +159,12 @@ async function runTask(
); );
let result: string | null = null; let result: string | null = null;
let error: string | null = null; let error: string | null;
const statusTracker = createTaskStatusTracker(task, { const statusTracker = createTaskStatusTracker(task, {
sendTrackedMessage: deps.sendTrackedMessage, sendTrackedMessage: deps.sendTrackedMessage,
editTrackedMessage: deps.editTrackedMessage, editTrackedMessage: deps.editTrackedMessage,
}); });
const isClaudeAgent = context.taskAgentType === 'claude-code'; const isClaudeAgent = context.taskAgentType === 'claude-code';
const canRotateToken = isClaudeAgent && getTokenCount() > 1;
try { try {
await statusTracker.update('checking'); await statusTracker.update('checking');

View File

@@ -10,7 +10,6 @@
* All exhausted: surface error to caller * All exhausted: surface error to caller
*/ */
import fs from 'fs';
import path from 'path'; import path from 'path';
import { DATA_DIR } from './config.js'; import { DATA_DIR } from './config.js';

View File

@@ -17,7 +17,6 @@ import {
getLatestPairedTurnForTask, getLatestPairedTurnForTask,
getRecentDeliveredWorkItemsForChat, getRecentDeliveredWorkItemsForChat,
getRecentChatMessages, getRecentChatMessages,
getRecentChatMessagesBatch,
getTaskById, getTaskById,
hasMessage, hasMessage,
storeChatMetadata, storeChatMetadata,

View File

@@ -68,7 +68,7 @@ async function readJsonObject(
request: Request, request: Request,
jsonResponse: JsonResponse, jsonResponse: JsonResponse,
): Promise<Record<string, unknown> | Response> { ): Promise<Record<string, unknown> | Response> {
let body: unknown = null; let body: unknown;
try { try {
body = await request.json(); body = await request.json();
} catch { } catch {
@@ -141,7 +141,7 @@ async function handleClaudeAccountAddRoute(
): Promise<Response | null> { ): Promise<Response | null> {
if (request.method !== 'POST') return null; if (request.method !== 'POST') return null;
let body: { token?: unknown } | null = null; let body: { token?: unknown };
try { try {
body = (await request.json()) as { token?: unknown }; body = (await request.json()) as { token?: unknown };
} catch { } catch {
@@ -213,7 +213,7 @@ async function handleCodexCurrentRoute(
): Promise<Response | null> { ): Promise<Response | null> {
if (request.method !== 'PUT') return null; if (request.method !== 'PUT') return null;
let body: { index?: unknown } | null = null; let body: { index?: unknown };
try { try {
body = (await request.json()) as { index?: unknown }; body = (await request.json()) as { index?: unknown };
} catch { } catch {