diff --git a/apps/dashboard/src/ServicePanel.test.ts b/apps/dashboard/src/ServicePanel.test.ts
index 57d1eac..416fb8a 100644
--- a/apps/dashboard/src/ServicePanel.test.ts
+++ b/apps/dashboard/src/ServicePanel.test.ts
@@ -85,22 +85,6 @@ const baseProps: ServicePanelProps = {
},
],
{
- inbox: [
- {
- createdAt: '2026-04-28T04:10:00.000Z',
- groupFolder: 'eyejokerdb',
- groupKey: 'ci',
- id: 'ci-1',
- kind: 'ci-failure',
- lastOccurredAt: '2026-04-28T04:12:00.000Z',
- occurrences: 2,
- occurredAt: '2026-04-28T04:10:00.000Z',
- severity: 'error',
- source: 'status-snapshot',
- summary: 'CI failed',
- title: 'CI failed',
- },
- ],
operations: {
serviceRestarts: [
{
@@ -113,6 +97,13 @@ const baseProps: ServicePanelProps = {
},
],
},
+ tasks: {
+ active: 0,
+ completed: 0,
+ paused: 2,
+ total: 2,
+ watchers: { active: 0, completed: 0, paused: 2 },
+ },
},
),
serviceActionKey: null,
diff --git a/apps/dashboard/src/ServicePanel.tsx b/apps/dashboard/src/ServicePanel.tsx
index 63c5c97..e87ab5a 100644
--- a/apps/dashboard/src/ServicePanel.tsx
+++ b/apps/dashboard/src/ServicePanel.tsx
@@ -67,11 +67,7 @@ export function ServicePanel({
},
{ pendingTasks: 0, pendingMessageRooms: 0 },
);
- const ciFailures = overview.inbox.reduce(
- (count, item) =>
- item.kind === 'ci-failure' ? count + item.occurrences : count,
- 0,
- );
+ const ciFailures = overview.tasks.watchers.paused;
const healthLevel: HealthLevel =
down > 0 ? 'down' : stale > 0 || ciFailures > 0 ? 'stale' : 'ok';
const affectedServices = serviceLevels.filter((item) => item.level !== 'ok');
diff --git a/apps/dashboard/src/SettingsPanel.test.ts b/apps/dashboard/src/SettingsPanel.test.ts
index 2910103..064ef1b 100644
--- a/apps/dashboard/src/SettingsPanel.test.ts
+++ b/apps/dashboard/src/SettingsPanel.test.ts
@@ -21,7 +21,8 @@ describe('SettingsPanel', () => {
const html = renderToStaticMarkup(createElement(SettingsPanel, baseProps));
expect(html).toContain('settings-panel');
- expect(html).toContain('settings-hero');
+ expect(html).not.toContain('settings-hero');
+ expect(html).toContain('settings-sidebar');
expect(html).toContain('settings-nav');
expect(html).toContain(t.settings.nicknameLabel);
expect(html).toContain('value="Night Owl"');
@@ -41,7 +42,9 @@ describe('SettingsPanel', () => {
expect(html).toContain('aria-controls="settings-codex"');
expect(html).not.toContain('href="#settings-codex"');
expect(html).toContain('/goal');
- expect(html).toContain('변경 적용');
+ expect(html).toContain('settings-apply-card');
+ expect(html).not.toContain('settings-apply-bar');
+ expect(html).toContain('저장 후 재시작');
expect(html).toContain('불러오는 중');
expect(html).toContain('Claude');
expect(html).toContain('계정');
diff --git a/apps/dashboard/src/SettingsPanel.tsx b/apps/dashboard/src/SettingsPanel.tsx
index 6d56ef2..b436760 100644
--- a/apps/dashboard/src/SettingsPanel.tsx
+++ b/apps/dashboard/src/SettingsPanel.tsx
@@ -62,9 +62,11 @@ export function SettingsPanel({
}: SettingsPanelProps) {
return (
-
-
+
-
-
@@ -134,26 +134,6 @@ export function SettingsPanel({
);
}
-function SettingsHero() {
- return (
-
-
-
Operations console
-
설정
-
- 모델, MoA, Codex 실험 기능, 계정을 한 화면에서 조정합니다. 런타임에
- 반영되는 항목은 저장 후 한 번만 재시작하면 됩니다.
-
-
-
- Codex /goal
- MoA
- Accounts
-
-
- );
-}
-
function SettingsNav() {
const scrollToSection = (targetId: string) => {
document
@@ -197,16 +177,13 @@ function SettingsSectionHeading({
);
}
-function SettingsApplyBar({ onRestartStack }: { onRestartStack: () => void }) {
+function SettingsApplyCard({ onRestartStack }: { onRestartStack: () => void }) {
return (
-
+
- Apply changes
- 변경 적용
-
- 모델, MoA, Codex 실험 기능, 계정 변경은 저장 후 스택 재시작으로
- 적용됩니다.
-
+ Apply
+ 저장 후 재시작
+ 모델, MoA, Codex, 계정 변경은 스택 재시작 후 반영됩니다.