Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export async function verifyWorkspaceLocales({ browser, url, installApi, outputD
await page.getByRole("radio", { name: /Simplified Chinese/ }).click();
assert.equal(await page.evaluate(() => localStorage.getItem("loopx-pw-locale")), "zh-CN");
await page.reload({ waitUntil: "networkidle" });
await page.getByRole("button", { name: "返回工作区", exact: true }).click();
await page.getByTestId("personal-goal-home").waitFor();
assert.equal(await page.locator("html").getAttribute("lang"), "zh-CN");
assert.match(await page.getByRole("region", { name: "控制面来源" }).innerText(), /本机/);
Expand All @@ -105,6 +106,7 @@ export async function verifyWorkspaceLocales({ browser, url, installApi, outputD
await page.getByRole("button", { name: /语言/ }).click();
await page.getByRole("radio", { name: /English/ }).click();
await page.reload({ waitUntil: "networkidle" });
await page.getByRole("button", { name: "Back to workspace", exact: true }).click();
await page.getByTestId("personal-goal-home").waitFor();
assert.equal(await page.locator("html").getAttribute("lang"), "en");
assert.equal(await page.evaluate(() => localStorage.getItem("loopx-pw-locale")), "en");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1189,8 +1189,13 @@ export function PersonalWorkspacePage({
setSelection(target);
}
useEffect(() => {
const restore = () => setSelectionState({scope: currentSelectionScope.current.scope,
value: readSettingsRoute(new URL(window.location.href))});
const restore = () => {
const target = readSettingsRoute(new URL(window.location.href));
// Task history has its own route reader. Leaving settings may clear its
// selection, but an unrelated history event must not clear a restored task.
setSelectionState(current => target ? {scope: currentSelectionScope.current.scope, value: target}
: current?.value?.kind === "settings" ? null : current);
};
window.addEventListener("popstate", restore);
return () => window.removeEventListener("popstate", restore);
}, []);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,11 @@ export const agentModelSelectionScenario = {
await assertReadableHeader();
assert.equal(discoveryCount, 0, "The steward binding does not start optional catalog discovery");
await managerControl.click();
assert.equal(await page.locator(".personal-settings-tabs").getByRole("button", {name: "管家", exact: true}).getAttribute("aria-current"), "page");
const settings = page.getByRole("region", {name: "设置", exact: true});
await settings.getByRole("heading", {name: "管家", exact: true}).waitFor();
assert.equal(await settings.getByRole("radio", {name: "本机设置", exact: true}).isChecked(), true);
assert.equal(await settings.locator(".personal-settings-mobile-category select").inputValue(), "steward",
"The phone model entry opens the machine-owned steward category");
await page.getByRole("button", {name: "返回工作区", exact: true}).click();
await page.reload({waitUntil: "networkidle"});
await managerControl.filter({hasText: managerBinding.model}).waitFor();
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ export const exploreCompositionOwnerScenario = {
const { page, errors } = context;
await page.getByRole("button", { name: "设置", exact: true }).click();
await page.locator(".personal-settings-tabs").getByRole("button", { name: "能力中心", exact: true }).click();
await page.getByRole("radio", { name: "单个 Goal", exact: true }).check();
await page.getByRole("radio", { name: "Goal 设置", exact: true }).check();
await page.getByRole("combobox", { name: "目标 Goal", exact: true }).selectOption(GOAL);
const catalog = page.getByRole("navigation", { name: "Goal 能力目录" });
const openExplore = async () => {
Expand Down
15 changes: 14 additions & 1 deletion examples/personal-workspace-browser/goal-work-map.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,14 @@ export const goalWorkMapScenario = {
assert.equal(await canvas.locator('.work-map-node[aria-pressed="true"]').count(), 0,
"Closing details clears the shared task selection");
assert.equal(new URL(page.url()).searchParams.get("todo"), null, "Closing details clears the task route");
await page.goBack({waitUntil: "domcontentloaded"});
await drawer.getByText(finalRequirement, {exact: true}).waitFor();
assert.equal(new URL(page.url()).searchParams.get("todo"), "todo_map_reserve");
assert.deepEqual(await drawer.locator(".personal-task-request .personal-md > p").allTextContents(), requestParagraphs,
"Back restores the same complete request through its native owner");
await page.goForward({waitUntil: "domcontentloaded"});
await drawer.waitFor({state: "hidden"});
assert.equal(new URL(page.url()).searchParams.get("todo"), null);

const hiddenRegistry = `${authority.registry}.hidden`;
const errorsBeforeLoss = desktop.errors.length;
Expand All @@ -198,7 +206,12 @@ export const goalWorkMapScenario = {
await page.getByRole("button", { name: /关闭详情/ }).click();

limits = { omitted_node_count: 3, topology_complete: false };
await page.getByRole("button", { name: "刷新快照", exact: true }).click();
const evidence = page.locator(".goal-overview-evidence");
if (await evidence.getAttribute("open") === null) {
await evidence.locator(":scope > summary").focus();
await page.keyboard.press("Enter");
}
await evidence.getByRole("button", { name: "刷新快照", exact: true }).click();
await map.getByText("部分工作未出现在此地图中。").waitFor();
assert.equal(await page.locator("[role=alert]", { hasText: "工作区状态已在此快照之后变化" }).count(), 0);
assert.ok(reads.length <= 4, `Delivery review re-read ${reads.length} times`);
Expand Down
7 changes: 7 additions & 0 deletions examples/personal-workspace-browser/goal-workspace-m2.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ export const goalWorkspaceM2Scenario = {
await page.locator('.personal-context-drawer').waitFor();
await now.locator('[data-todo-id="showcase-reconcile"][aria-pressed="true"]').waitFor();
assert.equal(await now.locator('[data-todo-id="showcase-reconcile"]').getAttribute('aria-pressed'),'true');
await page.screenshot({path:resolve(outputDir,'task-history-restored-desktop.png'),animations:'disabled'});
await page.goForward({waitUntil:"domcontentloaded"});
await page.waitForURL(value => !value.searchParams.has("todo"));
await page.locator('.personal-context-drawer').waitFor({state:"hidden"});
Expand All @@ -96,6 +97,11 @@ export const goalWorkspaceM2Scenario = {
await page.screenshot({path:resolve(outputDir,'goal-workspace-m2-mobile.png'),animations:'disabled'});
// An enabled contract uses the native acceptance disclosure; the
// fallback direction button only exists without a contract or plan.
const evidence = page.locator(".goal-overview-evidence");
if (await evidence.getAttribute("open") === null) {
await evidence.locator(":scope > summary").focus();
await page.keyboard.press("Enter");
}
const inspection = page.locator(".goal-overview .delivery-check-inspection");
const criteria = inspection.locator(".goal-overview-criteria");
await page.locator(".goal-overview .delivery-acceptance-contract .goal-overview-objective").waitFor({state:"visible"});
Expand All @@ -120,6 +126,7 @@ export const goalWorkspaceM2Scenario = {
await railDialog.waitFor({state:"hidden"});
await page.locator('.personal-context-drawer').waitFor();
assert.equal(new URL(page.url()).searchParams.get("todo"),"showcase-map-columns");
await page.screenshot({path:resolve(outputDir,'task-history-restored-narrow.png'),animations:'disabled'});
await page.locator('.personal-drawer-close').click();
await page.setViewportSize({width:1440,height:1000});
scale = true;
Expand Down
9 changes: 6 additions & 3 deletions examples/personal-workspace-browser/lark-cli-missing.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,12 @@ export const larkCliMissingScenario = {
// With lark-cli available again the same entries stay usable.
await page.unroute(larkReads, answerCliMissing);
await page.reload({ waitUntil: "networkidle" });
await page.getByTestId("personal-goal-home").waitFor({ state: "visible" });
await page.getByRole("button", { name: "设置", exact: true }).click();
await page.getByRole("button", { name: "Lark", exact: true }).click();
const restoredSettings = page.getByRole("region", { name: "设置", exact: true });
await restoredSettings.waitFor({ state: "visible" });
if (!await restoredSettings.getByRole("radio", { name: "本机设置", exact: true }).isChecked()) {
throw new Error("Reload did not retain the explicit device settings scope");
}
await restoredSettings.getByRole("button", { name: "Lark", exact: true }).click();
await page.locator(".personal-lark-tabs").getByRole("button", { name: /^Lark Apps/u }).click();
if (await page.getByRole("button", { name: "新建 Lark App" }).isDisabled()) {
throw new Error("New Lark App stayed disabled with lark-cli available");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const prReviewAgentOrderScenario = {
const {page} = context;
await page.getByRole("button", {name: "设置", exact: true}).click();
await page.locator(".personal-settings-tabs").getByRole("button", {name: "能力中心", exact: true}).click();
await page.getByRole("radio", {name: "单个 Goal", exact: true}).check();
await page.getByRole("radio", {name: "Goal 设置", exact: true}).check();
await page.getByRole("combobox", {name: "目标 Goal", exact: true}).selectOption("product-release");
await page.getByRole("navigation", {name: "Goal 能力目录"}).getByRole("button", {name: /Pull-request Review/}).click();
const detail = page.locator(".personal-capability-detail");
Expand Down
39 changes: 17 additions & 22 deletions examples/personal-workspace-browser/replan-cadence.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,13 @@ export const replanCadenceScenario = {
if (!settled.ok()) throw new Error(await settled.text());
}

async function openMachineCadence() {
await page.getByRole("button", { name: "设置", exact: true }).click();
async function selectMachineCadence() {
await page.getByRole("radio", { name: "本机设置", exact: true }).check();
await page.locator(".personal-settings-tabs").getByRole("button", { name: "能力中心", exact: true }).click();
await page.getByRole("navigation", { name: "机器能力目录" }).getByRole("button", { name: /Goal 复盘与步幅/ }).click();
}
await openMachineCadence();
await page.getByRole("button", { name: "设置", exact: true }).click();
await selectMachineCadence();
const unit = page.getByLabel(/^复核计数依据/);
const count = page.getByLabel("两次复核间的数量", { exact: true });
const strategy = page.getByLabel(/^步幅策略/);
Expand All @@ -90,7 +91,7 @@ export const replanCadenceScenario = {
const preview = await request(base + "/preview", legacy);
await request(base + "/apply", { ...legacy, expected_plan_revision: preview.plan_revision });
await page.reload({ waitUntil: "networkidle" });
await openMachineCadence();
await selectMachineCadence();
await waitForInputValue(count, "2");
if (await unit.inputValue() !== "completed_todos" || await count.inputValue() !== "2") throw new Error("Legacy cadence was reinterpreted");
let stored = (await request(base)).machine_configuration.namespaces.todo_replan_cadence;
Expand All @@ -110,7 +111,7 @@ export const replanCadenceScenario = {
if (stored.count_unit !== "effective_turns" || stored.count !== 3 || "completed_todos" in stored) throw new Error("Migration did not persist the selected unit");
if (stored.stride_strategy !== "evidence_conditioned_v1" || stored.schema_version !== "todo_replan_cadence_machine_defaults_v2") throw new Error("Machine stride version not recorded");
await page.screenshot({ path: resolve(outputDir, "replan-cadence-machine.png"), animations: "disabled" });
await page.getByRole("radio", { name: "单个 Goal", exact: true }).check();
await page.getByRole("radio", { name: "Goal 设置", exact: true }).check();
await page.getByRole("combobox", { name: "目标 Goal", exact: true }).selectOption("multi-agent-projection");
await page.getByRole("navigation", { name: "Goal 能力目录" }).getByRole("button", { name: /Goal 复盘与步幅/ }).click();
await waitForInputValue(count, "3");
Expand Down Expand Up @@ -148,11 +149,15 @@ export const replanCadenceScenario = {
}
async function reopenGoalCadence() {
await page.reload({ waitUntil: "networkidle" });
await page.getByRole("button", { name: "设置", exact: true }).click();
await page.locator(".personal-settings-tabs").getByRole("button", { name: "能力中心", exact: true }).click();
await page.getByRole("radio", { name: "单个 Goal", exact: true }).check();
await page.getByRole("combobox", { name: "目标 Goal", exact: true }).selectOption("multi-agent-projection");
await page.getByRole("navigation", { name: "Goal 能力目录" }).getByRole("button", { name: /Goal 复盘与步幅/ }).click();
const english = await page.locator("html").getAttribute("lang") === "en";
const settings = page.getByRole("region", { name: english ? "Settings" : "设置", exact: true });
await settings.waitFor();
if (!await settings.getByRole("radio", { name: english ? "One Goal" : "Goal 设置", exact: true }).isChecked()
|| await settings.getByRole("combobox", { name: english ? "Target Goal" : "目标 Goal", exact: true }).inputValue() !== "multi-agent-projection") {
throw new Error("Reload did not restore the explicit Goal settings target");
}
await settings.getByRole("navigation", { name: english ? "Goal capability catalog" : "Goal 能力目录" })
.getByRole("button", { name: english ? /Goal review and stride/ : /Goal 复盘与步幅/ }).click();
}
// Default context is visible to the Agent without an owner setup step.
// Advanced opt-out persists without pinning cadence or changing stride.
Expand Down Expand Up @@ -270,12 +275,7 @@ export const replanCadenceScenario = {
if (await page.evaluate(() => document.documentElement.scrollWidth > innerWidth + 1)) throw new Error("Cadence editor overflowed");
await page.setViewportSize({ width: 1512, height: 982 });
await page.evaluate(() => localStorage.setItem("loopx-pw-locale", "en"));
await page.reload({ waitUntil: "networkidle" });
await page.getByRole("button", { name: "Settings", exact: true }).click();
await page.locator(".personal-settings-tabs").getByRole("button", { name: "Capability Center", exact: true }).click();
await page.getByRole("radio", { name: "One Goal", exact: true }).check();
await page.getByRole("combobox", { name: "Target Goal", exact: true }).selectOption("multi-agent-projection");
await page.getByRole("navigation", { name: "Goal capability catalog" }).getByRole("button", { name: /Goal review and stride/ }).click();
await reopenGoalCadence();
const englishUnit = page.getByLabel(/^Review after/);
const englishCount = page.getByLabel("Number between reviews", { exact: true });
const englishStrategy = page.getByLabel(/^Stride strategy/);
Expand All @@ -296,12 +296,7 @@ export const replanCadenceScenario = {
await request(base + "/apply", { ...remove, expected_plan_revision: removalPreview.plan_revision });
const inherited = (await readGoalCadence()).effective_configuration;
if (inherited.source !== "capability_default" || inherited.configuration.count_unit !== "effective_turns" || inherited.configuration.count !== 6) throw new Error("Removing device policy did not restore product default");
await page.reload({ waitUntil: "networkidle" });
await page.getByRole("button", { name: "Settings", exact: true }).click();
await page.locator(".personal-settings-tabs").getByRole("button", { name: "Capability Center", exact: true }).click();
await page.getByRole("radio", { name: "One Goal", exact: true }).check();
await page.getByRole("combobox", { name: "Target Goal", exact: true }).selectOption("multi-agent-projection");
await page.getByRole("navigation", { name: "Goal capability catalog" }).getByRole("button", { name: /Goal review and stride/ }).click();
await reopenGoalCadence();
await waitForInputValue(englishCount, "6");
if (await englishUnit.inputValue() !== "effective_turns" || await englishStrategy.inputValue() !== "off") throw new Error("Goal editor did not restore product defaults");
await englishCount.fill("5");
Expand Down
Loading
Loading