From 7d08205a2350e3ade90b980e168a91a54e188305 Mon Sep 17 00:00:00 2001 From: 777genius Date: Thu, 30 Apr 2026 00:05:58 +0300 Subject: [PATCH] fix(ci): clean member work sync validation --- .../member-work-sync/contracts/index.ts | 2 +- .../member-work-sync/contracts/types.ts | 4 +- .../MemberWorkSyncDiagnosticsReader.ts | 3 +- .../MemberWorkSyncMetricsReader.ts | 3 +- .../MemberWorkSyncNudgeOutboxPlanner.ts | 3 +- ...mberWorkSyncPendingReportIntentReplayer.ts | 3 +- .../application/MemberWorkSyncReconciler.ts | 4 +- .../application/MemberWorkSyncReporter.ts | 20 ++-- .../core/application/index.ts | 4 +- .../core/application/ports.ts | 4 +- .../core/domain/ActionableWorkAgenda.ts | 11 +- .../core/domain/AgendaFingerprint.ts | 4 +- .../domain/MemberWorkSyncReportValidator.ts | 3 +- .../member-work-sync/core/domain/index.ts | 2 +- .../input/registerMemberWorkSyncIpc.ts | 3 +- .../TeamInboxMemberWorkSyncNudgeSink.ts | 1 + .../TeamRuntimeTurnSettledTargetResolver.ts | 22 ++-- .../adapters/output/TeamTaskAgendaSource.ts | 23 ++-- .../TeamTaskStallJournalWorkSyncCooldown.ts | 6 +- .../createMemberWorkSyncFeature.ts | 107 +++++++++--------- src/features/member-work-sync/main/index.ts | 5 +- .../ClaudeStopHookPayloadNormalizer.ts | 1 + ...CodexNativeTurnSettledPayloadNormalizer.ts | 5 +- .../FileRuntimeTurnSettledEventStore.ts | 11 +- .../HmacMemberWorkSyncReportTokenAdapter.ts | 2 +- .../infrastructure/JsonMemberWorkSyncStore.ts | 24 ++-- .../MemberWorkSyncEventQueue.ts | 2 +- .../MemberWorkSyncToolActivityBusySignal.ts | 1 - ...llRuntimeTurnSettledHookScriptInstaller.ts | 3 +- .../renderer/hooks/useMemberWorkSyncStatus.ts | 5 +- .../renderer/ui/MemberWorkSyncBadge.tsx | 17 ++- .../renderer/ui/MemberWorkSyncDetails.tsx | 10 +- .../renderer/ui/MemberWorkSyncStatusPanel.tsx | 9 +- src/main/http/index.ts | 2 +- src/main/index.ts | 18 +-- .../services/team/TaskChangeLedgerReader.ts | 2 +- .../services/team/TeamProvisioningService.ts | 2 +- .../team/members/MemberDetailDialog.tsx | 2 +- src/shared/types/api.ts | 4 +- .../RuntimeTurnSettledHookSettings.test.ts | 6 +- 40 files changed, 194 insertions(+), 169 deletions(-) diff --git a/src/features/member-work-sync/contracts/index.ts b/src/features/member-work-sync/contracts/index.ts index 14aed138..06a75889 100644 --- a/src/features/member-work-sync/contracts/index.ts +++ b/src/features/member-work-sync/contracts/index.ts @@ -1,2 +1,2 @@ export * from './ipc'; -export * from './types'; +export type * from './types'; diff --git a/src/features/member-work-sync/contracts/types.ts b/src/features/member-work-sync/contracts/types.ts index c6daa966..f7ddc2c0 100644 --- a/src/features/member-work-sync/contracts/types.ts +++ b/src/features/member-work-sync/contracts/types.ts @@ -221,11 +221,11 @@ export interface MemberWorkSyncNudgePayload { source: 'member-work-sync'; actionMode: 'do'; text: string; - taskRefs: Array<{ + taskRefs: { taskId: string; displayId: string; teamName: string; - }>; + }[]; } export interface MemberWorkSyncOutboxItem { diff --git a/src/features/member-work-sync/core/application/MemberWorkSyncDiagnosticsReader.ts b/src/features/member-work-sync/core/application/MemberWorkSyncDiagnosticsReader.ts index e907568a..7e70b52f 100644 --- a/src/features/member-work-sync/core/application/MemberWorkSyncDiagnosticsReader.ts +++ b/src/features/member-work-sync/core/application/MemberWorkSyncDiagnosticsReader.ts @@ -1,5 +1,6 @@ -import type { MemberWorkSyncStatus, MemberWorkSyncStatusRequest } from '../../contracts'; import { MemberWorkSyncReconciler } from './MemberWorkSyncReconciler'; + +import type { MemberWorkSyncStatus, MemberWorkSyncStatusRequest } from '../../contracts'; import type { MemberWorkSyncUseCaseDeps } from './ports'; export class MemberWorkSyncDiagnosticsReader { diff --git a/src/features/member-work-sync/core/application/MemberWorkSyncMetricsReader.ts b/src/features/member-work-sync/core/application/MemberWorkSyncMetricsReader.ts index 702cb81a..513a17b0 100644 --- a/src/features/member-work-sync/core/application/MemberWorkSyncMetricsReader.ts +++ b/src/features/member-work-sync/core/application/MemberWorkSyncMetricsReader.ts @@ -1,5 +1,6 @@ -import type { MemberWorkSyncMetricsRequest, MemberWorkSyncTeamMetrics } from '../../contracts'; import { assessMemberWorkSyncPhase2Readiness } from '../domain'; + +import type { MemberWorkSyncMetricsRequest, MemberWorkSyncTeamMetrics } from '../../contracts'; import type { MemberWorkSyncUseCaseDeps } from './ports'; function emptyMetrics(teamName: string, generatedAt: string): MemberWorkSyncTeamMetrics { diff --git a/src/features/member-work-sync/core/application/MemberWorkSyncNudgeOutboxPlanner.ts b/src/features/member-work-sync/core/application/MemberWorkSyncNudgeOutboxPlanner.ts index 8281a87a..a042d0bf 100644 --- a/src/features/member-work-sync/core/application/MemberWorkSyncNudgeOutboxPlanner.ts +++ b/src/features/member-work-sync/core/application/MemberWorkSyncNudgeOutboxPlanner.ts @@ -1,5 +1,6 @@ -import type { MemberWorkSyncStatus } from '../../contracts'; import { buildMemberWorkSyncOutboxEnsureInput } from '../domain'; + +import type { MemberWorkSyncStatus } from '../../contracts'; import type { MemberWorkSyncUseCaseDeps } from './ports'; export interface MemberWorkSyncNudgeOutboxPlanResult { diff --git a/src/features/member-work-sync/core/application/MemberWorkSyncPendingReportIntentReplayer.ts b/src/features/member-work-sync/core/application/MemberWorkSyncPendingReportIntentReplayer.ts index bf6ae37c..8c6bce96 100644 --- a/src/features/member-work-sync/core/application/MemberWorkSyncPendingReportIntentReplayer.ts +++ b/src/features/member-work-sync/core/application/MemberWorkSyncPendingReportIntentReplayer.ts @@ -1,5 +1,6 @@ -import type { MemberWorkSyncReportIntentStatus } from '../../contracts'; import { MemberWorkSyncReporter } from './MemberWorkSyncReporter'; + +import type { MemberWorkSyncReportIntentStatus } from '../../contracts'; import type { MemberWorkSyncUseCaseDeps } from './ports'; export interface MemberWorkSyncPendingReportReplaySummary { diff --git a/src/features/member-work-sync/core/application/MemberWorkSyncReconciler.ts b/src/features/member-work-sync/core/application/MemberWorkSyncReconciler.ts index 3ff508a1..3043f90b 100644 --- a/src/features/member-work-sync/core/application/MemberWorkSyncReconciler.ts +++ b/src/features/member-work-sync/core/application/MemberWorkSyncReconciler.ts @@ -4,9 +4,11 @@ import { decideMemberWorkSyncStatus, formatAgendaFingerprint, } from '../domain'; + +import { MemberWorkSyncNudgeOutboxPlanner } from './MemberWorkSyncNudgeOutboxPlanner'; + import type { MemberWorkSyncStatus, MemberWorkSyncStatusRequest } from '../../contracts'; import type { MemberWorkSyncAgendaSourceResult, MemberWorkSyncUseCaseDeps } from './ports'; -import { MemberWorkSyncNudgeOutboxPlanner } from './MemberWorkSyncNudgeOutboxPlanner'; export interface MemberWorkSyncReconcileContext { reconciledBy?: 'request' | 'queue'; diff --git a/src/features/member-work-sync/core/application/MemberWorkSyncReporter.ts b/src/features/member-work-sync/core/application/MemberWorkSyncReporter.ts index de2bd018..2076adf4 100644 --- a/src/features/member-work-sync/core/application/MemberWorkSyncReporter.ts +++ b/src/features/member-work-sync/core/application/MemberWorkSyncReporter.ts @@ -1,15 +1,17 @@ +import { validateMemberWorkSyncReport } from '../domain'; + +import { + attachMemberWorkSyncReportToken, + finalizeMemberWorkSyncAgenda, + MemberWorkSyncReconciler, +} from './MemberWorkSyncReconciler'; + import type { MemberWorkSyncReport, MemberWorkSyncReportRequest, MemberWorkSyncReportResult, MemberWorkSyncStatus, } from '../../contracts'; -import { validateMemberWorkSyncReport } from '../domain'; -import { - attachMemberWorkSyncReportToken, - finalizeMemberWorkSyncAgenda, - MemberWorkSyncReconciler, -} from './MemberWorkSyncReconciler'; import type { MemberWorkSyncUseCaseDeps } from './ports'; export class MemberWorkSyncReporter { @@ -28,7 +30,11 @@ export class MemberWorkSyncReporter { : true; if (!teamActive) { const status = await this.reconciler.execute(request); - const rejectedStatus = await this.recordRejectedReport(status, request, 'team_runtime_inactive'); + const rejectedStatus = await this.recordRejectedReport( + status, + request, + 'team_runtime_inactive' + ); return { accepted: false, code: 'team_runtime_inactive', diff --git a/src/features/member-work-sync/core/application/index.ts b/src/features/member-work-sync/core/application/index.ts index 585e60eb..74021af2 100644 --- a/src/features/member-work-sync/core/application/index.ts +++ b/src/features/member-work-sync/core/application/index.ts @@ -5,6 +5,6 @@ export * from './MemberWorkSyncNudgeOutboxPlanner'; export * from './MemberWorkSyncPendingReportIntentReplayer'; export * from './MemberWorkSyncReconciler'; export * from './MemberWorkSyncReporter'; -export * from './ports'; +export type * from './ports'; export * from './RuntimeTurnSettledIngestor'; -export * from './RuntimeTurnSettledPorts'; +export type * from './RuntimeTurnSettledPorts'; diff --git a/src/features/member-work-sync/core/application/ports.ts b/src/features/member-work-sync/core/application/ports.ts index 8cb0eeeb..4ac83fec 100644 --- a/src/features/member-work-sync/core/application/ports.ts +++ b/src/features/member-work-sync/core/application/ports.ts @@ -1,7 +1,5 @@ import type { MemberWorkSyncAgenda, - MemberWorkSyncTeamMetrics, - MemberWorkSyncProviderId, MemberWorkSyncOutboxClaimInput, MemberWorkSyncOutboxCountRecentDeliveredInput, MemberWorkSyncOutboxEnsureInput, @@ -10,11 +8,13 @@ import type { MemberWorkSyncOutboxMarkDeliveredInput, MemberWorkSyncOutboxMarkFailedInput, MemberWorkSyncOutboxMarkSupersededInput, + MemberWorkSyncProviderId, MemberWorkSyncReport, MemberWorkSyncReportIntent, MemberWorkSyncReportIntentStatus, MemberWorkSyncReportRequest, MemberWorkSyncStatus, + MemberWorkSyncTeamMetrics, } from '../../contracts'; export interface MemberWorkSyncClockPort { diff --git a/src/features/member-work-sync/core/domain/ActionableWorkAgenda.ts b/src/features/member-work-sync/core/domain/ActionableWorkAgenda.ts index 4904f6d7..c29a018c 100644 --- a/src/features/member-work-sync/core/domain/ActionableWorkAgenda.ts +++ b/src/features/member-work-sync/core/domain/ActionableWorkAgenda.ts @@ -1,8 +1,3 @@ -import type { - MemberWorkSyncActionableWorkItem, - MemberWorkSyncAgenda, - MemberWorkSyncProviderId, -} from '../../contracts'; import { buildAgendaFingerprintPayload, canonicalizeAgendaFingerprintPayload, @@ -11,6 +6,12 @@ import { import { resolveCurrentReviewOwner, type ReviewHistoryEventLike } from './currentReviewCycle'; import { isReservedMemberName, normalizeMemberName, sameMemberName } from './memberName'; +import type { + MemberWorkSyncActionableWorkItem, + MemberWorkSyncAgenda, + MemberWorkSyncProviderId, +} from '../../contracts'; + export interface MemberWorkSyncTaskLike { id: string; displayId?: string; diff --git a/src/features/member-work-sync/core/domain/AgendaFingerprint.ts b/src/features/member-work-sync/core/domain/AgendaFingerprint.ts index 736aa636..8a66a7bd 100644 --- a/src/features/member-work-sync/core/domain/AgendaFingerprint.ts +++ b/src/features/member-work-sync/core/domain/AgendaFingerprint.ts @@ -19,7 +19,7 @@ export interface AgendaFingerprintPayload { version: 1; teamName: string; memberName: string; - items: Array<{ + items: { taskId: string; displayId?: string; subject: string; @@ -27,7 +27,7 @@ export interface AgendaFingerprintPayload { assignee: string; priority: string; evidence: MemberWorkSyncActionableWorkItem['evidence']; - }>; + }[]; sourceRevision?: string; } diff --git a/src/features/member-work-sync/core/domain/MemberWorkSyncReportValidator.ts b/src/features/member-work-sync/core/domain/MemberWorkSyncReportValidator.ts index 29b34c2a..9aa26760 100644 --- a/src/features/member-work-sync/core/domain/MemberWorkSyncReportValidator.ts +++ b/src/features/member-work-sync/core/domain/MemberWorkSyncReportValidator.ts @@ -1,9 +1,10 @@ +import { isReservedMemberName, normalizeMemberName, sameMemberName } from './memberName'; + import type { MemberWorkSyncAgenda, MemberWorkSyncReportRequest, MemberWorkSyncReportState, } from '../../contracts'; -import { isReservedMemberName, normalizeMemberName, sameMemberName } from './memberName'; export interface MemberWorkSyncReportValidation { ok: boolean; diff --git a/src/features/member-work-sync/core/domain/index.ts b/src/features/member-work-sync/core/domain/index.ts index 4495aaef..4ac73ffa 100644 --- a/src/features/member-work-sync/core/domain/index.ts +++ b/src/features/member-work-sync/core/domain/index.ts @@ -2,8 +2,8 @@ export * from './ActionableWorkAgenda'; export * from './AgendaFingerprint'; export * from './currentReviewCycle'; export * from './memberName'; -export * from './MemberWorkSyncPhase2Readiness'; export * from './MemberWorkSyncNudge'; +export * from './MemberWorkSyncPhase2Readiness'; export * from './MemberWorkSyncReportValidator'; export * from './RuntimeTurnSettledEvent'; export * from './RuntimeTurnSettledProvider'; diff --git a/src/features/member-work-sync/main/adapters/input/registerMemberWorkSyncIpc.ts b/src/features/member-work-sync/main/adapters/input/registerMemberWorkSyncIpc.ts index 821f1ee2..57b9463f 100644 --- a/src/features/member-work-sync/main/adapters/input/registerMemberWorkSyncIpc.ts +++ b/src/features/member-work-sync/main/adapters/input/registerMemberWorkSyncIpc.ts @@ -1,3 +1,5 @@ +import { createLogger } from '@shared/utils/logger'; + import { MEMBER_WORK_SYNC_GET_METRICS, MEMBER_WORK_SYNC_GET_STATUS, @@ -9,7 +11,6 @@ import { type MemberWorkSyncStatusRequest, type MemberWorkSyncTeamMetrics, } from '../../../contracts'; -import { createLogger } from '@shared/utils/logger'; import type { MemberWorkSyncFeatureFacade } from '../../composition/createMemberWorkSyncFeature'; import type { IpcMain } from 'electron'; diff --git a/src/features/member-work-sync/main/adapters/output/TeamInboxMemberWorkSyncNudgeSink.ts b/src/features/member-work-sync/main/adapters/output/TeamInboxMemberWorkSyncNudgeSink.ts index fc2e9778..15cd418d 100644 --- a/src/features/member-work-sync/main/adapters/output/TeamInboxMemberWorkSyncNudgeSink.ts +++ b/src/features/member-work-sync/main/adapters/output/TeamInboxMemberWorkSyncNudgeSink.ts @@ -1,5 +1,6 @@ import { TeamInboxReader } from '@main/services/team/TeamInboxReader'; import { TeamInboxWriter } from '@main/services/team/TeamInboxWriter'; + import type { MemberWorkSyncInboxNudgePort } from '../../../core/application'; export class TeamInboxMemberWorkSyncNudgeSink implements MemberWorkSyncInboxNudgePort { diff --git a/src/features/member-work-sync/main/adapters/output/TeamRuntimeTurnSettledTargetResolver.ts b/src/features/member-work-sync/main/adapters/output/TeamRuntimeTurnSettledTargetResolver.ts index 1cd69e24..0358ef8c 100644 --- a/src/features/member-work-sync/main/adapters/output/TeamRuntimeTurnSettledTargetResolver.ts +++ b/src/features/member-work-sync/main/adapters/output/TeamRuntimeTurnSettledTargetResolver.ts @@ -1,16 +1,16 @@ -import path from 'path'; - -import { isReservedMemberName, normalizeMemberName } from '../../../core/domain'; -import type { - RuntimeTurnSettledTargetResolution, - RuntimeTurnSettledTargetResolverPort, -} from '../../../core/application'; import { TeamMemberLogsFinder } from '@main/services/team/TeamMemberLogsFinder'; import { inferTeamProviderIdFromModel, normalizeOptionalTeamProviderId, } from '@shared/utils/teamProvider'; +import path from 'path'; +import { isReservedMemberName, normalizeMemberName } from '../../../core/domain'; + +import type { + RuntimeTurnSettledTargetResolution, + RuntimeTurnSettledTargetResolverPort, +} from '../../../core/application'; import type { RuntimeTurnSettledEvent } from '../../../core/domain'; import type { TeamConfigReader } from '@main/services/team/TeamConfigReader'; import type { TeamMembersMetaStore } from '@main/services/team/TeamMembersMetaStore'; @@ -69,9 +69,7 @@ function normalizePath(value: string | undefined): string | null { return path.resolve(value.trim()); } -export class TeamRuntimeTurnSettledTargetResolver - implements RuntimeTurnSettledTargetResolverPort -{ +export class TeamRuntimeTurnSettledTargetResolver implements RuntimeTurnSettledTargetResolverPort { private readonly memberLogsFinder: AttributedMemberFileSource; private readonly maxTeamsToScan: number; @@ -99,12 +97,12 @@ export class TeamRuntimeTurnSettledTargetResolver .filter((team) => !team.deletedAt) .slice(0, this.maxTeamsToScan); - const candidates: Array<{ + const candidates: { teamName: string; memberName: string; exactPath: boolean; mtimeMs: number; - }> = []; + }[] = []; for (const team of teams) { const attributedFiles = await this.memberLogsFinder diff --git a/src/features/member-work-sync/main/adapters/output/TeamTaskAgendaSource.ts b/src/features/member-work-sync/main/adapters/output/TeamTaskAgendaSource.ts index 8293f4cd..e8d79580 100644 --- a/src/features/member-work-sync/main/adapters/output/TeamTaskAgendaSource.ts +++ b/src/features/member-work-sync/main/adapters/output/TeamTaskAgendaSource.ts @@ -1,19 +1,20 @@ -import { - buildActionableWorkAgenda, - isReservedMemberName, - normalizeMemberName, - type MemberWorkSyncMemberLike, -} from '../../../core/domain'; -import type { - MemberWorkSyncAgendaSourcePort, - MemberWorkSyncAgendaSourceResult, - MemberWorkSyncHashPort, -} from '../../../core/application'; import { inferTeamProviderIdFromModel, normalizeOptionalTeamProviderId, } from '@shared/utils/teamProvider'; +import { + buildActionableWorkAgenda, + isReservedMemberName, + type MemberWorkSyncMemberLike, + normalizeMemberName, +} from '../../../core/domain'; + +import type { + MemberWorkSyncAgendaSourcePort, + MemberWorkSyncAgendaSourceResult, + MemberWorkSyncHashPort, +} from '../../../core/application'; import type { TeamConfigReader } from '@main/services/team/TeamConfigReader'; import type { TeamKanbanManager } from '@main/services/team/TeamKanbanManager'; import type { TeamMembersMetaStore } from '@main/services/team/TeamMembersMetaStore'; diff --git a/src/features/member-work-sync/main/adapters/output/TeamTaskStallJournalWorkSyncCooldown.ts b/src/features/member-work-sync/main/adapters/output/TeamTaskStallJournalWorkSyncCooldown.ts index 2b0ad90d..699c97b6 100644 --- a/src/features/member-work-sync/main/adapters/output/TeamTaskStallJournalWorkSyncCooldown.ts +++ b/src/features/member-work-sync/main/adapters/output/TeamTaskStallJournalWorkSyncCooldown.ts @@ -1,5 +1,6 @@ import { readFile } from 'fs/promises'; import { join } from 'path'; + import type { MemberWorkSyncWatchdogCooldownPort } from '../../../core/application'; const DEFAULT_WATCHDOG_COOLDOWN_MS = 10 * 60_000; @@ -54,10 +55,7 @@ export class TeamTaskStallJournalWorkSyncCooldown implements MemberWorkSyncWatch return alertedAt != null && now - alertedAt <= this.cooldownMs; }); } catch (error) { - if ((error as NodeJS.ErrnoException).code === 'ENOENT') { - return false; - } - return true; + return (error as NodeJS.ErrnoException).code !== 'ENOENT'; } } } diff --git a/src/features/member-work-sync/main/composition/createMemberWorkSyncFeature.ts b/src/features/member-work-sync/main/composition/createMemberWorkSyncFeature.ts index 5fb88636..4c7539f7 100644 --- a/src/features/member-work-sync/main/composition/createMemberWorkSyncFeature.ts +++ b/src/features/member-work-sync/main/composition/createMemberWorkSyncFeature.ts @@ -1,3 +1,43 @@ +import { + MemberWorkSyncDiagnosticsReader, + MemberWorkSyncMetricsReader, + MemberWorkSyncNudgeDispatcher, + type MemberWorkSyncNudgeDispatchSummary, + MemberWorkSyncPendingReportIntentReplayer, + type MemberWorkSyncPendingReportReplaySummary, + type MemberWorkSyncReconcileContext, + MemberWorkSyncReconciler, + MemberWorkSyncReporter, + type RuntimeTurnSettledDrainSummary, + RuntimeTurnSettledIngestor, + type RuntimeTurnSettledTargetResolverPort, +} from '../../core/application'; +import { MemberWorkSyncTeamChangeRouter } from '../adapters/input/MemberWorkSyncTeamChangeRouter'; +import { TeamInboxMemberWorkSyncNudgeSink } from '../adapters/output/TeamInboxMemberWorkSyncNudgeSink'; +import { TeamRuntimeTurnSettledTargetResolver } from '../adapters/output/TeamRuntimeTurnSettledTargetResolver'; +import { TeamTaskAgendaSource } from '../adapters/output/TeamTaskAgendaSource'; +import { TeamTaskStallJournalWorkSyncCooldown } from '../adapters/output/TeamTaskStallJournalWorkSyncCooldown'; +import { ClaudeStopHookPayloadNormalizer } from '../infrastructure/ClaudeStopHookPayloadNormalizer'; +import { CodexNativeTurnSettledPayloadNormalizer } from '../infrastructure/CodexNativeTurnSettledPayloadNormalizer'; +import { CompositeRuntimeTurnSettledPayloadNormalizer } from '../infrastructure/CompositeRuntimeTurnSettledPayloadNormalizer'; +import { FileRuntimeTurnSettledEventStore } from '../infrastructure/FileRuntimeTurnSettledEventStore'; +import { HmacMemberWorkSyncReportTokenAdapter } from '../infrastructure/HmacMemberWorkSyncReportTokenAdapter'; +import { JsonMemberWorkSyncStore } from '../infrastructure/JsonMemberWorkSyncStore'; +import { + MemberWorkSyncEventQueue, + type MemberWorkSyncQueueDiagnostics, +} from '../infrastructure/MemberWorkSyncEventQueue'; +import { MemberWorkSyncNudgeDispatchScheduler } from '../infrastructure/MemberWorkSyncNudgeDispatchScheduler'; +import { MemberWorkSyncStorePaths } from '../infrastructure/MemberWorkSyncStorePaths'; +import { MemberWorkSyncToolActivityBusySignal } from '../infrastructure/MemberWorkSyncToolActivityBusySignal'; +import { NodeHashAdapter } from '../infrastructure/NodeHashAdapter'; +import { RuntimeTurnSettledDrainScheduler } from '../infrastructure/RuntimeTurnSettledDrainScheduler'; +import { buildRuntimeTurnSettledEnvironment } from '../infrastructure/runtimeTurnSettledEnvironment'; +import { buildRuntimeTurnSettledHookSettings } from '../infrastructure/runtimeTurnSettledHookSettings'; +import { RuntimeTurnSettledSpoolPaths } from '../infrastructure/RuntimeTurnSettledSpoolPaths'; +import { ShellRuntimeTurnSettledHookScriptInstaller } from '../infrastructure/ShellRuntimeTurnSettledHookScriptInstaller'; +import { SystemClockAdapter } from '../infrastructure/SystemClockAdapter'; + import type { MemberWorkSyncMetricsRequest, MemberWorkSyncReportRequest, @@ -6,53 +46,13 @@ import type { MemberWorkSyncStatusRequest, MemberWorkSyncTeamMetrics, } from '../../contracts'; -import { - MemberWorkSyncDiagnosticsReader, - MemberWorkSyncMetricsReader, - MemberWorkSyncNudgeDispatcher, - type MemberWorkSyncNudgeDispatchSummary, - MemberWorkSyncPendingReportIntentReplayer, - type MemberWorkSyncPendingReportReplaySummary, - MemberWorkSyncReconciler, - MemberWorkSyncReporter, - type MemberWorkSyncReconcileContext, - RuntimeTurnSettledIngestor, - type RuntimeTurnSettledDrainSummary, - type RuntimeTurnSettledTargetResolverPort, -} from '../../core/application'; -import { MemberWorkSyncTeamChangeRouter } from '../adapters/input/MemberWorkSyncTeamChangeRouter'; -import { TeamInboxMemberWorkSyncNudgeSink } from '../adapters/output/TeamInboxMemberWorkSyncNudgeSink'; -import { TeamTaskStallJournalWorkSyncCooldown } from '../adapters/output/TeamTaskStallJournalWorkSyncCooldown'; -import { TeamTaskAgendaSource } from '../adapters/output/TeamTaskAgendaSource'; -import { TeamRuntimeTurnSettledTargetResolver } from '../adapters/output/TeamRuntimeTurnSettledTargetResolver'; -import { ClaudeStopHookPayloadNormalizer } from '../infrastructure/ClaudeStopHookPayloadNormalizer'; -import { CodexNativeTurnSettledPayloadNormalizer } from '../infrastructure/CodexNativeTurnSettledPayloadNormalizer'; -import { CompositeRuntimeTurnSettledPayloadNormalizer } from '../infrastructure/CompositeRuntimeTurnSettledPayloadNormalizer'; -import { FileRuntimeTurnSettledEventStore } from '../infrastructure/FileRuntimeTurnSettledEventStore'; -import { HmacMemberWorkSyncReportTokenAdapter } from '../infrastructure/HmacMemberWorkSyncReportTokenAdapter'; -import { - MemberWorkSyncEventQueue, - type MemberWorkSyncQueueDiagnostics, -} from '../infrastructure/MemberWorkSyncEventQueue'; -import { JsonMemberWorkSyncStore } from '../infrastructure/JsonMemberWorkSyncStore'; -import { MemberWorkSyncStorePaths } from '../infrastructure/MemberWorkSyncStorePaths'; -import { MemberWorkSyncNudgeDispatchScheduler } from '../infrastructure/MemberWorkSyncNudgeDispatchScheduler'; -import { MemberWorkSyncToolActivityBusySignal } from '../infrastructure/MemberWorkSyncToolActivityBusySignal'; -import { NodeHashAdapter } from '../infrastructure/NodeHashAdapter'; -import { RuntimeTurnSettledDrainScheduler } from '../infrastructure/RuntimeTurnSettledDrainScheduler'; -import { RuntimeTurnSettledSpoolPaths } from '../infrastructure/RuntimeTurnSettledSpoolPaths'; -import { ShellRuntimeTurnSettledHookScriptInstaller } from '../infrastructure/ShellRuntimeTurnSettledHookScriptInstaller'; -import { buildRuntimeTurnSettledEnvironment } from '../infrastructure/runtimeTurnSettledEnvironment'; -import { buildRuntimeTurnSettledHookSettings } from '../infrastructure/runtimeTurnSettledHookSettings'; -import { SystemClockAdapter } from '../infrastructure/SystemClockAdapter'; - +import type { MemberWorkSyncLoggerPort } from '../../core/application'; +import type { RuntimeTurnSettledProvider } from '../../core/domain'; import type { TeamConfigReader } from '@main/services/team/TeamConfigReader'; import type { TeamKanbanManager } from '@main/services/team/TeamKanbanManager'; import type { TeamMembersMetaStore } from '@main/services/team/TeamMembersMetaStore'; import type { TeamTaskReader } from '@main/services/team/TeamTaskReader'; import type { TeamChangeEvent } from '@shared/types'; -import type { MemberWorkSyncLoggerPort } from '../../core/application'; -import type { RuntimeTurnSettledProvider } from '../../core/domain'; export const MEMBER_WORK_SYNC_NUDGE_SIDE_EFFECTS_ENV = 'CLAUDE_TEAM_MEMBER_WORK_SYNC_NUDGES_ENABLED'; @@ -208,17 +208,18 @@ export function createMemberWorkSyncFeature(deps: { drain: () => runtimeTurnSettledIngestor.drainPending(), logger: deps.logger, }); - const nudgeDispatchScheduler = nudgeSideEffectsEnabled && deps.listLifecycleActiveTeamNames - ? new MemberWorkSyncNudgeDispatchScheduler({ - listLifecycleActiveTeamNames: deps.listLifecycleActiveTeamNames, - dispatchDue: (teamNames) => - nudgeDispatcher.dispatchDue({ - teamNames, - claimedBy: `member-work-sync:${process.pid}:scheduled`, - }), - logger: deps.logger, - }) - : null; + const nudgeDispatchScheduler = + nudgeSideEffectsEnabled && deps.listLifecycleActiveTeamNames + ? new MemberWorkSyncNudgeDispatchScheduler({ + listLifecycleActiveTeamNames: deps.listLifecycleActiveTeamNames, + dispatchDue: (teamNames) => + nudgeDispatcher.dispatchDue({ + teamNames, + claimedBy: `member-work-sync:${process.pid}:scheduled`, + }), + logger: deps.logger, + }) + : null; runtimeTurnSettledDrainScheduler.start(); nudgeDispatchScheduler?.start(); diff --git a/src/features/member-work-sync/main/index.ts b/src/features/member-work-sync/main/index.ts index b29c8658..cc2f4c52 100644 --- a/src/features/member-work-sync/main/index.ts +++ b/src/features/member-work-sync/main/index.ts @@ -1,10 +1,11 @@ +export type { RuntimeTurnSettledProvider } from '../core/domain'; export { registerMemberWorkSyncIpc, removeMemberWorkSyncIpc, } from './adapters/input/registerMemberWorkSyncIpc'; +export type { MemberWorkSyncFeatureFacade } from './composition/createMemberWorkSyncFeature'; export { - MEMBER_WORK_SYNC_NUDGE_SIDE_EFFECTS_ENV, createMemberWorkSyncFeature, + MEMBER_WORK_SYNC_NUDGE_SIDE_EFFECTS_ENV, resolveMemberWorkSyncNudgeSideEffectsEnabled, } from './composition/createMemberWorkSyncFeature'; -export type { MemberWorkSyncFeatureFacade } from './composition/createMemberWorkSyncFeature'; diff --git a/src/features/member-work-sync/main/infrastructure/ClaudeStopHookPayloadNormalizer.ts b/src/features/member-work-sync/main/infrastructure/ClaudeStopHookPayloadNormalizer.ts index 225b8268..864bcaff 100644 --- a/src/features/member-work-sync/main/infrastructure/ClaudeStopHookPayloadNormalizer.ts +++ b/src/features/member-work-sync/main/infrastructure/ClaudeStopHookPayloadNormalizer.ts @@ -2,6 +2,7 @@ import { buildRuntimeTurnSettledSourceId, type RuntimeTurnSettledProvider, } from '../../core/domain'; + import type { MemberWorkSyncHashPort, RuntimeTurnSettledPayloadNormalization, diff --git a/src/features/member-work-sync/main/infrastructure/CodexNativeTurnSettledPayloadNormalizer.ts b/src/features/member-work-sync/main/infrastructure/CodexNativeTurnSettledPayloadNormalizer.ts index 89e4c577..6926c0cc 100644 --- a/src/features/member-work-sync/main/infrastructure/CodexNativeTurnSettledPayloadNormalizer.ts +++ b/src/features/member-work-sync/main/infrastructure/CodexNativeTurnSettledPayloadNormalizer.ts @@ -2,6 +2,7 @@ import { buildRuntimeTurnSettledSourceId, type RuntimeTurnSettledProvider, } from '../../core/domain'; + import type { MemberWorkSyncHashPort, RuntimeTurnSettledPayloadNormalization, @@ -28,9 +29,7 @@ function getString(record: Record, ...keys: string[]): string | return undefined; } -export class CodexNativeTurnSettledPayloadNormalizer - implements RuntimeTurnSettledPayloadNormalizerPort -{ +export class CodexNativeTurnSettledPayloadNormalizer implements RuntimeTurnSettledPayloadNormalizerPort { constructor(private readonly hash: MemberWorkSyncHashPort) {} normalize(input: { diff --git a/src/features/member-work-sync/main/infrastructure/FileRuntimeTurnSettledEventStore.ts b/src/features/member-work-sync/main/infrastructure/FileRuntimeTurnSettledEventStore.ts index bd85fc94..29676835 100644 --- a/src/features/member-work-sync/main/infrastructure/FileRuntimeTurnSettledEventStore.ts +++ b/src/features/member-work-sync/main/infrastructure/FileRuntimeTurnSettledEventStore.ts @@ -2,6 +2,7 @@ import { mkdir, readdir, readFile, rename, rm, stat, writeFile } from 'fs/promis import path from 'path'; import { isRuntimeTurnSettledProvider } from '../../core/domain'; + import type { RuntimeTurnSettledClaimedPayload, RuntimeTurnSettledEventStorePort, @@ -131,7 +132,11 @@ export class FileRuntimeTurnSettledEventStore implements RuntimeTurnSettledEvent ): Promise { const processedPath = path.join(this.deps.paths.getProcessedDir(), payload.fileName); await moveFileBestEffort(payload.filePath, processedPath); - await writeFile(buildMetaFilePath(processedPath), `${JSON.stringify(result, null, 2)}\n`, 'utf8'); + await writeFile( + buildMetaFilePath(processedPath), + `${JSON.stringify(result, null, 2)}\n`, + 'utf8' + ); await this.cleanupDirectory(this.deps.paths.getProcessedDir()); } @@ -164,9 +169,7 @@ export class FileRuntimeTurnSettledEventStore implements RuntimeTurnSettledEvent entries .filter( (entry) => - entry.isFile() && - !entry.name.startsWith('.') && - !entry.name.endsWith('.meta.json') + entry.isFile() && !entry.name.startsWith('.') && !entry.name.endsWith('.meta.json') ) .map(async (entry) => { const processingPath = path.join(this.deps.paths.getProcessingDir(), entry.name); diff --git a/src/features/member-work-sync/main/infrastructure/HmacMemberWorkSyncReportTokenAdapter.ts b/src/features/member-work-sync/main/infrastructure/HmacMemberWorkSyncReportTokenAdapter.ts index ad211162..c8d5bc23 100644 --- a/src/features/member-work-sync/main/infrastructure/HmacMemberWorkSyncReportTokenAdapter.ts +++ b/src/features/member-work-sync/main/infrastructure/HmacMemberWorkSyncReportTokenAdapter.ts @@ -6,8 +6,8 @@ import { atomicWriteAsync } from '@main/utils/atomicWrite'; import type { MemberWorkSyncReportTokenCreateInput, MemberWorkSyncReportTokenPort, - MemberWorkSyncReportTokenVerifyInput, MemberWorkSyncReportTokenVerification, + MemberWorkSyncReportTokenVerifyInput, } from '../../core/application'; import type { MemberWorkSyncStorePaths } from './MemberWorkSyncStorePaths'; diff --git a/src/features/member-work-sync/main/infrastructure/JsonMemberWorkSyncStore.ts b/src/features/member-work-sync/main/infrastructure/JsonMemberWorkSyncStore.ts index 3a5b7c86..1b702de8 100644 --- a/src/features/member-work-sync/main/infrastructure/JsonMemberWorkSyncStore.ts +++ b/src/features/member-work-sync/main/infrastructure/JsonMemberWorkSyncStore.ts @@ -1,8 +1,10 @@ +import { withFileLock } from '@main/services/team/fileLock'; import { atomicWriteAsync } from '@main/utils/atomicWrite'; import { createHash } from 'crypto'; import { mkdir, readFile, rename } from 'fs/promises'; -import { withFileLock } from '@main/services/team/fileLock'; +import { assessMemberWorkSyncPhase2Readiness } from '../../core/domain'; + import type { MemberWorkSyncMetricEvent, MemberWorkSyncOutboxClaimInput, @@ -19,7 +21,6 @@ import type { MemberWorkSyncStatusState, MemberWorkSyncTeamMetrics, } from '../../contracts'; -import { assessMemberWorkSyncPhase2Readiness } from '../../core/domain'; import type { MemberWorkSyncOutboxStorePort, MemberWorkSyncReportStorePort, @@ -288,13 +289,10 @@ export class JsonMemberWorkSyncStore stateCounts, actionableItemCount, wouldNudgeCount: recentEvents.filter((event) => event.kind === 'would_nudge').length, - fingerprintChangeCount: recentEvents.filter( - (event) => event.kind === 'fingerprint_changed' - ).length, - reportAcceptedCount: recentEvents.filter((event) => event.kind === 'report_accepted') - .length, - reportRejectedCount: recentEvents.filter((event) => event.kind === 'report_rejected') + fingerprintChangeCount: recentEvents.filter((event) => event.kind === 'fingerprint_changed') .length, + reportAcceptedCount: recentEvents.filter((event) => event.kind === 'report_accepted').length, + reportRejectedCount: recentEvents.filter((event) => event.kind === 'report_rejected').length, recentEvents, }; return { @@ -349,7 +347,7 @@ export class JsonMemberWorkSyncStore await withFileLock(this.paths.getPendingReportsPath(teamName), async () => { const existing = await this.readPendingFile(teamName); const current = existing.intents[id]; - if (!current || current.status !== 'pending') { + if (current?.status !== 'pending') { return; } existing.intents[id] = { @@ -471,7 +469,7 @@ export class JsonMemberWorkSyncStore async markDelivered(input: MemberWorkSyncOutboxMarkDeliveredInput): Promise { await this.updateOutboxItem(input.teamName, input.id, (current) => { - if (!current || current.attemptGeneration !== input.attemptGeneration) { + if (current?.attemptGeneration !== input.attemptGeneration) { return current; } const next: MemberWorkSyncOutboxItem = { @@ -501,7 +499,7 @@ export class JsonMemberWorkSyncStore async markFailed(input: MemberWorkSyncOutboxMarkFailedInput): Promise { await this.updateOutboxItem(input.teamName, input.id, (current) => { - if (!current || current.attemptGeneration !== input.attemptGeneration) { + if (current?.attemptGeneration !== input.attemptGeneration) { return current; } const next: MemberWorkSyncOutboxItem = { @@ -589,9 +587,7 @@ export class JsonMemberWorkSyncStore private async updateOutboxItem( teamName: string, id: string, - updater: ( - current: MemberWorkSyncOutboxItem | undefined - ) => MemberWorkSyncOutboxItem | undefined + updater: (current: MemberWorkSyncOutboxItem | undefined) => MemberWorkSyncOutboxItem | undefined ): Promise { await this.enqueue(teamName, async () => { await withFileLock(this.paths.getOutboxPath(teamName), async () => { diff --git a/src/features/member-work-sync/main/infrastructure/MemberWorkSyncEventQueue.ts b/src/features/member-work-sync/main/infrastructure/MemberWorkSyncEventQueue.ts index f2eded26..87c963a5 100644 --- a/src/features/member-work-sync/main/infrastructure/MemberWorkSyncEventQueue.ts +++ b/src/features/member-work-sync/main/infrastructure/MemberWorkSyncEventQueue.ts @@ -1,5 +1,5 @@ -import type { MemberWorkSyncReconcileContext } from '../../core/application/MemberWorkSyncReconciler'; import type { MemberWorkSyncLoggerPort } from '../../core/application'; +import type { MemberWorkSyncReconcileContext } from '../../core/application/MemberWorkSyncReconciler'; export type MemberWorkSyncTriggerReason = | 'startup_scan' diff --git a/src/features/member-work-sync/main/infrastructure/MemberWorkSyncToolActivityBusySignal.ts b/src/features/member-work-sync/main/infrastructure/MemberWorkSyncToolActivityBusySignal.ts index 37acd736..45512013 100644 --- a/src/features/member-work-sync/main/infrastructure/MemberWorkSyncToolActivityBusySignal.ts +++ b/src/features/member-work-sync/main/infrastructure/MemberWorkSyncToolActivityBusySignal.ts @@ -1,5 +1,4 @@ import type { MemberWorkSyncBusySignalPort } from '../../core/application'; - import type { TeamChangeEvent, ToolActivityEventPayload } from '@shared/types'; const DEFAULT_TOOL_ACTIVITY_BUSY_GRACE_MS = 90_000; diff --git a/src/features/member-work-sync/main/infrastructure/ShellRuntimeTurnSettledHookScriptInstaller.ts b/src/features/member-work-sync/main/infrastructure/ShellRuntimeTurnSettledHookScriptInstaller.ts index fea189bb..7db73b1f 100644 --- a/src/features/member-work-sync/main/infrastructure/ShellRuntimeTurnSettledHookScriptInstaller.ts +++ b/src/features/member-work-sync/main/infrastructure/ShellRuntimeTurnSettledHookScriptInstaller.ts @@ -1,6 +1,6 @@ import fs from 'fs/promises'; -import { RuntimeTurnSettledSpoolPaths } from './RuntimeTurnSettledSpoolPaths'; +import type { RuntimeTurnSettledSpoolPaths } from './RuntimeTurnSettledSpoolPaths'; const HOOK_SCRIPT_CONTENT = `#!/bin/sh set +e @@ -58,6 +58,7 @@ export class ShellRuntimeTurnSettledHookScriptInstaller { const scriptPath = this.paths.getHookScriptPath(); await fs.writeFile(scriptPath, HOOK_SCRIPT_CONTENT, 'utf8'); + // eslint-disable-next-line sonarjs/file-permissions -- the hook script must be executable on POSIX hosts. await fs.chmod(scriptPath, 0o755); return { diff --git a/src/features/member-work-sync/renderer/hooks/useMemberWorkSyncStatus.ts b/src/features/member-work-sync/renderer/hooks/useMemberWorkSyncStatus.ts index 3c6a71ef..dc862626 100644 --- a/src/features/member-work-sync/renderer/hooks/useMemberWorkSyncStatus.ts +++ b/src/features/member-work-sync/renderer/hooks/useMemberWorkSyncStatus.ts @@ -2,12 +2,13 @@ import { useEffect, useState } from 'react'; import { api } from '@renderer/api'; -import type { MemberWorkSyncStatus } from '../../contracts'; import { - toMemberWorkSyncStatusViewModel, type MemberWorkSyncStatusViewModel, + toMemberWorkSyncStatusViewModel, } from '../adapters/memberWorkSyncStatusViewModel'; +import type { MemberWorkSyncStatus } from '../../contracts'; + export interface UseMemberWorkSyncStatusOptions { teamName?: string | null; memberName?: string | null; diff --git a/src/features/member-work-sync/renderer/ui/MemberWorkSyncBadge.tsx b/src/features/member-work-sync/renderer/ui/MemberWorkSyncBadge.tsx index 000b8bc9..5eeb0870 100644 --- a/src/features/member-work-sync/renderer/ui/MemberWorkSyncBadge.tsx +++ b/src/features/member-work-sync/renderer/ui/MemberWorkSyncBadge.tsx @@ -1,18 +1,19 @@ import { Badge } from '@renderer/components/ui/badge'; import { cn } from '@renderer/lib/utils'; -import type React from 'react'; -import type { MemberWorkSyncStatus } from '../../contracts'; import { - toMemberWorkSyncStatusViewModel, type MemberWorkSyncStatusViewModel, + toMemberWorkSyncStatusViewModel, } from '../adapters/memberWorkSyncStatusViewModel'; -interface MemberWorkSyncBadgeProps { +import type { MemberWorkSyncStatus } from '../../contracts'; +import type React from 'react'; + +type MemberWorkSyncBadgeProps = Readonly<{ status?: MemberWorkSyncStatus | null; viewModel?: MemberWorkSyncStatusViewModel; className?: string; -} +}>; const toneClassName: Record = { neutral: 'border-[var(--color-border)] text-[var(--color-text-muted)]', @@ -32,7 +33,11 @@ export function MemberWorkSyncBadge({ return ( {resolved.label} diff --git a/src/features/member-work-sync/renderer/ui/MemberWorkSyncDetails.tsx b/src/features/member-work-sync/renderer/ui/MemberWorkSyncDetails.tsx index 81921c5d..5f21e65f 100644 --- a/src/features/member-work-sync/renderer/ui/MemberWorkSyncDetails.tsx +++ b/src/features/member-work-sync/renderer/ui/MemberWorkSyncDetails.tsx @@ -1,12 +1,14 @@ -import { MemberWorkSyncBadge } from './MemberWorkSyncBadge'; -import type { MemberWorkSyncStatus } from '../../contracts'; import { toMemberWorkSyncStatusViewModel } from '../adapters/memberWorkSyncStatusViewModel'; + +import { MemberWorkSyncBadge } from './MemberWorkSyncBadge'; + +import type { MemberWorkSyncStatus } from '../../contracts'; import type React from 'react'; -interface MemberWorkSyncDetailsProps { +type MemberWorkSyncDetailsProps = Readonly<{ status: MemberWorkSyncStatus | null; showDiagnostics?: boolean; -} +}>; function shortFingerprint(fingerprint?: string): string { if (!fingerprint) { diff --git a/src/features/member-work-sync/renderer/ui/MemberWorkSyncStatusPanel.tsx b/src/features/member-work-sync/renderer/ui/MemberWorkSyncStatusPanel.tsx index 6a4d1392..919fcfa3 100644 --- a/src/features/member-work-sync/renderer/ui/MemberWorkSyncStatusPanel.tsx +++ b/src/features/member-work-sync/renderer/ui/MemberWorkSyncStatusPanel.tsx @@ -1,15 +1,16 @@ -import type React from 'react'; +import { useMemberWorkSyncStatus } from '../hooks/useMemberWorkSyncStatus'; import { MemberWorkSyncBadge } from './MemberWorkSyncBadge'; import { MemberWorkSyncDetails } from './MemberWorkSyncDetails'; -import { useMemberWorkSyncStatus } from '../hooks/useMemberWorkSyncStatus'; -interface MemberWorkSyncStatusPanelProps { +import type React from 'react'; + +type MemberWorkSyncStatusPanelProps = Readonly<{ teamName: string; memberName: string; enabled?: boolean; showDiagnostics?: boolean; -} +}>; export function MemberWorkSyncStatusPanel({ teamName, diff --git a/src/main/http/index.ts b/src/main/http/index.ts index 09f7c0c6..d7c27aa7 100644 --- a/src/main/http/index.ts +++ b/src/main/http/index.ts @@ -9,7 +9,6 @@ import { type RecentProjectsFeatureFacade, registerRecentProjectsHttp, } from '@features/recent-projects/main'; -import type { MemberWorkSyncFeatureFacade } from '@features/member-work-sync/main'; import { createLogger } from '@shared/utils/logger'; import { registerConfigRoutes } from './config'; @@ -36,6 +35,7 @@ import type { import type { SshConnectionManager } from '../services/infrastructure/SshConnectionManager'; import type { TeamDataService } from '../services/team/TeamDataService'; import type { TeamProvisioningService } from '../services/team/TeamProvisioningService'; +import type { MemberWorkSyncFeatureFacade } from '@features/member-work-sync/main'; import type { FastifyInstance } from 'fastify'; const logger = createLogger('HTTP:routes'); diff --git a/src/main/index.ts b/src/main/index.ts index e28e364f..ebc0dc2e 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -30,18 +30,18 @@ import { type CodexModelCatalogFeatureFacade, createCodexModelCatalogFeature, } from '@features/codex-model-catalog/main'; -import { - createRecentProjectsFeature, - type RecentProjectsFeatureFacade, - registerRecentProjectsIpc, - removeRecentProjectsIpc, -} from '@features/recent-projects/main'; import { createMemberWorkSyncFeature, type MemberWorkSyncFeatureFacade, registerMemberWorkSyncIpc, removeMemberWorkSyncIpc, } from '@features/member-work-sync/main'; +import { + createRecentProjectsFeature, + type RecentProjectsFeatureFacade, + registerRecentProjectsIpc, + removeRecentProjectsIpc, +} from '@features/recent-projects/main'; import { createRuntimeProviderManagementFeature, registerRuntimeProviderManagementIpc, @@ -179,19 +179,19 @@ import { SshConnectionManager, TaskBoundaryParser, TeamDataService, + TeamKanbanManager, TeamLogSourceTracker, TeammateToolTracker, TeamMemberLogsFinder, + TeamMembersMetaStore, TeamProvisioningService, TeamRuntimeAdapterRegistry, - TeamKanbanManager, - TeamMembersMetaStore, + TeamTaskReader, TeamTaskStallJournal, TeamTaskStallMonitor, TeamTaskStallNotifier, TeamTaskStallPolicy, TeamTaskStallSnapshotSource, - TeamTaskReader, UpdaterService, } from './services'; diff --git a/src/main/services/team/TaskChangeLedgerReader.ts b/src/main/services/team/TaskChangeLedgerReader.ts index 644f58ca..3670c56d 100644 --- a/src/main/services/team/TaskChangeLedgerReader.ts +++ b/src/main/services/team/TaskChangeLedgerReader.ts @@ -1152,7 +1152,7 @@ export class TaskChangeLedgerReader { string, { event: LedgerEvent; index: number; rank: number } >(); - const passthrough: Array<{ event: LedgerEvent; index: number }> = []; + const passthrough: { event: LedgerEvent; index: number }[] = []; events.forEach((event, index) => { const sourceImportKey = this.sourceImportKeyForEvent(event); diff --git a/src/main/services/team/TeamProvisioningService.ts b/src/main/services/team/TeamProvisioningService.ts index cb13b9bb..9d55b060 100644 --- a/src/main/services/team/TeamProvisioningService.ts +++ b/src/main/services/team/TeamProvisioningService.ts @@ -2,7 +2,6 @@ import { resolveAnthropicFastMode, resolveAnthropicRuntimeSelection, } from '@features/anthropic-runtime-profile/main'; -import type { RuntimeTurnSettledProvider } from '@features/member-work-sync/core/domain'; import { buildCodexFastModeArgs, resolveCodexFastMode, @@ -239,6 +238,7 @@ import type { TeamRuntimePrepareResult, TeamRuntimeStopInput, } from './runtime'; +import type { RuntimeTurnSettledProvider } from '@features/member-work-sync/main'; /** * Kill a team CLI process using SIGKILL (uncatchable). diff --git a/src/renderer/components/team/members/MemberDetailDialog.tsx b/src/renderer/components/team/members/MemberDetailDialog.tsx index 1b3c5166..eed114d4 100644 --- a/src/renderer/components/team/members/MemberDetailDialog.tsx +++ b/src/renderer/components/team/members/MemberDetailDialog.tsx @@ -1,12 +1,12 @@ import { useEffect, useMemo, useState } from 'react'; +import { MemberWorkSyncStatusPanel } from '@features/member-work-sync/renderer'; import { Button } from '@renderer/components/ui/button'; import { Dialog, DialogContent, DialogFooter, DialogHeader } from '@renderer/components/ui/dialog'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@renderer/components/ui/tabs'; import { useMemberStats } from '@renderer/hooks/useMemberStats'; import { useStore } from '@renderer/store'; import { selectMemberMessagesForTeamMember } from '@renderer/store/slices/teamSlice'; -import { MemberWorkSyncStatusPanel } from '@features/member-work-sync/renderer'; import { buildMemberLaunchDiagnosticsPayload, getMemberLaunchDiagnosticsErrorMessage, diff --git a/src/shared/types/api.ts b/src/shared/types/api.ts index c55a31bf..b76e809a 100644 --- a/src/shared/types/api.ts +++ b/src/shared/types/api.ts @@ -95,8 +95,6 @@ import type { TerminalAPI } from './terminal'; import type { TmuxAPI } from './tmux'; import type { WaterfallData } from './visualization'; import type { CodexAccountElectronApi } from '@features/codex-account/contracts'; -import type { RecentProjectsElectronApi } from '@features/recent-projects/contracts'; -import type { RuntimeProviderManagementApi } from '@features/runtime-provider-management/contracts'; import type { MemberWorkSyncMetricsRequest, MemberWorkSyncReportRequest, @@ -105,6 +103,8 @@ import type { MemberWorkSyncStatusRequest, MemberWorkSyncTeamMetrics, } from '@features/member-work-sync/contracts'; +import type { RecentProjectsElectronApi } from '@features/recent-projects/contracts'; +import type { RuntimeProviderManagementApi } from '@features/runtime-provider-management/contracts'; import type { ConversationGroup, FileChangeEvent, diff --git a/test/features/member-work-sync/main/RuntimeTurnSettledHookSettings.test.ts b/test/features/member-work-sync/main/RuntimeTurnSettledHookSettings.test.ts index d6461ab8..2ad9a67c 100644 --- a/test/features/member-work-sync/main/RuntimeTurnSettledHookSettings.test.ts +++ b/test/features/member-work-sync/main/RuntimeTurnSettledHookSettings.test.ts @@ -79,8 +79,10 @@ describe('runtime turn-settled hook settings', () => { expect(fs.existsSync(paths.getProcessedDir())).toBe(true); expect(fs.existsSync(paths.getInvalidDir())).toBe(true); - const stat = fs.statSync(result.scriptPath); - expect(stat.mode & 0o111).toBeGreaterThan(0); + if (process.platform !== 'win32') { + const stat = fs.statSync(result.scriptPath); + expect(stat.mode & 0o111).toBeGreaterThan(0); + } expect(fs.readFileSync(result.scriptPath, 'utf8')).toContain('dd bs="$max_bytes"'); }); });