feat: tighten main agent execution traceability
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 06:23:17 +08:00
parent 895e3f3b13
commit 53b1854c21
7 changed files with 72 additions and 7 deletions

View File

@@ -913,6 +913,9 @@ function ensureActionUi() {
function renderActionFields(fields) {
return fields.map((field) => {
if (field.hidden) {
return "";
}
const common = `data-action-field="${escapeHtml(field.name)}"`;
if (field.type === "html") {
return `
@@ -1360,6 +1363,8 @@ function renderOneLinerMessagesHtml() {
${executionCard.platform_agent_name ? `<span class="tag">${escapeHtml(executionCard.platform_agent_name)}</span>` : ""}
${executionCard.assistant_name ? `<span class="tag green">${escapeHtml(executionCard.assistant_name)}</span>` : ""}
${profileVersion.version_no ? `<span class="tag">配置 v${escapeHtml(formatNumber(profileVersion.version_no || 0))}</span>` : ""}
${profileVersion.version_no ? `<span class="tag clickable-tag" data-action="open-oneliner-profile-history">看主配置历史</span>` : ""}
${executionCard.platform && executionCard.platform_agent_profile?.version_no ? `<span class="tag clickable-tag" data-action="open-platform-agent-profile-history" data-platform="${escapeHtml(executionCard.platform)}">看平台配置历史</span>` : ""}
${executionCard.readiness_label ? `<span class="tag ${executionCard.readiness_score >= 75 ? "green" : executionCard.readiness_score >= 50 ? "blue" : "orange"}">${escapeHtml(executionCard.readiness_label)} ${escapeHtml(formatNumber(executionCard.readiness_score || 0))}</span>` : ""}
${executionCard.primary_action?.key ? `<span class="tag clickable-tag" data-action="${escapeHtml(executionCard.primary_action.key)}">${escapeHtml(executionCard.primary_action.label || "执行下一步")}</span>` : ""}
</div>
@@ -2020,6 +2025,7 @@ function renderOneLinerExecutionPayloadHtml(payload) {
${platformAgentProfile.name ? `<span class="tag">${escapeHtml(platformAgentProfile.name)}</span>` : ""}
${platformAgentProfile.assistant_name ? `<span class="tag green">${escapeHtml(platformAgentProfile.assistant_name)}</span>` : ""}
${platformAgentProfile.version_no ? `<span class="tag">${escapeHtml(platformLabel(platformAgentProfile.platform || payload.platform || ""))} Agent v${escapeHtml(formatNumber(platformAgentProfile.version_no || 0))}</span>` : ""}
${platformAgentProfile.platform && platformAgentProfile.version_no ? `<span class="tag clickable-tag" data-action="open-platform-agent-profile-history" data-platform="${escapeHtml(platformAgentProfile.platform)}">看平台配置历史</span>` : ""}
${platformAgentProfile.readiness_label ? `<span class="tag ${platformAgentProfile.readiness_score >= 75 ? "green" : platformAgentProfile.readiness_score >= 50 ? "blue" : "orange"}">${escapeHtml(platformAgentProfile.readiness_label)} ${escapeHtml(formatNumber(platformAgentProfile.readiness_score || 0))}</span>` : ""}
</div>
</div>
@@ -2728,6 +2734,9 @@ async function refreshTrackedAccountAction(trackedAccountId) {
payload
);
await bootstrap();
if (payload.sync_job_id) {
openJobDetailAction(payload.sync_job_id);
}
} finally {
setBusy(false, "");
}
@@ -3209,6 +3218,7 @@ function openDashboardProjectSwitcher() {
}
const selectedProject = getSelectedProject();
const projects = safeArray(appState.dashboard?.projects);
const isMobileViewport = typeof window !== "undefined" && window.matchMedia?.("(max-width: 760px)")?.matches;
const projectCards = projects.map((project) => {
const stats = getProjectStats(project.id);
const reviewCount = getProjectReviews(project.id).length;
@@ -3259,11 +3269,10 @@ function openDashboardProjectSwitcher() {
</div>
`
},
{ name: "projectId", label: "当前项目", type: "select", value: getSelectedProject()?.id || "", options }
{ name: "projectId", label: "当前项目", type: "select", value: getSelectedProject()?.id || "", options, hidden: isMobileViewport }
],
onOpen: ({ fields, submit }) => {
const select = fields.querySelector('[data-action-field="projectId"]');
const isMobileViewport = typeof window !== "undefined" && window.matchMedia?.("(max-width: 760px)")?.matches;
if (submit && isMobileViewport) {
submit.hidden = true;
}

View File

@@ -138,12 +138,14 @@ test("mobile project sheets support direct project picking and zoom-safe form co
const createProject = extractBetween(APP, "async function createProject()", "function openPreferredModelAction()");
assert.match(APP, /async function applySelectedProject\(projectId = ""\)/);
assert.match(projectSwitcher, /data-project-choice=/);
assert.match(projectSwitcher, /hidden:\s*isMobileViewport/);
assert.match(projectSwitcher, /onOpen:\s*\(/);
assert.match(projectSwitcher, /select\.value = nextProjectId/);
assert.match(projectSwitcher, /window\.matchMedia\?\.\("\(max-width: 760px\)"\)\?\.matches/);
assert.match(projectSwitcher, /submit\.hidden = true/);
assert.match(projectSwitcher, /closeActionModal\(\);/);
assert.match(projectSwitcher, /await applySelectedProject\(nextProjectId\);/);
assert.match(APP, /if \(field\.hidden\) \{\s*return "";/);
assert.match(applySelectedProject, /loadStorageStatus\(appState\.selectedProjectId \|\| ""\)/);
assert.match(applySelectedProject, /loadAgentControlSurfaces\(appState\.selectedProjectId \|\| ""\)/);
assert.match(createProject, /onOpen:\s*\(/);
@@ -832,6 +834,21 @@ test("key workbench screens expose contextual handoff-to-main-agent actions", ()
assert.match(review, /sourceScreen: "review"/);
});
test("tracked-account refresh opens the created sync task when the backend returns one", () => {
const refresh = extractBetween(APP, "async function refreshTrackedAccountAction(trackedAccountId)", "function getSelectedProject()");
assert.match(refresh, /sync_job_id/);
assert.match(refresh, /openJobDetailAction\(payload\.sync_job_id\)/);
});
test("main agent execution cards can jump to oneliner and platform profile history", () => {
const messages = extractBetween(APP, "function renderOneLinerMessagesHtml()", "function renderAutoConnectingScreen(screenTitle, nextStepText)");
assert.match(messages, /data-action="open-oneliner-profile-history"/);
assert.match(messages, /data-action="open-platform-agent-profile-history"/);
assert.match(APP, /function renderOneLinerExecutionPayloadHtml\(payload\)/);
assert.match(APP, /data-action="open-oneliner-profile-history"/);
assert.match(APP, /data-action="open-platform-agent-profile-history"/);
});
test("oneliner runtime shows grouped run health summary above the current run card", () => {
const runtime = extractBetween(APP, "function renderOneLinerRunsHtml()", "function renderOneLinerMessagesHtml()");
assert.match(runtime, /近期运行概况/);