feat: refocus governance mutations after save
Some checks failed
StoryForge CI / Baseline checks (push) Has been cancelled
StoryForge CI / Backend tests (push) Has been cancelled
StoryForge CI / Web tests (push) Has been cancelled

This commit is contained in:
kris
2026-04-04 10:45:31 +08:00
parent 75142941f2
commit e910d976f8
3 changed files with 66 additions and 2 deletions

View File

@@ -298,3 +298,10 @@
- 精确版本 id
- 推荐业务动作
- 工作流标签
### 治理保存后的工作区回跳
- OneLiner 主配置在保存和历史回滚成功后,会自动回到 `Agent -> 当前 Agent 工作台 -> OneLiner 主 Agent` 区块。
- 用户全局策略、用户平台策略在保存和历史回滚成功后,会自动回到 `我的策略` 对应 tab不再只停留在成功提示里。
- 管理员覆盖策略在保存和历史回滚成功后,会自动回到 `管理员配置台 -> 覆盖与审计`,方便连续治理和审计查看。
- 前端回归新增了这三条治理回跳断言,避免后续又退回成“改完策略后自己重新找页面”。

View File

@@ -4447,7 +4447,7 @@ function renderAdminGovernanceAuditPanel() {
const targetSummary = getAdminOverrideTargetSummary();
const audits = safeArray(appState.adminPolicyAudits);
return `
<div class="panel pad" style="box-shadow:none; margin-top:18px;">
<div class="panel pad" id="admin-override-audit-anchor" style="box-shadow:none; margin-top:18px;">
<div class="panel-head">
<div>
<h3>覆盖与审计</h3>
@@ -6588,6 +6588,7 @@ function renderPlaybookScreen() {
<div class="layout-grid grid-main">
<div class="side-stack">
<div class="panel pad" style="box-shadow:none;">
<div id="oneliner-profile-anchor"></div>
<div class="panel-head">
<div>
<h3>OneLiner 主 Agent</h3>
@@ -7274,7 +7275,7 @@ function renderStrategyScreen() {
</div>
` : ""}
</div>
<div class="panel pad" style="margin-top:18px;">
<div class="panel pad" id="strategy-governance-anchor" style="margin-top:18px;">
<div class="panel-head">
<div>
<h3>策略治理</h3>
@@ -8858,6 +8859,14 @@ function openUploadVideoAction() {
});
}
function focusPlaybookOneLinerWorkspace(anchorId = "oneliner-profile-anchor") {
appState.playbookDetailTab = "workspace";
setScreen("playbook");
setTimeout(() => {
document.getElementById(anchorId)?.scrollIntoView({ block: "start", behavior: "smooth" });
}, 0);
}
function openOneLinerProfileAction() {
const project = requireSelectedProject();
const assistants = getAssistantOptions(project.id);
@@ -8897,6 +8906,7 @@ function openOneLinerProfileAction() {
await loadAgentControlSurfaces(project.id);
rememberAction("OneLiner 已保存", `已更新 OneLiner「${saved.display_name || "OneLiner"}」配置,当前版本 ${saved.current_version?.version_no || 1}`, "green", saved);
renderAll();
focusPlaybookOneLinerWorkspace("oneliner-profile-anchor");
}
});
}
@@ -8959,6 +8969,7 @@ async function openOneLinerProfileHistoryAction(preferredVersionId = "") {
await loadAgentControlSurfaces(project.id);
rememberAction("OneLiner 已回滚", `已回滚到版本 ${saved.current_version?.version_no || "指定版本"}`, "green", saved);
renderAll();
focusPlaybookOneLinerWorkspace("oneliner-profile-anchor");
}
});
}
@@ -9123,6 +9134,22 @@ function ensureAdminOverrideTargetReady(target) {
return false;
}
function focusUserGovernanceWorkspace(tab = "effective", anchorId = "strategy-governance-anchor") {
appState.strategyDetailTab = tab;
setScreen("strategy");
setTimeout(() => {
document.getElementById(anchorId)?.scrollIntoView({ block: "start", behavior: "smooth" });
}, 0);
}
function focusAdminGovernanceAuditWorkspace(anchorId = "admin-override-audit-anchor") {
appState.adminWorkbenchTab = "governance_audit";
setScreen("admin-workbench");
setTimeout(() => {
document.getElementById(anchorId)?.scrollIntoView({ block: "start", behavior: "smooth" });
}, 0);
}
function openUserGlobalPolicyAction() {
const project = requireSelectedProject();
const bundle = appState.userGlobalPolicy || {};
@@ -9153,6 +9180,7 @@ function openUserGlobalPolicyAction() {
await loadAgentControlSurfaces(project.id);
rememberAction("我的全局策略已保存", `已发布版本 ${saved.current_version?.version_no || 1}`, "green", saved);
renderAll();
focusUserGovernanceWorkspace("global", "strategy-governance-anchor");
}
});
}
@@ -9188,6 +9216,7 @@ function openUserPlatformPolicyAction(platform) {
await loadAgentControlSurfaces(project.id);
rememberAction(`${platformLabel(normalizedPlatform)} 平台策略已保存`, `已发布版本 ${saved.current_version?.version_no || 1}`, "green", saved);
renderAll();
focusUserGovernanceWorkspace("platform", "strategy-governance-anchor");
}
});
}
@@ -9223,6 +9252,7 @@ async function openUserGlobalPolicyHistoryAction(preferredVersionId = "") {
await loadAgentControlSurfaces(project.id);
rememberAction("我的全局策略已回滚", `已生成回滚版本 ${saved.current_version?.version_no || "所选版本"}`, "green", saved);
renderAll();
focusUserGovernanceWorkspace("global", "strategy-governance-anchor");
}
});
}
@@ -9259,6 +9289,7 @@ async function openUserPlatformPolicyHistoryAction(platform, preferredVersionId
await loadAgentControlSurfaces(project.id);
rememberAction(`${platformLabel(normalizedPlatform)} 平台策略已回滚`, `已生成回滚版本 ${saved.current_version?.version_no || "所选版本"}`, "green", saved);
renderAll();
focusUserGovernanceWorkspace("platform", "strategy-governance-anchor");
}
});
}
@@ -9431,6 +9462,7 @@ function openAdminOverridePolicyAction() {
await loadAgentControlSurfaces(getOneLinerProjectId());
rememberAction("管理员覆盖策略已保存", `已为 ${formatAdminGovernanceTargetLabel(target)} 发布版本 ${saved.current_version?.version_no || 1}`, "green", saved);
renderAll();
focusAdminGovernanceAuditWorkspace("admin-override-audit-anchor");
}
});
}
@@ -9468,6 +9500,7 @@ async function openAdminOverrideHistoryAction(preferredVersionId = "") {
await loadAgentControlSurfaces(getOneLinerProjectId());
rememberAction("管理员覆盖已回滚", `已回滚到版本 ${saved.current_version?.version_no || "所选版本"}`, "green", saved);
renderAll();
focusAdminGovernanceAuditWorkspace("admin-override-audit-anchor");
}
});
}

View File

@@ -645,17 +645,25 @@ test("system governance saves refresh control surfaces after persisting", () =>
});
test("oneliner profile history exposes rollback and audit entrypoints", () => {
const playbookFocusHelper = extractBetween(APP, "function focusPlaybookOneLinerWorkspace(anchorId = \"oneliner-profile-anchor\") {", "function openOneLinerProfileAction() {");
const profile = extractBetween(APP, "function openOneLinerProfileAction()", "function resolvePreferredVersionId(history, preferredVersionId = \"\")");
const profileHistory = extractBetween(APP, "async function openOneLinerProfileHistoryAction(preferredVersionId = \"\")", "function parsePolicyJsonField(rawValue, label = \"策略 JSON\")");
const playbook = extractBetween(APP, "function renderPlaybookScreen()", "function renderProductionScreen()");
const actions = extractBetween(APP, "document.addEventListener(\"click\", async (event) => {", "document.addEventListener(\"submit\", async (event) => {");
assert.match(playbookFocusHelper, /appState\.playbookDetailTab = "workspace"/);
assert.match(playbookFocusHelper, /setScreen\("playbook"\)/);
assert.match(playbookFocusHelper, /scrollIntoView/);
assert.match(profile, /focusPlaybookOneLinerWorkspace\("oneliner-profile-anchor"\)/);
assert.match(APP, /function resolvePreferredVersionId\(history, preferredVersionId = ""\)/);
assert.match(profileHistory, /\/v2\/oneliner\/profile\/versions/);
assert.match(profileHistory, /\/v2\/oneliner\/profile\/audits/);
assert.match(profileHistory, /\/v2\/oneliner\/profile\/rollback/);
assert.match(profileHistory, /resolvePreferredVersionId\(history, preferredVersionId\)/);
assert.match(profileHistory, /hideSubmit:\s*!selectedVersionId/);
assert.match(profileHistory, /focusPlaybookOneLinerWorkspace\("oneliner-profile-anchor"\)/);
assert.match(playbook, /open-oneliner-profile-history/);
assert.match(playbook, /id="oneliner-profile-anchor"/);
assert.match(actions, /name === "open-oneliner-profile-history"/);
assert.match(actions, /openOneLinerProfileHistoryAction\(action\.dataset\.versionId \|\| ""\)/);
});
@@ -717,11 +725,19 @@ test("admin governance actions apply local permission and empty-directory guards
});
test("user governance UI exposes personal history and rollback entrypoints", () => {
const helpers = extractBetween(APP, "function ensureAdminGovernanceAccess()", "function openSystemMainPolicyAction() {");
const playbook = extractBetween(APP, "function renderPlaybookScreen()", "function renderProductionScreen()");
const strategy = extractBetween(APP, "function renderStrategyScreen()", "function renderCreditsScreen()");
const automation = extractBetween(APP, "function renderAutomationScreen()", "function renderOwnedScreen()");
const actions = extractBetween(APP, "document.addEventListener(\"click\", async (event) => {", "document.addEventListener(\"submit\", async (event) => {");
const userGlobal = extractBetween(APP, "function openUserGlobalPolicyAction()", "function openUserPlatformPolicyAction(platform) {");
const userPlatform = extractBetween(APP, "function openUserPlatformPolicyAction(platform)", "async function openUserGlobalPolicyHistoryAction(preferredVersionId = \"\")");
const userGlobalHistory = extractBetween(APP, "async function openUserGlobalPolicyHistoryAction(preferredVersionId = \"\")", "async function openUserPlatformPolicyHistoryAction(platform, preferredVersionId = \"\")");
const userPlatformHistory = extractBetween(APP, "async function openUserPlatformPolicyHistoryAction(platform, preferredVersionId = \"\")", "function focusAdminGovernanceAgentsWorkspace(anchorId = \"admin-governance-anchor\") {");
assert.match(helpers, /function focusUserGovernanceWorkspace\(tab = "effective", anchorId = "strategy-governance-anchor"\)/);
assert.match(helpers, /appState\.strategyDetailTab = tab/);
assert.match(helpers, /setScreen\("strategy"\)/);
assert.match(playbook, /open-user-global-policy-history/);
assert.match(playbook, /open-user-platform-policy-history/);
assert.match(playbook, /handoff-to-main-agent/);
@@ -730,8 +746,13 @@ test("user governance UI exposes personal history and rollback entrypoints", ()
assert.match(strategy, /管理员覆盖生效中/);
assert.match(strategy, /handoff-to-main-agent/);
assert.match(strategy, /strategy-main-agent-handoff/);
assert.match(strategy, /id="strategy-governance-anchor"/);
assert.match(automation, /handoff-to-main-agent/);
assert.match(automation, /automation-main-agent-handoff/);
assert.match(userGlobal, /focusUserGovernanceWorkspace\("global", "strategy-governance-anchor"\)/);
assert.match(userPlatform, /focusUserGovernanceWorkspace\("platform", "strategy-governance-anchor"\)/);
assert.match(userGlobalHistory, /focusUserGovernanceWorkspace\("global", "strategy-governance-anchor"\)/);
assert.match(userPlatformHistory, /focusUserGovernanceWorkspace\("platform", "strategy-governance-anchor"\)/);
assert.match(actions, /name === "open-user-global-policy-history"/);
assert.match(actions, /name === "open-user-platform-policy-history"/);
@@ -744,8 +765,11 @@ test("admin override actions guard against missing governance targets", () => {
assert.match(helpers, /function ensureAdminOverrideTargetReady\(target\)/);
assert.match(helpers, /当前治理目录里还没有可选用户/);
assert.match(helpers, /function focusAdminGovernanceAuditWorkspace\(anchorId = "admin-override-audit-anchor"\)/);
assert.match(override, /if \(!ensureAdminOverrideTargetReady\(target\)\) return;/);
assert.match(overrideHistory, /if \(!ensureAdminOverrideTargetReady\(target\)\) return;/);
assert.match(override, /focusAdminGovernanceAuditWorkspace\("admin-override-audit-anchor"\)/);
assert.match(overrideHistory, /focusAdminGovernanceAuditWorkspace\("admin-override-audit-anchor"\)/);
});
test("main agent result rendering offers a direct route back into the recommended screen", () => {