策略治理
@@ -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");
}
});
}
diff --git a/web/storyforge-web-v4/tests/workbench-pages.test.mjs b/web/storyforge-web-v4/tests/workbench-pages.test.mjs
index c757a61..c9fee39 100644
--- a/web/storyforge-web-v4/tests/workbench-pages.test.mjs
+++ b/web/storyforge-web-v4/tests/workbench-pages.test.mjs
@@ -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", () => {