Skip to content
Open
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
5 changes: 5 additions & 0 deletions .changeset/tall-maps-stay-durable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@sapiom/harness": patch
---

Remove the older-server project graph fallback. Project clicks now open the durable Agent Map or offer identity recovery without selecting or creating a conversation. Ordinary sessions retain their independent Canvas and Steps views.
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,19 @@ patch; the combined Harness release takes the higher minor bump.
| Missing project identity, ambiguous scope, unsafe path or unavailable catalog | Show an unavailable Agent Map with a project-catalog retry. Keep ordinary sessions and per-agent Canvas reachable through explicit selection. Retry promotes only an exact server-issued workspace-key/project-ID association. |
| Selected durable map disappears from the catalog | Keep that selected ID and offer catalog retry. Explicit agent/session selection still opens its ordinary Canvas/Steps. |
| Current server receives old graph GET, refresh or navigation | Boot token remains required; authenticated requests receive 410 `legacy_graph_retired` before scope resolution, graph reads or watcher activation. No legacy graph owners are retained. |
| Older server omits `studioProjects` entirely | Temporary browser protocol compatibility only. `WorkspaceGraphView`, its loader and announcements remain for this older payload until SAP-3090. An empty list is not this protocol. |
| Older server omits `studioProjects` entirely | The browser offers the same identity recovery, preserving the selected project and conversation. There is no fallback renderer or implicit session handoff. Ordinary session tabs remain available. |

Current-server graph events are ignored before browser state, cache invalidation
Old graph events are ignored before browser state, cache invalidation
or other refresh handlers run. Shared discovery, accepted source evidence,
PackageInventory, rail launch edges, ordinary sessions and each agent's
Canvas/Steps retain their own consumers; they are not legacy project topology.

SAP-3090 first disconnects `WorkspaceGraphView` from the shell and removes the
older-protocol session handoff. The following layer deletes its now-unreachable
browser modules. `agent-map-authority.spec.ts` includes omitted-catalog recovery
and exact keyboard tabs; `project-altitude.spec.ts` preserves pane geometry,
Steps restoration, independent disclosure and map/agent Back/Forward navigation.

## Evidence required before browser deletion

Attach results to SAP-3089 at the reviewed PR head. Do not treat the presence of
Expand Down
9 changes: 5 additions & 4 deletions packages/harness/web/e2e/agent-map-authority.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { expect, test, type Page } from "@playwright/test";

type Probe = {
identity: "ready" | "missing-id" | "missing-project";
identity: "ready" | "missing-id" | "missing-project" | "older-protocol";
reads: number;
refreshes: number;
navigation: number;
Expand Down Expand Up @@ -91,6 +91,7 @@ MockApi.prototype.getState = async function() {
const state = await stateRead.call(this);
authority.projects = Object.fromEntries(state.studioProjects.map(p => [p.displayName, p.projectId]));
if (identity === "missing-project") state.studioProjects = [];
if (identity === "older-protocol") delete state.studioProjects;
if (identity === "missing-id") {
state.workspaceScopes = state.workspaceScopes.map(({ projectId, ...scope }) => scope);
}
Expand Down Expand Up @@ -153,8 +154,8 @@ async function evidence(page: Page) {
});
}

for (const identity of ["missing-id", "missing-project"] as const) {
test(`current project with ${identity} offers identity recovery without legacy fallback or session actions`, async ({
for (const identity of ["missing-id", "missing-project", "older-protocol"] as const) {
test(`project with ${identity} offers identity recovery without legacy fallback or session actions`, async ({
page,
}) => {
await open(page, identity);
Expand Down Expand Up @@ -219,7 +220,7 @@ test("recovering another project cannot restore the active conversation's projec
expect(await evidence(page)).toEqual(before);
});

for (const identity of ["missing-id", "missing-project"] as const) {
for (const identity of ["missing-id", "missing-project", "older-protocol"] as const) {
test(`keyboard session selection matches the visible unresolved project's tabs with ${identity}`, async ({
page,
}) => {
Expand Down
2 changes: 1 addition & 1 deletion packages/harness/web/e2e/agent-map-navigation.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ for (const boundWorkflowPath of ["/Users/demo/acme-app/leasing", null]) {
test(`ending a session retains its own Canvas with binding ${boundWorkflowPath}`, async ({
page,
}) => {
await page.goto("/?seed=0&mockStudioProjects=absent");
await page.goto("/?seed=0&mockStudioProjects=present");
await expect(page.getByTestId("session-context")).toBeVisible();
await updateSession(page, "sess-boot", { boundWorkflowPath });
await page.getByTestId("session-tab-main-sess-boot").click();
Expand Down
22 changes: 0 additions & 22 deletions packages/harness/web/e2e/group-axis.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,28 +132,6 @@ async function dragAgent(
}

test.describe("derivation", () => {
test("project selection opens its graph without folding the Group axis", async ({
page,
}) => {
const project = page.getByTestId(POLSIA);
await expect(project.getByTestId("group-agent-gateway")).toBeVisible();

await page.getByTestId("project-select-polsia").click();

await expect(page.getByTestId("workspace-graph-view")).toBeVisible();
await expect(page.getByTestId("system-graph-node-gateway")).toBeVisible();
await expect(project.getByTestId("group-agent-gateway")).toBeVisible();
await expect(page.getByTestId("project-row-polsia")).toHaveClass(
/is-selected/,
);

await page.getByTestId("system-graph-node-gateway").click();
await expect(page.getByTestId("workspace-graph-view")).toHaveCount(0);
await expect(
project.getByTestId("group-agent-gateway").locator(".workflow-item"),
).toHaveClass(/is-focused/);
});

test("launch-connected agents form one group named for its HEAD, with Ungrouped last", async ({
page,
}) => {
Expand Down
11 changes: 6 additions & 5 deletions packages/harness/web/e2e/mobile.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,17 +104,18 @@ test("right pane opens as a bottom sheet and dismisses from its own collapse con
await expect(pane).toHaveCount(1);
});

test("a workspace graph opens in the right sheet, over a workbench that is still there", async ({
test("Agent Map opens in the right sheet, over a workbench that is still there", async ({
page,
}) => {
await page.goto("/?seed=0&mockFixtures=deep&mockStudioProjects=present&mockAgentMapGolden=1");
// It used to be a full-main destination that hid BOTH panes — the mode
// switch SAP-2980 removes. On mobile the map is the right pane's map, so it
// arrives in the sheet, and the conversation is one dismissal away rather
// than gone.
await page.getByTestId("rail-expand").click();
await page.getByTestId("project-select-acme-app").click();

const graph = page.getByTestId("workspace-graph-view");
const graph = page.getByTestId("agent-map-frame");
await expect(graph).toBeVisible();
await expect(page.locator(".rail-workflows")).toHaveCount(0);
await expect(page.locator(".right-pane")).toBeVisible();
Expand All @@ -137,7 +138,7 @@ test("a workspace graph opens in the right sheet, over a workbench that is still
expect((bounds?.y ?? 0) + (bounds?.height ?? 0)).toBe(812);

const controls = await page
.getByTestId("system-graph-controls")
.getByRole("group", { name: "Agent Map view controls" })
.boundingBox();
expect((controls?.x ?? -1) + (controls?.width ?? 0)).toBeLessThanOrEqual(375);
expect((controls?.y ?? -1) + (controls?.height ?? 0)).toBeLessThanOrEqual(
Expand All @@ -149,12 +150,12 @@ test("a workspace graph opens in the right sheet, over a workbench that is still
});
expect(overflow).toBe(0);
await page.screenshot({
path: "web/e2e/screenshots/mobile-workspace-graph.png",
path: "web/e2e/screenshots/mobile-agent-map.png",
});

// Drilling into a node cuts to board altitude; the sheet's own collapse
// control then hands the whole screen back to the conversation.
await page.getByTestId("system-graph-node-leasing").click();
await page.getByTestId("agent-map-node-node_00000000-0000-7000-8000-000000000101").click();
await expect(graph).toHaveCount(0);
await page.getByTestId("right-collapse").click();
await expect(page.locator(".center-pane")).toBeVisible();
Expand Down
146 changes: 0 additions & 146 deletions packages/harness/web/e2e/polsia-workspace.spec.ts

This file was deleted.

Loading
Loading