From 57dd4ffcb733d10879e5a122642df5af1a263544 Mon Sep 17 00:00:00 2001
From: nntrivi2001
Date: Thu, 6 Aug 2026 10:22:58 +0700
Subject: [PATCH] feat(lanes): add Lanes section (skills install, housekeeping)
to Settings (F4)
---
client/src/i18n/locales/en/settings.json | 9 +
client/src/i18n/locales/vi/settings.json | 9 +
client/src/pages/Settings.tsx | 66 ++++++++
.../screens.snapshot.test.tsx.snap | 158 ++++++++++++++++++
4 files changed, 242 insertions(+)
diff --git a/client/src/i18n/locales/en/settings.json b/client/src/i18n/locales/en/settings.json
index dd75c36..0dd5533 100644
--- a/client/src/i18n/locales/en/settings.json
+++ b/client/src/i18n/locales/en/settings.json
@@ -61,6 +61,15 @@
"success": "Hooks installed successfully",
"failed": "Hook installation failed"
},
+ "lanesSection": {
+ "title": "Lanes",
+ "description": "Machine-wide housekeeping and one-time setup for the ship-feature-lane pipeline.",
+ "installSkill": "Install ship-feature-lane skill",
+ "installSkillSuccess": "Installed to {{path}}",
+ "runHousekeeping": "Run housekeeping",
+ "dryRun": "Dry run",
+ "gcResult": "Reaped {{reaped}} process(es), capped {{capped}} log(s)"
+ },
"notifications": {
"title": "Notifications",
"description": "Browser notifications for important events. Requires permission.",
diff --git a/client/src/i18n/locales/vi/settings.json b/client/src/i18n/locales/vi/settings.json
index cc54a5c..4e773b6 100644
--- a/client/src/i18n/locales/vi/settings.json
+++ b/client/src/i18n/locales/vi/settings.json
@@ -61,6 +61,15 @@
"success": "Cài hooks thành công",
"failed": "Cài hooks thất bại"
},
+ "lanesSection": {
+ "title": "Lanes",
+ "description": "Bảo trì toàn máy và cài đặt một lần cho pipeline ship-feature-lane.",
+ "installSkill": "Cài skill ship-feature-lane",
+ "installSkillSuccess": "Đã cài vào {{path}}",
+ "runHousekeeping": "Chạy dọn dẹp",
+ "dryRun": "Chạy thử (dry run)",
+ "gcResult": "Đã dọn {{reaped}} tiến trình, cắt {{capped}} log"
+ },
"notifications": {
"title": "Thông báo",
"description": "Thông báo trình duyệt cho các sự kiện quan trọng. Cần cấp quyền.",
diff --git a/client/src/pages/Settings.tsx b/client/src/pages/Settings.tsx
index 012502d..dc8206f 100644
--- a/client/src/pages/Settings.tsx
+++ b/client/src/pages/Settings.tsx
@@ -132,6 +132,7 @@ const SETTINGS_SECTIONS: {
}[] = [
{ id: "pricing", labelKey: "pricing.title", Icon: DollarSign },
{ id: "hooks", labelKey: "hooks.title", Icon: Plug },
+ { id: "lanes", labelKey: "lanesSection.title", Icon: GitBranch },
{ id: "claude-home", labelKey: "claudeHome.title", Icon: FolderOpen },
{ id: "import", labelKey: "import.title", fallback: "Import", Icon: History },
{
@@ -468,6 +469,7 @@ export function Settings() {
}, []);
const [abandonHours, setAbandonHours] = useState("24");
const [purgeDays, setPurgeDays] = useState("90");
+ const [gcDryRun, setGcDryRun] = useState(false);
const [claudeHome, setClaudeHomeState] = useState("");
const [claudeHomeInput, setClaudeHomeInput] = useState("");
const [claudeHomeSaving, setClaudeHomeSaving] = useState(false);
@@ -727,6 +729,18 @@ export function Settings() {
return res.ok ? t("hooks.success") : t("hooks.failed");
});
+ const handleSkillsInstall = () =>
+ runAction("skills-install", async () => {
+ const res = await api.settings.skillsInstall();
+ return t("lanesSection.installSkillSuccess", { path: res.path });
+ });
+
+ const handleGc = () =>
+ runAction("gc", async () => {
+ const res = await api.settings.gc({ dryRun: gcDryRun });
+ return t("lanesSection.gcResult", { reaped: res.reaped.length, capped: res.capped.length });
+ });
+
const handleResetPricing = () =>
runAction("reset-pricing", async () => {
const res = await api.settings.resetPricing();
@@ -1357,6 +1371,58 @@ export function Settings() {
+ {/* ─── LANES ─── */}
+
+
+
+ {t("lanesSection.title")}
+
+ {t("lanesSection.description")}
+
+
+
+ {t("lanesSection.installSkill")}
+
+
+ {actionBanner(["skills-install"])}
+
+
+
+
+
+ {actionBanner(["gc"])}
+
+
+
{/* ─── CLAUDE HOME ─── */}
diff --git a/client/src/pages/__tests__/__snapshots__/screens.snapshot.test.tsx.snap b/client/src/pages/__tests__/__snapshots__/screens.snapshot.test.tsx.snap
index e00e874..5de7b7b 100644
--- a/client/src/pages/__tests__/__snapshots__/screens.snapshot.test.tsx.snap
+++ b/client/src/pages/__tests__/__snapshots__/screens.snapshot.test.tsx.snap
@@ -7522,6 +7522,44 @@ exports[`screen snapshots > Settings 1`] = `
Hook Configuration
+
+