feat(onboarding): 接入包前端 UI——治理面板升级为应用接入包

治理面板 buff 区改为应用接入包:调 apply_onboarding_pack(种 3 模板 + 挂 buff),新增模板分发结果展示(written/skipped/failed)。接入包 A/B/C1/C2 就绪,剩 D 可信度提示。
This commit is contained in:
lanrtop 2026-06-19 13:07:09 +09:00
parent ee2a37876e
commit 150535ffcf
2 changed files with 35 additions and 6 deletions

View File

@ -73,8 +73,8 @@ git 是「过去时 + 量化」(做了什么),蓝图是「将来时 + 语
- files: src-tauri/src/commands/onboarding.rs, src-tauri/resources/onboarding/{AGENTS.md,lefthook.yml,git-workflow.md}.tmpl - files: src-tauri/src/commands/onboarding.rs, src-tauri/resources/onboarding/{AGENTS.md,lefthook.yml,git-workflow.md}.tmpl
- acceptance: include_str! 内嵌 3 个标准模板(蓝本取自 enterprise-system分发时文件不存在→写入、已存在→跳过并在报告标注绝不覆盖复用 mcp_inject 的路径解析(含 WSL返回每个模板的 written/skipped/failed - acceptance: include_str! 内嵌 3 个标准模板(蓝本取自 enterprise-system分发时文件不存在→写入、已存在→跳过并在报告标注绝不覆盖复用 mcp_inject 的路径解析(含 WSL返回每个模板的 written/skipped/failed
### 🔵 B apply_onboarding_pack 编排 + 前端入口 ### B apply_onboarding_pack 编排 + 前端入口
- status: in_progress - status: done
- complexity: M - complexity: M
- depends: onboarding-pack卡A - depends: onboarding-pack卡A
- files: src-tauri/src/commands/onboarding.rs, src-tauri/src/lib.rs, src/lib/commands.ts, src/components/dashboard/ProjectCard.tsx - files: src-tauri/src/commands/onboarding.rs, src-tauri/src/lib.rs, src/lib/commands.ts, src/components/dashboard/ProjectCard.tsx

View File

@ -22,7 +22,7 @@ import {
getFlywheelStats, getFlywheelStats,
generateMuhePrompt, generateMuhePrompt,
archiveProjectDocs, archiveProjectDocs,
applyBlueprintBuff, applyOnboardingPack,
removeBlueprintBuff, removeBlueprintBuff,
getBuffStatus, getBuffStatus,
getUserConventionsStatus, getUserConventionsStatus,
@ -38,6 +38,7 @@ import {
type FlywheelStats, type FlywheelStats,
type StalledProject, type StalledProject,
type BuffStatus, type BuffStatus,
type TemplateResult,
type UserConventionsStatus, type UserConventionsStatus,
} from "../../lib/commands"; } from "../../lib/commands";
@ -1068,6 +1069,7 @@ function GovernancePanel({
const [buffError, setBuffError] = useState<string | null>(null); const [buffError, setBuffError] = useState<string | null>(null);
const [buffInitPrompt, setBuffInitPrompt] = useState<string | null>(null); const [buffInitPrompt, setBuffInitPrompt] = useState<string | null>(null);
const [buffInitCopied, setBuffInitCopied] = useState(false); const [buffInitCopied, setBuffInitCopied] = useState(false);
const [packTemplates, setPackTemplates] = useState<TemplateResult[] | null>(null);
const [promptMode, setPromptMode] = useState<"init" | "sync" | null>(null); const [promptMode, setPromptMode] = useState<"init" | "sync" | null>(null);
const [prompt, setPrompt] = useState(""); const [prompt, setPrompt] = useState("");
@ -1091,8 +1093,10 @@ function GovernancePanel({
setBuffLoading(true); setBuffLoading(true);
setBuffError(null); setBuffError(null);
setBuffInitPrompt(null); setBuffInitPrompt(null);
setPackTemplates(null);
try { try {
await applyBlueprintBuff(projectPath, projectId); const report = await applyOnboardingPack(projectPath, projectId);
setPackTemplates(report.templates);
refetchBuff(); refetchBuff();
// 只有尚无蓝图时才展示 init prompt已有蓝图则 Buff 直接激活无需初始化 // 只有尚无蓝图时才展示 init prompt已有蓝图则 Buff 直接激活无需初始化
if (bpStatus?.status === "none") { if (bpStatus?.status === "none") {
@ -1113,6 +1117,7 @@ function GovernancePanel({
await removeBlueprintBuff(projectPath); await removeBlueprintBuff(projectPath);
refetchBuff(); refetchBuff();
setBuffInitPrompt(null); setBuffInitPrompt(null);
setPackTemplates(null);
} catch (e) { } catch (e) {
setBuffError(String(e)); setBuffError(String(e));
} finally { } finally {
@ -1435,13 +1440,13 @@ function GovernancePanel({
{/* ── 蓝图 Buff ─────────────────────────────────────── */} {/* ── 蓝图 Buff ─────────────────────────────────────── */}
<div className="bg-white rounded-lg border border-gray-100 p-3 space-y-2"> <div className="bg-white rounded-lg border border-gray-100 p-3 space-y-2">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<p className="text-[10px] font-semibold text-gray-400 uppercase tracking-wider"> Buff</p> <p className="text-[10px] font-semibold text-gray-400 uppercase tracking-wider"></p>
{buffStatus?.status === "active" && ( {buffStatus?.status === "active" && (
<span className="text-[10px] text-purple-600 bg-purple-50 border border-purple-200 px-1.5 py-0.5 rounded-full"> </span> <span className="text-[10px] text-purple-600 bg-purple-50 border border-purple-200 px-1.5 py-0.5 rounded-full"> </span>
)} )}
</div> </div>
<p className="text-[11px] text-gray-500 leading-relaxed"> <p className="text-[11px] text-gray-500 leading-relaxed">
Buff git AGENTS.md / lefthook / git-workflow buff git
</p> </p>
{buffStatus?.last_sync_at && ( {buffStatus?.last_sync_at && (
<p className="text-[10px] text-gray-400">{buffStatus.last_sync_at}</p> <p className="text-[10px] text-gray-400">{buffStatus.last_sync_at}</p>
@ -1449,6 +1454,30 @@ function GovernancePanel({
{buffError && ( {buffError && (
<p className="text-[11px] text-red-600 font-mono break-all">{buffError}</p> <p className="text-[11px] text-red-600 font-mono break-all">{buffError}</p>
)} )}
{packTemplates && (
<div className="space-y-0.5 pt-0.5">
<p className="text-[10px] text-gray-500 font-semibold"></p>
{packTemplates.map((t) => (
<p key={t.name} className="text-[10px] font-mono flex items-center gap-1">
<span
className={
t.action === "written"
? "text-green-600"
: t.action === "skipped"
? "text-gray-400"
: "text-red-600"
}
>
{t.action === "written" ? "✓" : t.action === "skipped" ? "○" : "✗"}
</span>
<span className="text-gray-600 truncate flex-1">{t.name}</span>
<span className="text-gray-400">
{t.action === "written" ? "已写入" : t.action === "skipped" ? "已存在" : t.detail}
</span>
</p>
))}
</div>
)}
{buffStatus?.status === "active" ? ( {buffStatus?.status === "active" ? (
<button <button
onClick={handleRemoveBuff} onClick={handleRemoveBuff}