From cab477b541b0485f22a4948075d2921ba1a3434c Mon Sep 17 00:00:00 2001 From: Yash Date: Wed, 9 Sep 2026 23:10:11 +0000 Subject: [PATCH 1/6] refactor(harness): delete retired server graph topology (SAP-3091) --- packages/harness/README.md | 5 +- packages/harness/docs/agent-map-api.md | 40 + .../harness/docs/workspace-system-graph.md | 232 --- .../system-graph-workspace/growth/index.ts | 3 - .../system-graph-workspace/research/index.ts | 12 - .../src/core/canvas-interconnections.ts | 2 +- .../src/core/system-graph-inventory.test.ts | 1402 ---------------- .../src/core/system-graph-inventory.ts | 1033 ------------ .../core/system-graph-relationships.test.ts | 590 ------- .../src/core/system-graph-relationships.ts | 522 ------ .../src/core/system-graph-store.test.ts | 578 ------- .../harness/src/core/system-graph-store.ts | 484 ------ .../src/core/system-graph-watcher.test.ts | 657 -------- .../harness/src/core/system-graph-watcher.ts | 169 -- .../harness/src/core/system-graph.test.ts | 1423 ----------------- packages/harness/src/core/system-graph.ts | 524 ------ packages/harness/src/server/events-ws.test.ts | 27 - .../harness/src/server/system-graph.test.ts | 311 ---- packages/harness/src/server/system-graph.ts | 117 -- packages/harness/src/shared/system-graph.ts | 78 - packages/harness/src/shared/types.ts | 11 - .../web/src/lib/bus-message-type.test.ts | 26 + .../harness/web/src/lib/bus-message-type.ts | 30 + packages/harness/web/src/lib/events.test.ts | 37 + packages/harness/web/src/lib/events.ts | 10 +- .../harness/web/src/lib/use-harness-state.ts | 1 - .../agent-studio-terminology-allowlist.json | 7 + 27 files changed, 150 insertions(+), 8181 deletions(-) create mode 100644 packages/harness/docs/agent-map-api.md delete mode 100644 packages/harness/docs/workspace-system-graph.md delete mode 100644 packages/harness/src/core/__fixtures__/system-graph-workspace/growth/index.ts delete mode 100644 packages/harness/src/core/__fixtures__/system-graph-workspace/research/index.ts delete mode 100644 packages/harness/src/core/system-graph-inventory.test.ts delete mode 100644 packages/harness/src/core/system-graph-inventory.ts delete mode 100644 packages/harness/src/core/system-graph-relationships.test.ts delete mode 100644 packages/harness/src/core/system-graph-relationships.ts delete mode 100644 packages/harness/src/core/system-graph-store.test.ts delete mode 100644 packages/harness/src/core/system-graph-store.ts delete mode 100644 packages/harness/src/core/system-graph-watcher.test.ts delete mode 100644 packages/harness/src/core/system-graph-watcher.ts delete mode 100644 packages/harness/src/core/system-graph.test.ts delete mode 100644 packages/harness/src/core/system-graph.ts delete mode 100644 packages/harness/src/server/system-graph.test.ts delete mode 100644 packages/harness/src/server/system-graph.ts delete mode 100644 packages/harness/src/shared/system-graph.ts create mode 100644 packages/harness/web/src/lib/bus-message-type.test.ts create mode 100644 packages/harness/web/src/lib/bus-message-type.ts create mode 100644 packages/harness/web/src/lib/events.test.ts diff --git a/packages/harness/README.md b/packages/harness/README.md index b0abd1b04..0b7cff826 100644 --- a/packages/harness/README.md +++ b/packages/harness/README.md @@ -353,9 +353,8 @@ HTTP contracts that need more than a type to use are written up under `docs/`: - [`docs/agent-canvas-graph.md`](docs/agent-canvas-graph.md) — the session-free `GET /api/workflows/:path/graph` Canvas route keyed by an agent's path. -- [`docs/workspace-system-graph.md`](docs/workspace-system-graph.md) — the - retired Project dependency-graph endpoints (`410 legacy_graph_retired`) and - migration to the durable Agent Map APIs. +- [`docs/agent-map-api.md`](docs/agent-map-api.md) — durable project identity, + map/node navigation, recovery and the removed project graph endpoints. ## Testing diff --git a/packages/harness/docs/agent-map-api.md b/packages/harness/docs/agent-map-api.md new file mode 100644 index 000000000..fcb92771b --- /dev/null +++ b/packages/harness/docs/agent-map-api.md @@ -0,0 +1,40 @@ +# Agent Map identity and navigation + +Studio uses one durable Agent Map per project. Read `GET /api/state` for +server-issued `studioProjects[].projectId` values and their exact +`workspaceScopes[].projectId` associations. A scope key identifies an allowed +workspace root; it is distinct from a durable project ID. Do not derive project +IDs from paths, names or node labels. + +Send the boot token in `X-Harness-Token` for local API requests. + +| Purpose | Endpoint | +| ----------------------------------------- | --------------------------------------------------------------------- | +| Read the saved map and shared proposal | `GET /api/projects/:projectId/agent-map/workspace` | +| Resolve an implementation-backed map node | `GET /api/projects/:projectId/agent-map/nodes/:nodeId/implementation` | + +Use the exact project and node IDs when resolving an implementation. Missing, +ambiguous or unavailable implementations remain unresolved. Viewing a project, +retrying its identity, inspecting a node or navigating to an agent does not +create, select, resume, bind or prompt a conversation. Explicit session tabs +open their exact ordinary conversation and its independent Canvas/Steps. + +When identity is unavailable, Studio preserves the selected project and +conversation and offers **Reload projects**. An omitted catalog from an older +server follows the same recovery path. Upgrade older clients and servers +together; there is no second map protocol or fallback renderer. + +The former `GET /api/workspaces/:workspaceKey/system-graph`, its `POST /refresh` +and `GET /navigation` handlers have been deleted. Without a valid boot token, +requests return 401. Authenticated requests return the generic API 404, replacing +the temporary 410 retirement response. Removed and unknown event types are +ignored before reaching browser state subscribers. + +Shared workspace discovery, watch leases, the public `@sapiom/agent` +PackageInventory contract and individual-agent Canvas source scanning remain +independent of the removed project topology. + +See the [authority and retirement record](../../../docs/plans/agent-studio-plan-first-agent-map/authority-retirement.md) +for validation evidence and the release recovery boundary. Installed-release +recovery requires a reverted change released at strictly higher package and +desktop versions; no in-place downgrade or lossless state reset is promised. diff --git a/packages/harness/docs/workspace-system-graph.md b/packages/harness/docs/workspace-system-graph.md deleted file mode 100644 index aa5d88ee8..000000000 --- a/packages/harness/docs/workspace-system-graph.md +++ /dev/null @@ -1,232 +0,0 @@ -# Retired Project system graph HTTP contract - -**Breaking for HTTP clients:** current Studio servers retire the following -routes. The route handlers and server graph composition have been removed. -Authenticated requests return `404` with `error: "API route not found"`: - -```http -GET /api/workspaces/:workspaceKey/system-graph -POST /api/workspaces/:workspaceKey/system-graph/refresh -GET /api/workspaces/:workspaceKey/system-graph/navigation -``` - -The boot-token gate still runs first: send `X-Harness-Token`; missing or invalid -tokens return `401`. Authenticated unknown workspace keys also receive the -not-found response. Current servers do not emit `system-graph.changed` events -or return the historical snapshots/cache headers described below. - -## Migration to Agent Map - -Read `GET /api/state` for server-issued `studioProjects[].projectId` values and -their exact `workspaceScopes[].projectId` associations. A `workspaceKey` is not -a project ID; do not derive an ID from a path, name or legacy graph key. - -Use `GET /api/projects/:projectId/agent-map/workspace` to read the durable map -and shared proposal. To navigate an implementation-backed node, use -`GET /api/projects/:projectId/agent-map/nodes/:nodeId/implementation` with its -exact map node ID. Ordinary session tabs and per-agent Canvas remain available. -These APIs use the same boot-token protection and are not drop-in replacements -for the process-memory graph snapshot or its revision-matched navigation. - -If the catalog cannot resolve a project's identity, keep its conversation and -selection, show an unavailable-map retry, and re-read the catalog. Do not call -the retired routes or start a session as a fallback. Current Studio's -**Reload projects** action provides this recovery; stale clients must upgrade -to a release containing both the server retirement and client recovery. - -## Historical contract — older servers only - -The remainder documents the retired protocol for older servers. Its success -responses, lifecycle states and events do not describe the current server. - -Agent Studio exposes a local, read-only dependency graph for each opened -Project. The route keeps its historical `/workspaces/` name, but a -`workspaceKey` identifies one exact Project root in the current Studio server. -It is an opaque server-issued value, not a path and not an identifier clients -should derive. - -The API is local to the Harness process and sits behind the same boot-token -middleware as the rest of `/api`. Send the token in `X-Harness-Token`. An -unknown or retired key returns `404 { "error": "Workspace not found" }` without -scanning the supplied string as a path. - -## Discovering a Project key - -`GET /api/state` includes an optional `workspaceScopes` array: - -```ts -interface WorkspaceScopeSummary { - workspaceKey: string; - cwd: string; -} -``` - -The browser joins a displayed Project root to the entry with the same `cwd` -and then uses its `workspaceKey`. Filesystem paths stop at this state boundary: -system-graph snapshots and change events never contain a Project root or agent -source path. - -## Reading and refreshing - -```http -GET /api/workspaces/:workspaceKey/system-graph -POST /api/workspaces/:workspaceKey/system-graph/refresh -``` - -`GET` returns the current accepted process-memory snapshot. On a cold read, -known inventory nodes and revision-matched navigation render immediately in a -degraded projection; bounded direct invocation extraction and background discovery -may publish a later revision. Concurrent reads share that work, and ordinary -reads never await a filesystem baseline or discovery scan. `POST .../refresh` -reruns registry prerequisites, requests a fresh projection, waits for that -attempt, and is the explicit recovery action after an error. Both successful -routes return `200` with a -`SystemGraphSnapshot`: - -```ts -interface SystemGraphSnapshot { - workspaceKey: string; - revision: number; - state: "building" | "ready" | "stale" | "degraded"; - graph: SystemGraph | null; -} -``` - -Revisions increase for accepted lifecycle transitions. They are monotonic for -one `workspaceKey` during one server process, including a remove-and-reopen, -but they are not durable across a Studio restart. - -| State | `graph` | Meaning | -| ---------- | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | -| `building` | `null` until a usable projection exists | The first projection, or a refresh without a usable graph, is in progress. | -| `ready` | non-null | The current projection completed and is cacheable. | -| `stale` | non-null | The newest usable graph remains visible while refresh is running or after refresh failed. | -| `degraded` | partial graph or `null` | Projection was not cacheable, or no usable graph could be built. The UI may offer one bounded automatic recovery followed by explicit retry. | - -Every `200` response also carries: - -```http -X-Sapiom-System-Graph-Cache: complete | degraded -``` - -`complete` means the returned snapshot is `ready`. `building`, `stale`, and -`degraded` all report `degraded`; the header is a health/cacheability signal, -not an HTTP cache directive. - -## Resolving agent navigation - -Filesystem navigation is isolated from the public graph payload behind a -separate boot-token-protected route: - -```http -GET /api/workspaces/:workspaceKey/system-graph/navigation -``` - -It returns the resolver sidecar committed atomically with the graph snapshot: - -```ts -interface SystemGraphNavigationResponse { - workspaceKey: string; - revision: number; - targets: Array<{ agentKey: string; workflowPath: string }>; -} -``` - -The response has `Cache-Control: no-store`. Agent paths appear only in this -protected sidecar; they never enter `SystemGraph` JSON, lifecycle events, or -browser-derived identity logic. The browser accepts a sidecar only when both -its `workspaceKey` and `revision` exactly match the displayed snapshot. A -malformed or mismatched response, a newer invalidation, or a snapshot in a -loading, error, or `building` state leaves graph cards inert. An exact-revision -sidecar remains usable for a stale graph while its refresh runs, but a newer -invalidation closes navigation immediately. If the resolver is newer, the -browser reloads the graph through the normal lifecycle and retries the join -within a bounded loop. - -## Graph payload - -`SystemGraph` is path-free and has `kind: "system"`. Its scope repeats only the -opaque key. Nodes contain an `id`, Project-scoped `agentKey`, and display -`label`. Public direct-invocation edges are explicit and extensible: - -```ts -interface StaticInvocationGraphEdge { - from: string; - to: string; - kind: "invokes"; - basis: "static-invocation"; - mode: "blocking" | "async"; -} - -type SystemGraphEdge = StaticInvocationGraphEdge; -``` - -Blocking and asynchronous calls between the same pair remain distinct in the -JSON even when the UI groups them into one connector. - -Direct invocation analysis is syntax-only. It never creates a TypeScript -`Program` or `TypeChecker`, and it never imports, bundles, or executes customer -code. The provider scans each inventoried agent source root separately for -literal calls. It does not inspect the provenance of invocation inputs, follow -agent outputs through formatter/helper/router code, or scan arbitrary workspace -router modules outside those roots. Cross-agent output-to-input analysis will -use a separate package-level evidence provider. - -Projection can remain useful while reporting warnings: - -| Warning code | Meaning | -| ----------------------------- | ------------------------------------------------------------------------------------------------- | -| `unresolved-target` | A literal target does not resolve to an agent in the selected Project. | -| `dynamic-target` | Source contains a call whose target cannot be proven statically. | -| `duplicate-edge` | The same mode-specific direct invocation was discovered more than once. | -| `projection-failed` | A direct invocation projection failed and the remaining graph was preserved. | -| `duplicate-agent-key` | More than one contained agent proposed the same key; local fallback identities disambiguate them. | -| `inventory-extraction-failed` | One agent could not be enriched, so the remaining inventory was returned. | - -Registry and syntax-discovered agents enter a working-tree package inventory -and render immediately. A syntax-proven source definition name is canonical -without bundling or executing project code; a retained marker/cloud slug remains -only a compatibility alias. Unknown or invalid identity uses a safe provisional marker -or `local:` key. Marker-authorized legacy name inspection and direct invocation -extraction run in bounded background queues after the inventory projection -commits. Settled identities and invocation edges publish later revisions; -failures preserve provisional nodes and unambiguous direct edges. - -Cacheability keeps three private facts separate: workspace discovery must be -complete, identity work must be settled, and direct invocation extraction must -be complete. A settled unavailable identity may therefore remain provisional -while the snapshot is `ready`; an incomplete workspace walk, pending/retryable -identity, or incomplete invocation scan keeps it `degraded`. Warnings and the -Retry affordance remain visible without freezing evidence that may still change. - -Package inventory protocol 1 is deliberately limited to which agents exist, -their stable identities, and their package-relative locations. It carries no -agent-owned or opaque relationship payload. Future package-wide data-flow and -cross-agent relationship evidence will use a separate versioned contract with -its own deterministic provenance and validation. - -## Freshness event - -After an accepted transition, the Harness event WebSocket publishes: - -```ts -{ - type: "system-graph.changed"; - workspaceKey: string; - revision: number; - state: "building" | "ready" | "stale" | "degraded"; -} -``` - -The event is an invalidation hint. Clients compare its key and revision with -the displayed snapshot and refetch when newer; the graph itself is not sent on -the event bus. - -Opening a Project graph acquires a canonical-root watcher lease. Sessions and -graphs for the same root share its bounded asynchronous fingerprint rather than -multiplying recursive walks. Relevant raw events synchronously make old -navigation inert; source/inventory reconciliation is debounced, coalesced, and -generation-guarded. Platforms without recursive watch support, or watchers that -later error, fall back to asynchronous polling over the same admitted candidate -and dependency observations. Removing the final lease retires the watcher and -degrades its accepted freshness proof before a later reopen can reuse it. diff --git a/packages/harness/src/core/__fixtures__/system-graph-workspace/growth/index.ts b/packages/harness/src/core/__fixtures__/system-graph-workspace/growth/index.ts deleted file mode 100644 index 9f057d762..000000000 --- a/packages/harness/src/core/__fixtures__/system-graph-workspace/growth/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function growth(input: unknown) { - return input; -} diff --git a/packages/harness/src/core/__fixtures__/system-graph-workspace/research/index.ts b/packages/harness/src/core/__fixtures__/system-graph-workspace/research/index.ts deleted file mode 100644 index db66c5e88..000000000 --- a/packages/harness/src/core/__fixtures__/system-graph-workspace/research/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -export async function research(ctx: { - sapiom: { agents: { run: Function; launch: Function } }; -}) { - await ctx.sapiom.agents.run({ - definition: "growth", - input: { topic: "market" }, - }); - return ctx.sapiom.agents.launch({ - definition: "growth", - input: { topic: "market" }, - }); -} diff --git a/packages/harness/src/core/canvas-interconnections.ts b/packages/harness/src/core/canvas-interconnections.ts index d52b08392..062f6c650 100644 --- a/packages/harness/src/core/canvas-interconnections.ts +++ b/packages/harness/src/core/canvas-interconnections.ts @@ -499,7 +499,7 @@ export interface DetectedLaunch { fromStepId: string | null; } -/** Internal source evidence. It never crosses the system-graph HTTP boundary. */ +/** Private syntax evidence for per-agent Canvas extraction. */ export interface SourceEvidence { /** POSIX path relative to the caller's source root. */ file: string; diff --git a/packages/harness/src/core/system-graph-inventory.test.ts b/packages/harness/src/core/system-graph-inventory.test.ts deleted file mode 100644 index c1cce8ebe..000000000 --- a/packages/harness/src/core/system-graph-inventory.test.ts +++ /dev/null @@ -1,1402 +0,0 @@ -import * as fs from "node:fs/promises"; -import * as os from "node:os"; -import * as path from "node:path"; -import { describe, expect, it, vi } from "vitest"; - -import type { RegistryWorkflowInfo as WorkflowInfo } from "./workflow-registry.js"; -import { - dirtyGraphSourceRoots, - HarnessRegistryInventoryProvider, - inventorySourceRoot, - type AgentInventoryResult, - type HarnessRegistryInventoryProviderOptions, - type WorkspaceScope, -} from "./system-graph-inventory.js"; -import type { - ManifestNameInspection, - ManifestNameInspectionOptions, -} from "./definition-name.js"; - -const WORKSPACE = "/private/workspaces/acme"; -const SCOPE: WorkspaceScope = { - workspaceKey: "workspace-acme", - root: WORKSPACE, -}; - -function workflow( - name: string, - relativePath: string, - definitionSlug: string | null, - overrides: Partial = {}, -): WorkflowInfo { - return { - name, - path: relativePath ? `${WORKSPACE}/${relativePath}` : WORKSPACE, - definitionId: definitionSlug ? 1 : null, - definitionSlug, - markerPresent: true, - source: "scan", - ...overrides, - }; -} - -function provider( - workflows: readonly WorkflowInfo[], - options: Partial = {}, -): HarnessRegistryInventoryProvider { - return new HarnessRegistryInventoryProvider({ - listWorkflows: () => workflows, - fingerprintSource: async (sourceRoot) => `fingerprint:${sourceRoot}`, - revalidateMarker: async () => true, - ...options, - inventorySnapshot: - options.inventorySnapshot ?? - (async (scope) => ({ - workflows, - status: await (options.inventoryStatus?.(scope) ?? "complete"), - generation: 1, - canonicalScopeRoot: scope.root, - canonicalWorkflowRoots: workflows.map((item) => ({ - workflowPath: item.path, - canonicalRoot: item.path, - identityEvidence: Object.prototype.hasOwnProperty.call( - item, - "sourceDefinitionName", - ) - ? ("source" as const) - : item.markerPresent === true - ? ("marker" as const) - : ("unknown" as const), - })), - })), - }); -} - -async function enrich( - inventory: HarnessRegistryInventoryProvider, - initial: AgentInventoryResult, - changed: ReturnType, -): Promise { - initial.startEnrichment?.(); - await vi.waitFor(() => expect(changed).toHaveBeenCalled()); - return inventory.listAgents(SCOPE); -} - -describe("HarnessRegistryInventoryProvider", () => { - it("uses syntax-proven source identity immediately without extraction", async () => { - const inspectManifestName = vi.fn(async () => { - throw new Error("source-only rows must never execute extraction"); - }); - const inventory = provider( - [ - workflow("Billing package", "billing", "old-marker", { - sourceDefinitionName: "CurrentSourceName", - }), - ], - { - inspectManifestName, - inventoryStatus: async () => "degraded" as const, - }, - ); - - const result = await inventory.listAgents(SCOPE); - - expect(result.inventory).toMatchObject({ - status: "degraded", - agents: [ - { - agentKey: "CurrentSourceName", - identityStatus: "canonical", - }, - ], - }); - expect(result.context[0]?.resolutionAliases).toContain("old-marker"); - expect(result.discoveryComplete).toBe(false); - expect(result.startEnrichment).toBeUndefined(); - expect(inspectManifestName).not.toHaveBeenCalled(); - }); - - it("never extracts a markerless manual row even after discovery is complete", async () => { - const inspectManifestName = vi.fn(async () => ({ - status: "found" as const, - name: "Executed", - })); - let status: "complete" | "degraded" = "degraded"; - const inventory = provider( - [ - workflow("Pending", "pending", null, { - markerPresent: undefined, - source: "connect", - }), - ], - { inspectManifestName, inventoryStatus: () => status }, - ); - - const degraded = await inventory.listAgents(SCOPE); - degraded.startEnrichment?.(); - await Promise.resolve(); - expect(degraded.startEnrichment).toBeUndefined(); - expect(inspectManifestName).not.toHaveBeenCalled(); - - status = "complete"; - const complete = await inventory.listAgents(SCOPE); - expect(complete.startEnrichment).toBeUndefined(); - complete.startEnrichment?.(); - expect(inspectManifestName).not.toHaveBeenCalled(); - }); - - it("enriches a markerless row with retained cloud-link authorization", async () => { - const inspectManifestName = vi.fn(async () => ({ - status: "found" as const, - name: "CloudLinked", - })); - const inventory = provider( - [ - workflow("Linked", "linked", "old-alias", { - markerPresent: undefined, - source: "connect", - }), - ], - { inspectManifestName }, - ); - - const initial = await inventory.listAgents(SCOPE); - expect(initial.startEnrichment).toBeTypeOf("function"); - initial.startEnrichment?.(); - await vi.waitFor(() => expect(inspectManifestName).toHaveBeenCalledOnce()); - await expect(inventory.listAgents(SCOPE)).resolves.toMatchObject({ - discoveryComplete: true, - inventory: { - agents: [{ agentKey: "CloudLinked", identityStatus: "canonical" }], - }, - }); - }); - - it("enriches a marker-proven row despite unrelated degraded discovery", async () => { - const inspectManifestName = vi.fn(async () => ({ - status: "found" as const, - name: "CurrentSource", - })); - const inventory = provider( - [ - workflow("Linked", "linked", null, { - markerPresent: true, - }), - ], - { - inspectManifestName, - inventoryStatus: () => "degraded", - }, - ); - - const degraded = await inventory.listAgents(SCOPE); - expect(degraded.inventory.status).toBe("degraded"); - expect(degraded.startEnrichment).toBeTypeOf("function"); - degraded.startEnrichment?.(); - await vi.waitFor(() => expect(inspectManifestName).toHaveBeenCalledOnce()); - }); - - it("prefers one atomic inventory snapshot over independently racing reads", async () => { - const listWorkflows = vi.fn(() => [workflow("wrong", "wrong", "wrong")]); - const inventoryStatus = vi.fn(() => "complete" as const); - const inventory = new HarnessRegistryInventoryProvider({ - listWorkflows, - inventoryStatus, - inventorySnapshot: () => ({ - workflows: [ - workflow("Atomic", "atomic", null, { - sourceDefinitionName: "atomic-source", - }), - ], - status: "degraded", - generation: 7, - }), - }); - - const result = await inventory.listAgents(SCOPE); - - expect(result.inventory).toMatchObject({ - status: "degraded", - agents: [{ agentKey: "atomic-source", path: "atomic" }], - }); - expect(listWorkflows).not.toHaveBeenCalled(); - expect(inventoryStatus).not.toHaveBeenCalled(); - }); - - it("retires an active legacy extraction when syntax evidence arrives", async () => { - let release!: () => void; - const gate = new Promise((resolve) => { - release = resolve; - }); - let workflows: WorkflowInfo[] = [workflow("Legacy", "agent", "old-marker")]; - const inspectManifestName = vi.fn(async () => { - await gate; - return { status: "found" as const, name: "StaleExtracted" }; - }); - const changed = vi.fn(); - const inventory = new HarnessRegistryInventoryProvider({ - listWorkflows: () => workflows, - inventoryStatus: () => "complete", - fingerprintSource: async () => "fingerprint", - revalidateMarker: async () => true, - inspectManifestName, - onIdentityChange: changed, - }); - const legacy = await inventory.listAgents(SCOPE); - legacy.startEnrichment?.(); - await vi.waitFor(() => expect(inspectManifestName).toHaveBeenCalledOnce()); - - workflows = [ - workflow("Source", "agent", "old-marker", { - sourceDefinitionName: "CurrentSyntax", - }), - ]; - const syntax = await inventory.listAgents(SCOPE); - expect(syntax.inventory.agents[0]).toMatchObject({ - agentKey: "CurrentSyntax", - identityStatus: "canonical", - }); - release(); - await new Promise((resolve) => setTimeout(resolve, 0)); - - expect(changed).not.toHaveBeenCalled(); - await expect(inventory.listAgents(SCOPE)).resolves.toMatchObject({ - inventory: { - agents: [{ agentKey: "CurrentSyntax", identityStatus: "canonical" }], - }, - }); - }); - - it("derives inventory roots using POSIX, drive, and UNC workspace flavor", () => { - expect(inventorySourceRoot("/workspace", "nested/agent")).toBe( - "/workspace/nested/agent", - ); - expect(inventorySourceRoot("C:\\workspace", "nested/agent")).toBe( - "C:\\workspace\\nested\\agent", - ); - expect( - inventorySourceRoot("\\\\server\\share\\workspace", "nested/agent"), - ).toBe("\\\\server\\share\\workspace\\nested\\agent"); - }); - - it("returns linked agents provisionally before source inspection starts", async () => { - let release!: () => void; - const gate = new Promise((resolve) => { - release = resolve; - }); - const inspectManifestName = vi.fn(async () => { - await gate; - return { status: "found" as const, name: "SourceName" }; - }); - const changed = vi.fn(); - const inventory = provider( - [workflow("Research package", "research", "old-marker")], - { inspectManifestName, onIdentityChange: changed }, - ); - - const initial = await inventory.listAgents(SCOPE); - - expect(inspectManifestName).not.toHaveBeenCalled(); - expect(initial.identitySettled).toBe(false); - expect(initial.inventory).toMatchObject({ - status: "degraded", - agents: [ - { - agentKey: "old-marker", - identityStatus: "provisional", - identityIssue: "identity-pending", - path: "research", - entrypoint: "index.ts", - }, - ], - }); - expect(initial.context[0]).toMatchObject({ - agentKey: "old-marker", - workflowPath: `${WORKSPACE}/research`, - resolutionAliases: ["old-marker"], - }); - - initial.startEnrichment?.(); - await vi.waitFor(() => - expect(inspectManifestName).toHaveBeenCalledTimes(1), - ); - release(); - await vi.waitFor(() => expect(changed).toHaveBeenCalledTimes(1)); - const enriched = await inventory.listAgents(SCOPE); - - expect(enriched.inventory).toMatchObject({ - status: "complete", - agents: [ - { - agentKey: "SourceName", - identityStatus: "canonical", - }, - ], - }); - expect(enriched.identitySettled).toBe(true); - expect(enriched.context[0]?.resolutionAliases).toEqual(["old-marker"]); - }); - - it("uses a renamed source identity while retaining the marker only as an alias", async () => { - const inspectManifestName = vi - .fn<() => Promise>() - .mockResolvedValueOnce({ status: "found", name: "Before" }) - .mockResolvedValueOnce({ status: "found", name: "After" }); - const changed = vi.fn(); - const inventory = provider([workflow("Package", "agent", "marker-name")], { - inspectManifestName, - onIdentityChange: changed, - }); - - const before = await enrich( - inventory, - await inventory.listAgents(SCOPE), - changed, - ); - expect(before.inventory.agents[0]?.agentKey).toBe("Before"); - - changed.mockClear(); - inventory.invalidateSource(`${WORKSPACE}/agent`); - const pending = await inventory.listAgents(SCOPE); - expect(pending.inventory.agents[0]).toMatchObject({ - agentKey: "marker-name", - identityIssue: "identity-pending", - }); - const after = await enrich(inventory, pending, changed); - - expect(after.inventory.agents[0]?.agentKey).toBe("After"); - expect(after.context[0]?.resolutionAliases).toEqual(["marker-name"]); - }); - - it("does not call two unsettled marker identities a collision", async () => { - let release!: () => void; - const inspectionGate = new Promise((resolve) => { - release = resolve; - }); - const inspectManifestName = vi.fn(async (sourceRoot: string) => { - await inspectionGate; - return { - status: "found" as const, - name: sourceRoot.endsWith("/first") ? "payments" : "billing", - }; - }); - const changed = vi.fn(); - const inventory = provider( - [ - workflow("First", "first", "shared-marker"), - workflow("Second", "second", "shared-marker"), - ], - { inspectManifestName, onIdentityChange: changed }, - ); - - const pending = await inventory.listAgents(SCOPE); - expect(pending.identitySettled).toBe(false); - expect(pending.warnings).toEqual([]); - expect(pending.inventory.agents).toMatchObject([ - { - agentKey: "local:first", - identityStatus: "provisional", - identityIssue: "identity-pending", - }, - { - agentKey: "local:second", - identityStatus: "provisional", - identityIssue: "identity-pending", - }, - ]); - expect( - pending.inventory.agents.map((agent) => agent.identityIssue), - ).toEqual(["identity-pending", "identity-pending"]); - expect(pending.context.map((item) => item.resolutionAliases)).toEqual([ - ["shared-marker"], - ["shared-marker"], - ]); - - pending.startEnrichment?.(); - release(); - await vi.waitFor(() => expect(changed).toHaveBeenCalled()); - const settled = await inventory.listAgents(SCOPE); - - expect(settled.identitySettled).toBe(true); - expect(settled.inventory.agents.map((agent) => agent.agentKey)).toEqual([ - "billing", - "payments", - ]); - expect(settled.warnings).toEqual([]); - }); - - it("keeps shared retryable marker guesses under local identities", async () => { - const changed = vi.fn(); - const inventory = provider( - [ - workflow("First", "first", "shared-marker"), - workflow("Second", "second", "shared-marker"), - ], - { - inspectManifestName: async () => ({ - status: "failed", - retryable: true, - }), - onIdentityChange: changed, - }, - ); - - const result = await enrich( - inventory, - await inventory.listAgents(SCOPE), - changed, - ); - - expect(result.identitySettled).toBe(false); - expect(result.inventory.agents).toMatchObject([ - { - agentKey: "local:first", - identityStatus: "provisional", - identityIssue: "identity-unavailable", - }, - { - agentKey: "local:second", - identityStatus: "provisional", - identityIssue: "identity-unavailable", - }, - ]); - expect(result.warnings).toHaveLength(2); - expect( - result.warnings.every( - (warning) => warning.code === "inventory-extraction-failed", - ), - ).toBe(true); - }); - - it("keeps duplicate source names as separate deterministic local identities", async () => { - const inspectManifestName = vi.fn(async () => ({ - status: "found" as const, - name: "shared", - })); - const changed = vi.fn(); - const inventory = provider( - [ - workflow("First", "first", "marker-first"), - workflow("Second", "second", "marker-second"), - ], - { inspectManifestName, onIdentityChange: changed }, - ); - const initial = await inventory.listAgents(SCOPE); - initial.startEnrichment?.(); - await vi.waitFor(() => expect(changed).toHaveBeenCalledTimes(1)); - const result = await inventory.listAgents(SCOPE); - - expect(result.inventory.agents).toEqual([ - { - agentKey: "local:first", - identityStatus: "provisional", - identityIssue: "duplicate-agent-key", - candidateAgentKey: "shared", - path: "first", - entrypoint: "index.ts", - }, - { - agentKey: "local:second", - identityStatus: "provisional", - identityIssue: "duplicate-agent-key", - candidateAgentKey: "shared", - path: "second", - entrypoint: "index.ts", - }, - ]); - expect(result.context.map((item) => item.resolutionAliases)).toEqual([ - ["marker-first", "shared"], - ["marker-second", "shared"], - ]); - expect(result.warnings).toEqual([ - { - code: "duplicate-agent-key", - agentKey: "shared", - message: "Multiple agents use shared; kept each with a local identity.", - }, - ]); - }); - - it("keeps a source-canonical identity above a colliding provisional marker", async () => { - const inspectManifestName = vi.fn(async (sourceRoot: string) => - sourceRoot.endsWith("/canonical") - ? ({ status: "found", name: "payments" } as const) - : ({ status: "absent" } as const), - ); - const changed = vi.fn(); - const inventory = provider( - [ - workflow("Canonical", "canonical", "old-payments"), - workflow("Pending", "pending", "payments"), - ], - { inspectManifestName, onIdentityChange: changed }, - ); - const initial = await inventory.listAgents(SCOPE); - initial.startEnrichment?.(); - await vi.waitFor(() => expect(changed).toHaveBeenCalledTimes(1)); - const result = await inventory.listAgents(SCOPE); - - expect(result.inventory.agents).toEqual([ - { - agentKey: "local:pending", - identityStatus: "provisional", - identityIssue: "identity-unavailable", - path: "pending", - entrypoint: "index.ts", - }, - { - agentKey: "payments", - identityStatus: "canonical", - path: "canonical", - entrypoint: "index.ts", - }, - ]); - expect( - result.context.map((item) => [item.agentKey, item.resolutionAliases]), - ).toEqual([ - ["local:pending", ["payments"]], - ["payments", ["old-payments"]], - ]); - expect(result.warnings).toEqual([]); - }); - - it("preserves a provisional marker identity after inspection failure and retries only explicitly", async () => { - const inspectManifestName = vi - .fn<() => Promise>() - .mockResolvedValueOnce({ status: "failed", retryable: true }) - .mockResolvedValueOnce({ status: "found", name: "recovered" }); - const changed = vi.fn(); - const inventory = provider([workflow("Research", "research", "marker")], { - inspectManifestName, - onIdentityChange: changed, - }); - const failed = await enrich( - inventory, - await inventory.listAgents(SCOPE), - changed, - ); - - expect(failed.inventory.agents[0]).toMatchObject({ - agentKey: "marker", - identityStatus: "provisional", - identityIssue: "identity-unavailable", - }); - expect(failed.warnings[0]?.code).toBe("inventory-extraction-failed"); - expect(failed.identitySettled).toBe(false); - failed.startEnrichment?.(); - await Promise.resolve(); - expect(inspectManifestName).toHaveBeenCalledTimes(1); - - inventory.retryFailedInspections(SCOPE); - changed.mockClear(); - const retrying = await inventory.listAgents(SCOPE); - const recovered = await enrich(inventory, retrying, changed); - expect(inspectManifestName).toHaveBeenCalledTimes(2); - expect(recovered.inventory.agents[0]).toMatchObject({ - agentKey: "recovered", - identityStatus: "canonical", - }); - }); - - it("settles an unnameable identity without hiding its warning", async () => { - const changed = vi.fn(); - const inventory = provider([workflow("Dashboard", "dashboard", null)], { - inspectManifestName: async () => ({ - status: "failed", - retryable: false, - }), - onIdentityChange: changed, - }); - - const result = await enrich( - inventory, - await inventory.listAgents(SCOPE), - changed, - ); - - expect(result.inventory).toMatchObject({ - status: "degraded", - agents: [ - { - agentKey: "local:dashboard", - identityIssue: "identity-unavailable", - }, - ], - }); - expect(result.identitySettled).toBe(true); - expect(result.warnings).toEqual([ - expect.objectContaining({ - code: "inventory-extraction-failed", - agentKey: "local:dashboard", - }), - ]); - }); - - it("treats an absent source definition as normal unavailable identity", async () => { - const changed = vi.fn(); - const inspectManifestName = vi.fn(async () => ({ - status: "absent" as const, - })); - const inventory = provider([workflow("Research", "research", "marker")], { - inspectManifestName, - onIdentityChange: changed, - }); - const result = await enrich( - inventory, - await inventory.listAgents(SCOPE), - changed, - ); - - expect(result.inventory.agents[0]).toMatchObject({ - agentKey: "marker", - identityStatus: "provisional", - identityIssue: "identity-unavailable", - }); - expect(result.warnings).toEqual([]); - expect(result.identitySettled).toBe(true); - - inventory.retryFailedInspections(SCOPE); - const afterExplicitRetry = await inventory.listAgents(SCOPE); - expect(afterExplicitRetry.inventory.agents[0]).toMatchObject({ - agentKey: "marker", - identityIssue: "identity-unavailable", - }); - expect(inspectManifestName).toHaveBeenCalledTimes(1); - }); - - it("keeps invalid source names provisional without leaking the candidate", async () => { - const changed = vi.fn(); - const inventory = provider([workflow("Agent", "agent", "safe-marker")], { - inspectManifestName: async () => ({ - status: "found", - name: "../unsafe", - }), - onIdentityChange: changed, - }); - const result = await enrich( - inventory, - await inventory.listAgents(SCOPE), - changed, - ); - - expect(result.inventory.agents[0]).toEqual({ - agentKey: "safe-marker", - identityStatus: "provisional", - identityIssue: "identity-invalid", - path: "agent", - entrypoint: "index.ts", - }); - expect(result.warnings).toEqual([ - expect.objectContaining({ code: "inventory-extraction-failed" }), - ]); - expect(JSON.stringify(result)).not.toContain("../unsafe"); - }); - - it("caps background source inspection concurrency at four", async () => { - let release!: () => void; - const gate = new Promise((resolve) => { - release = resolve; - }); - let active = 0; - let maximum = 0; - const inspectManifestName = vi.fn(async (sourceRoot: string) => { - active += 1; - maximum = Math.max(maximum, active); - await gate; - active -= 1; - return { status: "found" as const, name: path.basename(sourceRoot) }; - }); - const changed = vi.fn(); - const inventory = provider( - Array.from({ length: 7 }, (_, index) => - workflow(`Agent ${index}`, `agent-${index}`, null), - ), - { inspectManifestName, onIdentityChange: changed }, - ); - - (await inventory.listAgents(SCOPE)).startEnrichment?.(); - await vi.waitFor(() => - expect(inspectManifestName).toHaveBeenCalledTimes(4), - ); - expect(maximum).toBe(4); - release(); - await vi.waitFor(() => expect(changed).toHaveBeenCalledTimes(1)); - expect(changed).toHaveBeenCalledWith( - Array.from({ length: 7 }, (_, index) => `${WORKSPACE}/agent-${index}`), - ); - expect(maximum).toBe(4); - }); - - it("retires queued and active marker inspections synchronously on a raw scope edit", async () => { - let release!: () => void; - const gate = new Promise((resolve) => { - release = resolve; - }); - const inspectManifestName = vi.fn(async (sourceRoot: string) => { - await gate; - return { status: "found" as const, name: path.basename(sourceRoot) }; - }); - const changed = vi.fn(); - const inventory = provider( - Array.from({ length: 5 }, (_, index) => - workflow(`Agent ${index}`, `agent-${index}`, null), - ), - { inspectManifestName, onIdentityChange: changed }, - ); - - (await inventory.listAgents(SCOPE)).startEnrichment?.(); - await vi.waitFor(() => - expect(inspectManifestName).toHaveBeenCalledTimes(4), - ); - inventory.invalidateScope(WORKSPACE); - release(); - await new Promise((resolve) => setTimeout(resolve, 20)); - - expect(inspectManifestName).toHaveBeenCalledTimes(4); - expect(changed).not.toHaveBeenCalled(); - }); - - it("queues fresh proof behind an invalidated active inspection and converges", async () => { - let releaseFirst!: () => void; - const firstGate = new Promise((resolve) => { - releaseFirst = resolve; - }); - const inspectManifestName = vi.fn(async () => { - if (inspectManifestName.mock.calls.length === 1) await firstGate; - return { status: "found" as const, name: "FreshIdentity" }; - }); - const changed = vi.fn(); - const inventory = provider([workflow("Agent", "agent", null)], { - inspectManifestName, - onIdentityChange: changed, - }); - - (await inventory.listAgents(SCOPE)).startEnrichment?.(); - await vi.waitFor(() => expect(inspectManifestName).toHaveBeenCalledOnce()); - - // A raw edit in another active scope conservatively invalidates the shared - // provider epoch. A later ordinary read of this scope must enqueue fresh - // work instead of mistaking the stale active task for the same request. - inventory.invalidateScope("/private/workspaces/unrelated"); - (await inventory.listAgents(SCOPE)).startEnrichment?.(); - releaseFirst(); - - await vi.waitFor(() => - expect(inspectManifestName).toHaveBeenCalledTimes(2), - ); - await vi.waitFor(() => expect(changed).toHaveBeenCalledTimes(1)); - await expect(inventory.listAgents(SCOPE)).resolves.toMatchObject({ - inventory: { - agents: [{ agentKey: "FreshIdentity", identityStatus: "canonical" }], - }, - }); - }); - - it("revalidates marker proof after fingerprinting immediately before inspection", async () => { - let releaseFingerprint!: () => void; - const fingerprintGate = new Promise((resolve) => { - releaseFingerprint = resolve; - }); - let markerPresent = true; - const fingerprintEntered = vi.fn(); - const inspectManifestName = vi.fn(async () => ({ - status: "found" as const, - name: "must-not-run", - })); - const changed = vi.fn(); - const inventory = provider([workflow("Agent", "agent", null)], { - fingerprintSource: async () => { - fingerprintEntered(); - await fingerprintGate; - return "fingerprint"; - }, - revalidateMarker: async () => markerPresent, - inspectManifestName, - onIdentityChange: changed, - }); - - (await inventory.listAgents(SCOPE)).startEnrichment?.(); - await vi.waitFor(() => expect(fingerprintEntered).toHaveBeenCalledOnce()); - markerPresent = false; - releaseFingerprint(); - await new Promise((resolve) => setTimeout(resolve, 20)); - - expect(inspectManifestName).not.toHaveBeenCalled(); - expect(changed).not.toHaveBeenCalled(); - }); - - it("threads current marker proof to the inspector's actual child-launch boundary", async () => { - let releaseInnerFingerprint!: () => void; - const innerFingerprintGate = new Promise((resolve) => { - releaseInnerFingerprint = resolve; - }); - let markerPresent = true; - const innerFingerprintEntered = vi.fn(); - const actualExtractorLaunch = vi.fn(); - const inspectManifestName = vi.fn( - async ( - _sourceRoot: string, - options?: ManifestNameInspectionOptions, - ): Promise => { - innerFingerprintEntered(); - await innerFingerprintGate; - if (!(await options?.authorizeBeforeLaunch?.())) { - return { status: "failed", retryable: true }; - } - actualExtractorLaunch(); - return { status: "found", name: "must-not-run" }; - }, - ); - const changed = vi.fn(); - const inventory = provider([workflow("Agent", "agent", null)], { - revalidateMarker: async () => markerPresent, - inspectManifestName, - onIdentityChange: changed, - }); - - (await inventory.listAgents(SCOPE)).startEnrichment?.(); - await vi.waitFor(() => - expect(innerFingerprintEntered).toHaveBeenCalledOnce(), - ); - markerPresent = false; - releaseInnerFingerprint(); - await vi.waitFor(() => expect(changed).toHaveBeenCalledOnce()); - - expect(actualExtractorLaunch).not.toHaveBeenCalled(); - expect( - (await inventory.listAgents(SCOPE)).inventory.agents[0], - ).toMatchObject({ identityIssue: "identity-unavailable" }); - }); - - it("surfaces settled identities within a bounded window while slower work continues", async () => { - let releaseSlow!: () => void; - const slow = new Promise((resolve) => { - releaseSlow = resolve; - }); - const inspectManifestName = vi.fn(async (sourceRoot: string) => { - if (sourceRoot.endsWith("/slow")) await slow; - return { status: "found" as const, name: path.basename(sourceRoot) }; - }); - const changed = vi.fn(); - const inventory = provider( - [workflow("Fast", "fast", null), workflow("Slow", "slow", null)], - { - inspectManifestName, - onIdentityChange: changed, - }, - ); - - (await inventory.listAgents(SCOPE)).startEnrichment?.(); - await vi.waitFor(() => expect(changed).toHaveBeenCalledTimes(1), { - timeout: 5_000, - }); - expect(changed).toHaveBeenNthCalledWith(1, [`${WORKSPACE}/fast`]); - - const partial = await inventory.listAgents(SCOPE); - expect( - partial.inventory.agents.find((agent) => agent.path === "fast"), - ).toMatchObject({ agentKey: "fast", identityStatus: "canonical" }); - expect( - partial.inventory.agents.find((agent) => agent.path === "slow"), - ).toMatchObject({ identityIssue: "identity-pending" }); - - releaseSlow(); - await vi.waitFor(() => expect(changed).toHaveBeenCalledTimes(2), { - timeout: 5_000, - }); - expect(changed).toHaveBeenNthCalledWith(2, [`${WORKSPACE}/slow`]); - }); - - it("drops a settled batch notification when its source is invalidated before the batch drains", async () => { - let releaseSlow!: () => void; - const slow = new Promise((resolve) => { - releaseSlow = resolve; - }); - const inspectManifestName = vi.fn(async (sourceRoot: string) => { - if (sourceRoot.endsWith("/slow")) await slow; - return { status: "found" as const, name: path.basename(sourceRoot) }; - }); - const changed = vi.fn(); - const inventory = provider( - [workflow("Fast", "fast", null), workflow("Slow", "slow", null)], - { - inspectManifestName, - onIdentityChange: changed, - identityChangeCoalesceMs: 10_000, - }, - ); - - (await inventory.listAgents(SCOPE)).startEnrichment?.(); - await vi.waitFor(async () => { - const snapshot = await inventory.listAgents(SCOPE); - expect( - snapshot.inventory.agents.find((agent) => agent.path === "fast") - ?.agentKey, - ).toBe("fast"); - expect( - snapshot.inventory.agents.find((agent) => agent.path === "slow") - ?.identityIssue, - ).toBe("identity-pending"); - }); - inventory.invalidateSource(`${WORKSPACE}/fast`); - releaseSlow(); - - await vi.waitFor(() => expect(changed).toHaveBeenCalledTimes(1)); - expect(changed).toHaveBeenCalledWith([`${WORKSPACE}/slow`]); - }); - - it("deduplicates in-flight inspection and prevents an invalidated result from winning", async () => { - let resolveBefore!: (value: ManifestNameInspection) => void; - let resolveAfter!: (value: ManifestNameInspection) => void; - const before = new Promise((resolve) => { - resolveBefore = resolve; - }); - const after = new Promise((resolve) => { - resolveAfter = resolve; - }); - const inspectManifestName = vi - .fn<() => Promise>() - .mockReturnValueOnce(before) - .mockReturnValueOnce(after); - const changed = vi.fn(); - const sourceRoot = `${WORKSPACE}/agent`; - const inventory = provider([workflow("Agent", "agent", "marker")], { - inspectManifestName, - onIdentityChange: changed, - }); - - const initial = await inventory.listAgents(SCOPE); - initial.startEnrichment?.(); - initial.startEnrichment?.(); - await vi.waitFor(() => - expect(inspectManifestName).toHaveBeenCalledTimes(1), - ); - - inventory.invalidateSource(sourceRoot); - (await inventory.listAgents(SCOPE)).startEnrichment?.(); - resolveBefore({ status: "found", name: "Before" }); - await vi.waitFor(() => - expect(inspectManifestName).toHaveBeenCalledTimes(2), - ); - expect(changed).not.toHaveBeenCalled(); - resolveAfter({ status: "found", name: "After" }); - await vi.waitFor(() => expect(changed).toHaveBeenCalledTimes(1)); - - expect( - (await inventory.listAgents(SCOPE)).inventory.agents[0]?.agentKey, - ).toBe("After"); - expect(changed).toHaveBeenCalledTimes(1); - }); - - it("coalesces burst invalidations so one root cannot occupy every inspection slot", async () => { - let releaseOld!: (value: ManifestNameInspection) => void; - let releaseLatest!: (value: ManifestNameInspection) => void; - const oldInspection = new Promise((resolve) => { - releaseOld = resolve; - }); - const latestInspection = new Promise((resolve) => { - releaseLatest = resolve; - }); - const inspectManifestName = vi - .fn<() => Promise>() - .mockReturnValueOnce(oldInspection) - .mockReturnValueOnce(latestInspection); - const changed = vi.fn(); - const sourceRoot = `${WORKSPACE}/agent`; - const inventory = provider([workflow("Agent", "agent", "marker")], { - inspectManifestName, - onIdentityChange: changed, - }); - - (await inventory.listAgents(SCOPE)).startEnrichment?.(); - await vi.waitFor(() => - expect(inspectManifestName).toHaveBeenCalledTimes(1), - ); - for (let index = 0; index < 6; index += 1) { - inventory.invalidateSource(sourceRoot); - (await inventory.listAgents(SCOPE)).startEnrichment?.(); - } - expect(inspectManifestName).toHaveBeenCalledTimes(1); - - releaseOld({ status: "found", name: "Old" }); - await vi.waitFor(() => - expect(inspectManifestName).toHaveBeenCalledTimes(2), - ); - expect(changed).not.toHaveBeenCalled(); - releaseLatest({ status: "found", name: "Latest" }); - await vi.waitFor(() => expect(changed).toHaveBeenCalledTimes(1)); - expect( - (await inventory.listAgents(SCOPE)).inventory.agents[0]?.agentKey, - ).toBe("Latest"); - }); - - it("does not let an active inspection repopulate identity after clear", async () => { - let release!: (value: ManifestNameInspection) => void; - const inspection = new Promise((resolve) => { - release = resolve; - }); - const inspectManifestName = vi.fn(() => inspection); - const changed = vi.fn(); - const inventory = provider([workflow("Agent", "agent", "marker")], { - inspectManifestName, - onIdentityChange: changed, - }); - - (await inventory.listAgents(SCOPE)).startEnrichment?.(); - await vi.waitFor(() => - expect(inspectManifestName).toHaveBeenCalledTimes(1), - ); - inventory.clear(); - release({ status: "found", name: "Retired" }); - await vi.waitFor(() => expect(changed).not.toHaveBeenCalled()); - - expect( - (await inventory.listAgents(SCOPE)).inventory.agents[0], - ).toMatchObject({ - agentKey: "marker", - identityIssue: "identity-pending", - }); - }); - - it("prunes settled identity state for a removed registry root", async () => { - const inspectManifestName = vi.fn(async () => ({ - status: "found" as const, - name: "Settled", - })); - const changed = vi.fn(); - const sourceRoot = `${WORKSPACE}/agent`; - const inventory = provider([workflow("Agent", "agent", "marker")], { - inspectManifestName, - onIdentityChange: changed, - }); - await enrich(inventory, await inventory.listAgents(SCOPE), changed); - - inventory.retainSources(new Set()); - const readded = await inventory.listAgents(SCOPE); - - expect(readded.inventory.agents[0]).toMatchObject({ - agentKey: "marker", - identityIssue: "identity-pending", - }); - expect(sourceRoot).toBe(readded.context[0]?.sourceRoot); - }); - - it("invalidates an in-flight inspection when its source root retires", async () => { - let release!: (value: ManifestNameInspection) => void; - const pending = new Promise((resolve) => { - release = resolve; - }); - const inspectManifestName = vi.fn(() => pending); - const changed = vi.fn(); - const inventory = provider([workflow("Agent", "agent", "marker")], { - inspectManifestName, - onIdentityChange: changed, - }); - - (await inventory.listAgents(SCOPE)).startEnrichment?.(); - await vi.waitFor(() => - expect(inspectManifestName).toHaveBeenCalledTimes(1), - ); - inventory.retainSources(new Set()); - release({ status: "found", name: "Retired" }); - await Promise.resolve(); - await Promise.resolve(); - - expect(changed).not.toHaveBeenCalled(); - expect( - (await inventory.listAgents(SCOPE)).inventory.agents[0], - ).toMatchObject({ - agentKey: "marker", - identityIssue: "identity-pending", - }); - }); - - it("serves a cached identity immediately and refreshes it after a missed edit", async () => { - let fingerprint = "v1"; - const inspectManifestName = vi - .fn<() => Promise>() - .mockResolvedValueOnce({ status: "found", name: "Before" }) - .mockResolvedValueOnce({ status: "found", name: "After" }); - const changed = vi.fn(); - const inventory = provider([workflow("Agent", "agent", "marker")], { - inspectManifestName, - fingerprintSource: async () => fingerprint, - revalidateMarker: async () => true, - onIdentityChange: changed, - }); - const before = await enrich( - inventory, - await inventory.listAgents(SCOPE), - changed, - ); - expect(before.inventory.agents[0]?.agentKey).toBe("Before"); - - changed.mockClear(); - fingerprint = "v2"; - const immediate = await inventory.listAgents(SCOPE); - expect(immediate.inventory.agents[0]?.agentKey).toBe("Before"); - immediate.startEnrichment?.(); - await vi.waitFor(() => expect(changed).toHaveBeenCalledTimes(1)); - expect( - (await inventory.listAgents(SCOPE)).inventory.agents[0]?.agentKey, - ).toBe("After"); - }); - - it("preserves a settled identity when background fingerprinting fails", async () => { - let fingerprintFails = false; - const fingerprintSource = vi.fn(async () => { - if (fingerprintFails) throw new Error("stat failed"); - return "v1"; - }); - const inspectManifestName = vi.fn(async () => ({ - status: "found" as const, - name: "Before", - })); - const changed = vi.fn(); - const inventory = provider([workflow("Agent", "agent", "marker")], { - inspectManifestName, - fingerprintSource, - onIdentityChange: changed, - }); - await enrich(inventory, await inventory.listAgents(SCOPE), changed); - - changed.mockClear(); - fingerprintFails = true; - const cached = await inventory.listAgents(SCOPE); - expect(cached.inventory.agents[0]?.agentKey).toBe("Before"); - cached.startEnrichment?.(); - await vi.waitFor(() => expect(fingerprintSource).toHaveBeenCalledTimes(2)); - - expect( - (await inventory.listAgents(SCOPE)).inventory.agents[0]?.agentKey, - ).toBe("Before"); - expect(changed).not.toHaveBeenCalled(); - }); - - it("degrades when a changed fingerprint is observed but inspection fails", async () => { - let fingerprint = "v1"; - const inspectManifestName = vi - .fn<() => Promise>() - .mockResolvedValueOnce({ status: "found", name: "Before" }) - .mockRejectedValueOnce(new Error("bundle failed")); - const changed = vi.fn(); - const inventory = provider([workflow("Agent", "agent", "marker")], { - inspectManifestName, - fingerprintSource: async () => fingerprint, - onIdentityChange: changed, - }); - await enrich(inventory, await inventory.listAgents(SCOPE), changed); - - fingerprint = "v2"; - changed.mockClear(); - const cached = await inventory.listAgents(SCOPE); - cached.startEnrichment?.(); - await vi.waitFor(() => expect(changed).toHaveBeenCalledTimes(1)); - const degraded = await inventory.listAgents(SCOPE); - - expect(degraded.inventory.agents[0]).toMatchObject({ - agentKey: "marker", - identityIssue: "identity-unavailable", - }); - expect(degraded.warnings).toEqual([ - expect.objectContaining({ code: "inventory-extraction-failed" }), - ]); - }); - - it("reinspects a retired root when it is later re-added", async () => { - const registered = workflow("Agent", "agent", "marker"); - let workflows: WorkflowInfo[] = [registered]; - let fingerprint = "v1"; - const inspectManifestName = vi - .fn<() => Promise>() - .mockResolvedValueOnce({ status: "found", name: "Before" }) - .mockResolvedValueOnce({ status: "found", name: "After" }); - const changed = vi.fn(); - const inventory = new HarnessRegistryInventoryProvider({ - listWorkflows: () => workflows, - inspectManifestName, - fingerprintSource: async () => fingerprint, - revalidateMarker: async () => true, - onIdentityChange: changed, - }); - await enrich(inventory, await inventory.listAgents(SCOPE), changed); - - workflows = []; - expect((await inventory.listAgents(SCOPE)).inventory.agents).toEqual([]); - fingerprint = "v2"; - workflows = [registered]; - changed.mockClear(); - const readded = await inventory.listAgents(SCOPE); - expect(readded.inventory.agents[0]?.agentKey).toBe("marker"); - readded.startEnrichment?.(); - await vi.waitFor(() => expect(changed).toHaveBeenCalledTimes(1)); - expect( - (await inventory.listAgents(SCOPE)).inventory.agents[0]?.agentKey, - ).toBe("After"); - }); - - it("computes an order- and checkout-invariant revision without private metadata", async () => { - const left = provider([ - workflow("Zeta label", "zeta", "zeta", { definitionId: 1 }), - workflow("Alpha label", "alpha", "alpha", { definitionId: 2 }), - ]); - const otherRoot = "/different/checkout"; - const right = provider([ - { - ...workflow("Private label changed", "alpha", "alpha", { - definitionId: 999, - }), - path: `${otherRoot}/alpha`, - }, - { - ...workflow("Other private label", "zeta", "zeta", { - definitionId: null, - }), - path: `${otherRoot}/zeta`, - }, - ]); - - const leftResult = await left.listAgents(SCOPE); - const rightResult = await right.listAgents({ - workspaceKey: SCOPE.workspaceKey, - root: otherRoot, - }); - expect(leftResult.inventory.agents.map((agent) => agent.agentKey)).toEqual([ - "alpha", - "zeta", - ]); - expect(leftResult.inventory.version).toEqual(rightResult.inventory.version); - }); - - it("uses a checkout-invariant local identity for a markerless root agent", async () => { - const otherRoot = "/different/checkout"; - const left = await provider([ - workflow("Left checkout", "", null), - ]).listAgents(SCOPE); - const right = await provider([ - { - ...workflow("Right checkout", "", null), - path: otherRoot, - }, - ]).listAgents({ workspaceKey: SCOPE.workspaceKey, root: otherRoot }); - - expect(left.inventory.agents).toEqual([ - expect.objectContaining({ agentKey: "local:root", path: "." }), - ]); - expect(left.inventory.version).toEqual(right.inventory.version); - }); - - it("resolves colliding local fallbacks without canonical duplicate metadata", async () => { - const workflows = [ - workflow("Package root", "", null), - workflow("Root child", "root", null), - workflow("Suffix child", "root~2", null), - ]; - const forward = await provider(workflows).listAgents(SCOPE); - const reversed = await provider([...workflows].reverse()).listAgents(SCOPE); - - expect(forward.inventory).toEqual(reversed.inventory); - expect(forward.inventory.agents).toEqual([ - expect.objectContaining({ - agentKey: "local:root", - identityIssue: "identity-unavailable", - path: ".", - }), - expect.objectContaining({ - agentKey: "local:root~2", - identityIssue: "identity-unavailable", - path: "root", - }), - expect.objectContaining({ - agentKey: "local:root~2~2", - identityIssue: "identity-unavailable", - path: "root~2", - }), - ]); - expect(forward.warnings).toEqual([]); - expect( - forward.inventory.agents.every( - (agent) => agent.identityIssue !== "duplicate-agent-key", - ), - ).toBe(true); - }); - - it("deduplicates exact registry roots independently of registry order", async () => { - const alpha = workflow("Alpha", "agent", "alpha", { definitionId: 1 }); - const zeta = workflow("Zeta", "agent", "zeta", { definitionId: 2 }); - const forward = await provider([zeta, alpha]).listAgents(SCOPE); - const reversed = await provider([alpha, zeta]).listAgents(SCOPE); - - expect(forward.inventory).toEqual(reversed.inventory); - expect(forward.inventory.agents).toEqual([ - expect.objectContaining({ agentKey: "alpha", path: "agent" }), - ]); - expect(forward.inventory.version).toEqual(reversed.inventory.version); - }); - - it("includes nested agents in every containing selected project", async () => { - const workflows = [ - workflow("Root", "", "root"), - workflow("Parent", "research", "research"), - workflow("Nested", "experiments/evaluator", "evaluator"), - { - ...workflow("Outside", "outside", "outside"), - path: `${WORKSPACE}-old/outside`, - }, - ]; - const parent = await provider(workflows).listAgents(SCOPE); - const nested = await provider(workflows).listAgents({ - workspaceKey: "workspace-experiments", - root: `${WORKSPACE}/experiments`, - }); - - expect(parent.inventory.agents.map((agent) => agent.path)).toEqual([ - "experiments/evaluator", - "research", - ".", - ]); - expect(nested.inventory.agents.map((agent) => agent.path)).toEqual([ - "evaluator", - ]); - }); - - it("matches canonical workflow roots beneath a symlinked workspace", async () => { - if (process.platform === "win32") return; - const tempRoot = await fs.mkdtemp( - path.join(os.tmpdir(), "inventory-symlink-"), - ); - try { - const workspaceRoot = path.join(tempRoot, "real-workspace"); - const agentRoot = path.join(workspaceRoot, "agent"); - const nestedRoot = path.join(agentRoot, "nested-agent"); - const outsideRoot = path.join(tempRoot, "outside", "agent"); - const linkedRoot = path.join(tempRoot, "linked-workspace"); - await Promise.all([ - fs.mkdir(nestedRoot, { recursive: true }), - fs.mkdir(outsideRoot, { recursive: true }), - ]); - await fs.symlink(workspaceRoot, linkedRoot, "dir"); - - expect( - dirtyGraphSourceRoots( - linkedRoot, - [agentRoot, nestedRoot], - [path.join(linkedRoot, "agent", "nested-agent", "index.ts")], - ), - ).toEqual([await fs.realpath(nestedRoot)]); - } finally { - await fs.rm(tempRoot, { recursive: true, force: true }); - } - }); - - it("fails the provider call when the registry snapshot cannot be read", async () => { - const inventory = new HarnessRegistryInventoryProvider({ - listWorkflows: async () => { - throw new Error("registry unavailable"); - }, - }); - await expect(inventory.listAgents(SCOPE)).rejects.toThrow( - "registry unavailable", - ); - }); -}); diff --git a/packages/harness/src/core/system-graph-inventory.ts b/packages/harness/src/core/system-graph-inventory.ts deleted file mode 100644 index 337b2c2bc..000000000 --- a/packages/harness/src/core/system-graph-inventory.ts +++ /dev/null @@ -1,1033 +0,0 @@ -import type { WorkspaceScope } from "./workspace-scope-catalog.js"; -import type { WorkspaceKey } from "../shared/workspace-scope.js"; -export type { WorkspaceScope } from "./workspace-scope-catalog.js"; -import { isWithinWorkspacePath as isWithinGraphPath, sourceRootsWithinScope as graphSourceRootsWithinScope } from "./workspace-path.js"; -export { isWithinWorkspacePath as isWithinGraphPath, sourceRootsWithinScope as graphSourceRootsWithinScope } from "./workspace-path.js"; -import { createHash } from "node:crypto"; -import * as path from "node:path"; - -import { - PACKAGE_INVENTORY_PROTOCOL, - packageInventorySchema, - type PackageInventory, - type PackageInventoryAgent, -} from "@sapiom/agent"; - -import { - type AgentKey, - type GraphWarning, -} from "../shared/system-graph.js"; -import type { RegistryWorkflowInfo as WorkflowInfo } from "./workflow-registry.js"; -import { fingerprintWorkflowSources } from "./canvas-cache.js"; -import { canonicalGraphPath } from "./canonical-graph-path.js"; -import type { - ManifestNameInspection, - ManifestNameInspectionOptions, -} from "./definition-name.js"; -import { inspectAgentProjectMarker } from "./agent-project-discovery.js"; - -export { canonicalGraphPath } from "./canonical-graph-path.js"; - -/** Harness-only evidence paired with one public inventory record. */ -export interface AgentInventoryContextItem { - agentKey: AgentKey; - /** Internal deployment provenance. Never serialize this into SystemGraph. */ - definitionId: number | null; - definitionSlug: string | null; - label: string; - /** Marker/source compatibility aliases. Never cross the graph HTTP boundary. */ - resolutionAliases: string[]; - /** Canonical filesystem evidence. Never serialize this into SystemGraph. */ - sourceRoot: string; - /** Registry-owned navigation target, served only by the protected resolver. */ - workflowPath: string; - /** Joins this context to the public record without relying on array order. */ - path: string; - entrypoint: string; -} - -/** Builder-facing item after the public contract and private context are joined. */ -export interface AgentInventoryItem extends AgentInventoryContextItem { - /** Parsed public evidence used to keep authoritative keys above aliases. */ - identityStatus: PackageInventoryAgent["identityStatus"]; -} - -export interface AgentInventoryWarning { - code: Extract< - GraphWarning["code"], - "duplicate-agent-key" | "inventory-extraction-failed" - >; - agentKey: AgentKey; - message: string; -} - -export interface AgentInventoryResult { - inventory: PackageInventory; - context: AgentInventoryContextItem[]; - warnings: AgentInventoryWarning[]; - /** - * Private lifecycle state: false while an unchanged source could still - * resolve to a different identity. This stays outside PackageInventory so - * the public contract continues to answer only what exists and where. - */ - identitySettled: boolean; - /** - * Private discovery coverage: false when the accepted workspace scan could - * not prove that every eligible agent was considered. This is independent - * of identity settlement because a settled provisional identity is still a - * cacheable result, while an incomplete workspace walk is not. - */ - discoveryComplete: boolean; - /** Starts source identity work only after the provisional graph is committed. */ - startEnrichment?: () => void; -} - -/** Read-only boundary between Studio's registry and graph projection. */ -export interface AgentInventoryProvider { - listAgents(scope: WorkspaceScope): Promise; - /** Prunes private identity state for roots no active graph can reference. */ - retainSources?(sourceRoots: ReadonlySet): void; -} - -type ManifestNameInspector = ( - sourceRoot: string, - options?: ManifestNameInspectionOptions, -) => Promise; - -export interface HarnessRegistryInventoryProviderOptions { - listWorkflows: () => - | readonly WorkflowInfo[] - | Promise; - inspectManifestName?: ManifestNameInspector; - /** Hardened launch-time marker proof; injectable for filesystem-free tests. */ - revalidateMarker?: (sourceRoot: string) => Promise; - /** Last discovery completeness for this exact selected scope. */ - inventoryStatus?: ( - scope: WorkspaceScope, - ) => "complete" | "degraded" | Promise<"complete" | "degraded">; - /** Atomic registry/cache projection; preferred over separate legacy reads. */ - inventorySnapshot?: (scope: WorkspaceScope) => - | { - workflows: readonly WorkflowInfo[]; - status: "complete" | "degraded"; - generation: number; - canonicalScopeRoot?: string; - canonicalWorkflowRoots?: readonly { - workflowPath: string; - canonicalRoot: string; - identityEvidence: "marker" | "source" | "not-agent" | "unknown"; - }[]; - } - | Promise<{ - workflows: readonly WorkflowInfo[]; - status: "complete" | "degraded"; - generation: number; - canonicalScopeRoot?: string; - canonicalWorkflowRoots?: readonly { - workflowPath: string; - canonicalRoot: string; - identityEvidence: "marker" | "source" | "not-agent" | "unknown"; - }[]; - }>; - /** - * Called with coalesced identity changes. Settled roots are surfaced within - * a short bounded window, while a fully drained queue flushes immediately. - */ - onIdentityChange?: (sourceRoots: readonly string[]) => void | Promise; - /** Test seam. Production uses the same fingerprint as Canvas extraction. */ - fingerprintSource?: (sourceRoot: string) => Promise; - /** Test seam for the bounded identity-change coalescing window. */ - identityChangeCoalesceMs?: number; -} - -const MANIFEST_INSPECTION_CONCURRENCY = 4; -const IDENTITY_CHANGE_COALESCE_MS = 250; -const ENTRYPOINT = "index.ts"; -const ZERO_REVISION = `sha256:${"0".repeat(64)}` as const; -function hasControlCharacter(value: string): boolean { - return [...value].some((character) => { - const code = character.codePointAt(0)!; - return code <= 0x1f || (code >= 0x7f && code <= 0x9f); - }); -} - -type InventoryIdentityIssue = Exclude< - PackageInventoryAgent["identityIssue"], - undefined ->; - -function isWindowsAbsolute(input: string): boolean { - return ( - /^[A-Za-z]:[\\/]/.test(input) || /^[\\/]{2}[^\\/]+[\\/][^\\/]+/.test(input) - ); -} - -function pathApi(input: string): typeof path.posix { - return isWindowsAbsolute(input) ? path.win32 : path.posix; -} - -/** - * Resolve with the input path's own flavor so mixed Windows separators remain - * comparable even when the test process (or a future remote host) is POSIX. - */ -/** - * Resolve a public package-relative inventory path against its workspace. - * The inventory path is always POSIX, while the workspace path keeps the - * host's native drive/UNC/POSIX flavor. Canonicalization also resolves a - * symlinked workspace before this value is compared with private context. - */ -export function inventorySourceRoot( - scopeRoot: string, - inventoryPath: string, -): string { - const api = pathApi(scopeRoot); - const joined = - inventoryPath === "." - ? scopeRoot - : api.join(scopeRoot, ...inventoryPath.split("/")); - return canonicalGraphPath(joined); -} - -/** - * Attribute exact source edits to the deepest registered project roots. - * A null path list is the polling/ambiguous-event fallback. - */ -export function dirtyGraphSourceRoots( - scopeRoot: string, - sourceRoots: readonly string[], - sourcePaths: readonly string[] | null, -): string[] { - const roots = graphSourceRootsWithinScope(scopeRoot, sourceRoots); - if (sourcePaths === null) return roots; - - const dirty = new Set(); - for (const sourcePath of sourcePaths) { - const canonicalSourcePath = canonicalGraphPath(sourcePath); - const matches = roots.filter((sourceRoot) => - isWithinGraphPath(sourceRoot, canonicalSourcePath), - ); - for (const match of matches) { - if ( - !matches.some( - (candidate) => - candidate !== match && isWithinGraphPath(match, candidate), - ) - ) { - dirty.add(match); - } - } - } - return [...dirty].sort(); -} - -function canonicalIdentity(value: string | null): string | null { - const identity = value?.trim() ?? ""; - if ( - identity === "" || - identity === "." || - identity === ".." || - identity.startsWith("local:") || - hasControlCharacter(identity) || - identity.includes("/") || - identity.includes("\\") || - path.posix.isAbsolute(identity) || - path.win32.isAbsolute(identity) - ) { - return null; - } - return identity; -} - -function safeLabel(value: string, fallback: string): string { - const label = value.trim(); - if ( - label === "" || - hasControlCharacter(label) || - path.posix.isAbsolute(label) || - path.win32.isAbsolute(label) - ) { - return fallback; - } - return label; -} - -function uniqueAliases(values: Array): string[] { - return [ - ...new Set(values.filter((value): value is string => value !== null)), - ].sort(compareText); -} - -function compareText(left: string, right: string): number { - return left === right ? 0 : left < right ? -1 : 1; -} - -function packageRelativePath( - scopeRoot: string, - workflowPath: string, - knownCanonicalScope?: string, - knownCanonicalSource?: string, -): string { - const api = pathApi(scopeRoot); - const relative = api.relative(scopeRoot, workflowPath); - if ( - relative !== "" && - relative !== ".." && - !relative.startsWith(`..${api.sep}`) && - !api.isAbsolute(relative) - ) { - return relative.split(api.sep).join("/"); - } - if (relative === "") return "."; - - // A symlinked registry path can have a different lexical spelling. Its - // canonical source was already proven inside the canonical scope. - const canonicalScope = knownCanonicalScope ?? canonicalGraphPath(scopeRoot); - const canonicalSource = - knownCanonicalSource ?? canonicalGraphPath(workflowPath); - const canonicalApi = pathApi(canonicalScope); - const canonicalRelative = canonicalApi.relative( - canonicalScope, - canonicalSource, - ); - return canonicalRelative === "" - ? "." - : canonicalRelative.split(canonicalApi.sep).join("/"); -} - -function stableJson(value: unknown): string { - if (value === null || typeof value !== "object") return JSON.stringify(value); - if (Array.isArray(value)) { - return `[${value.map((item) => stableJson(item)).join(",")}]`; - } - const entries = Object.entries(value as Record) - .filter(([, child]) => child !== undefined) - .sort(([left], [right]) => compareText(left, right)); - return `{${entries - .map(([key, child]) => `${JSON.stringify(key)}:${stableJson(child)}`) - .join(",")}}`; -} - -function buildWorkingTreeInventory( - workspaceKey: WorkspaceKey, - agents: PackageInventoryAgent[], - discoveryStatus: "complete" | "degraded", -): PackageInventory { - const status = - discoveryStatus === "degraded" || - agents.some((agent) => agent.identityStatus === "provisional") - ? "degraded" - : "complete"; - const normalized = packageInventorySchema.parse({ - protocol: PACKAGE_INVENTORY_PROTOCOL, - version: { - kind: "working-tree", - workspaceKey, - revision: ZERO_REVISION, - }, - status, - agents, - }); - const revision = `sha256:${createHash("sha256") - .update( - stableJson({ - protocol: normalized.protocol, - status: normalized.status, - agents: normalized.agents, - }), - ) - .digest("hex")}` as const; - return { - ...normalized, - version: { kind: "working-tree", workspaceKey, revision }, - }; -} - -interface PreparedAgent { - canonicalName: string | null; - candidateKey: AgentKey; - fallbackKey: AgentKey; - identityIssue: InventoryIdentityIssue | null; - identitySettled: boolean; - definitionId: number | null; - definitionSlug: string | null; - label: string; - markerAlias: string | null; - path: string; - sourceRoot: string; - workflowPath: string; - warnOnIdentityFailure: boolean; -} - -interface IdentityCacheEntry { - fingerprint: string | null; - inspection: ManifestNameInspection; -} - -interface IdentityTask { - sourceRoot: string; - generation: number; - epoch: number; - freshnessEpoch: number; - authorization: "marker" | "linked"; -} - -function preparedOrder(left: PreparedAgent, right: PreparedAgent): number { - return ( - compareText(left.candidateKey, right.candidateKey) || - compareText(left.path, right.path) || - compareText(left.sourceRoot, right.sourceRoot) - ); -} - -function warningOrder( - left: AgentInventoryWarning, - right: AgentInventoryWarning, -): number { - return ( - compareText(left.code, right.code) || - compareText(left.agentKey, right.agentKey) || - compareText(left.message, right.message) - ); -} - -function workflowRegistryOrder( - scopeRoot: string, - left: { workflow: WorkflowInfo; sourceRoot: string }, - right: { workflow: WorkflowInfo; sourceRoot: string }, -): number { - const leftWorkflow = left.workflow; - const rightWorkflow = right.workflow; - return ( - compareText(left.sourceRoot, right.sourceRoot) || - compareText( - packageRelativePath(scopeRoot, leftWorkflow.path), - packageRelativePath(scopeRoot, rightWorkflow.path), - ) || - compareText( - leftWorkflow.definitionSlug ?? "", - rightWorkflow.definitionSlug ?? "", - ) || - compareText(leftWorkflow.name, rightWorkflow.name) || - (leftWorkflow.definitionId ?? -1) - (rightWorkflow.definitionId ?? -1) || - compareText(leftWorkflow.source, rightWorkflow.source) || - compareText(leftWorkflow.path, rightWorkflow.path) - ); -} - -/** - * Local transition adapter from WorkflowRegistry to the public package - * inventory contract. Registry reads are immediate. Source definition names - * enrich provisional identities only after that first graph revision commits. - */ -export class HarnessRegistryInventoryProvider implements AgentInventoryProvider { - private readonly identityCache = new Map(); - private readonly generations = new Map(); - private readonly queuedTasks: IdentityTask[] = []; - private readonly activeTasks = new Map(); - private readonly pendingIdentityChanges = new Set(); - private activeInspections = 0; - private identityChangeFlushInFlight = false; - private identityChangeTimer: ReturnType | null = null; - private epoch = 0; - private nextGeneration = 1; - private latestInventoryGeneration = -1; - private freshnessEpoch = 0; - - constructor( - private readonly options: HarnessRegistryInventoryProviderOptions, - ) {} - - async listAgents(scope: WorkspaceScope): Promise { - let snapshot = this.options.inventorySnapshot - ? await this.options.inventorySnapshot(scope) - : null; - for ( - let retry = 0; - snapshot && - snapshot.generation < this.latestInventoryGeneration && - retry < 3; - retry += 1 - ) { - snapshot = await this.options.inventorySnapshot!(scope); - } - if (snapshot && snapshot.generation < this.latestInventoryGeneration) { - throw new Error( - "Inventory snapshot was superseded by a newer generation", - ); - } - if (snapshot) { - this.latestInventoryGeneration = Math.max( - this.latestInventoryGeneration, - snapshot.generation, - ); - } - const [workflows, discoveryStatus] = snapshot - ? [snapshot.workflows, snapshot.status] - : await Promise.all([ - this.options.listWorkflows(), - this.options.inventoryStatus?.(scope) ?? "complete", - ]); - const canonicalEntries = new Map( - snapshot?.canonicalWorkflowRoots?.map((entry) => [ - entry.workflowPath, - entry, - ]) ?? [], - ); - const canonicalScopeRoot = - snapshot?.canonicalScopeRoot ?? canonicalGraphPath(scope.root); - const bySourceRoot = new Map< - string, - { - workflow: WorkflowInfo; - sourceRoot: string; - identityEvidence: "marker" | "source" | "not-agent" | "unknown"; - } - >(); - const projected = workflows.map((workflow) => { - const canonicalEntry = canonicalEntries.get(workflow.path); - return { - workflow, - sourceRoot: - canonicalEntry?.canonicalRoot ?? canonicalGraphPath(workflow.path), - identityEvidence: - canonicalEntry?.identityEvidence ?? - (Object.prototype.hasOwnProperty.call( - workflow, - "sourceDefinitionName", - ) - ? "source" - : workflow.markerPresent === true - ? "marker" - : "unknown"), - } as const; - }); - this.retainSources(new Set(projected.map(({ sourceRoot }) => sourceRoot))); - const contained = projected - .filter(({ sourceRoot }) => - isWithinGraphPath(canonicalScopeRoot, sourceRoot), - ) - .sort((left, right) => workflowRegistryOrder(scope.root, left, right)); - for (const { workflow, sourceRoot, identityEvidence } of contained) { - // Registry persistence is expected to be unique by path. Keep the first - // deterministic row if a corrupt/legacy file contains an exact duplicate. - if (!bySourceRoot.has(sourceRoot)) { - bySourceRoot.set(sourceRoot, { - workflow, - sourceRoot, - identityEvidence, - }); - } - } - - const inspectionRoots: Array<{ - sourceRoot: string; - authorization: "marker" | "linked"; - }> = []; - let consumedUnknownPersistedIdentity = false; - const prepared = [...bySourceRoot.values()] - .map(({ workflow, sourceRoot, identityEvidence }): PreparedAgent => { - const inventoryPath = packageRelativePath( - scope.root, - workflow.path, - canonicalScopeRoot, - sourceRoot, - ); - const fallbackKey = `local:${ - inventoryPath === "." ? "root" : inventoryPath - }` as AgentKey; - const markerAlias = canonicalIdentity(workflow.definitionSlug); - const cached = this.identityCache.get(sourceRoot); - let canonicalName: string | null = null; - let identityIssue: InventoryIdentityIssue | null = null; - let identitySettled = true; - let warnOnIdentityFailure = false; - const hasPersistedSourceIdentity = - Object.prototype.hasOwnProperty.call( - workflow, - "sourceDefinitionName", - ) && - (identityEvidence === "source" || identityEvidence === "unknown"); - if (hasPersistedSourceIdentity) { - this.retireInspectionSource(sourceRoot); - consumedUnknownPersistedIdentity ||= identityEvidence === "unknown"; - const sourceDefinitionName = workflow.sourceDefinitionName ?? null; - canonicalName = canonicalIdentity(sourceDefinitionName); - if (!canonicalName) { - identityIssue = sourceDefinitionName - ? "identity-invalid" - : "identity-unavailable"; - } - } else if ( - identityEvidence !== "marker" && - workflow.definitionId === null - ) { - this.retireInspectionSource(sourceRoot); - identityIssue = "identity-unavailable"; - } else if (!this.options.inspectManifestName) { - identityIssue = "identity-unavailable"; - } else { - inspectionRoots.push({ - sourceRoot, - authorization: identityEvidence === "marker" ? "marker" : "linked", - }); - this.ensureGeneration(sourceRoot); - if (!cached) { - identityIssue = "identity-pending"; - identitySettled = false; - } else if (cached.inspection.status === "found") { - canonicalName = canonicalIdentity(cached.inspection.name); - if (!canonicalName) { - identityIssue = "identity-invalid"; - warnOnIdentityFailure = true; - } - } else { - identityIssue = "identity-unavailable"; - warnOnIdentityFailure = cached.inspection.status === "failed"; - identitySettled = - cached.inspection.status !== "failed" || - !cached.inspection.retryable; - } - } - const candidateKey = canonicalName ?? markerAlias ?? fallbackKey; - return { - canonicalName, - candidateKey, - fallbackKey, - identityIssue, - identitySettled, - definitionId: workflow.definitionId, - definitionSlug: markerAlias, - label: safeLabel( - workflow.name, - canonicalName ?? markerAlias ?? fallbackKey.slice("local:".length), - ), - markerAlias, - path: inventoryPath, - sourceRoot, - workflowPath: workflow.path, - warnOnIdentityFailure, - }; - }) - .sort(preparedOrder); - - const canonicalCounts = new Map(); - const provisionalCounts = new Map(); - const candidateCounts = new Map(); - for (const agent of prepared) { - candidateCounts.set( - agent.candidateKey, - (candidateCounts.get(agent.candidateKey) ?? 0) + 1, - ); - // An unsettled candidate is a guess, not a claim. Two agents that share - // a registry marker while source identity is pending or retryable are - // not yet a collision. - if (!agent.identitySettled) continue; - const counts = agent.canonicalName ? canonicalCounts : provisionalCounts; - counts.set(agent.candidateKey, (counts.get(agent.candidateKey) ?? 0) + 1); - } - - const warnings: AgentInventoryWarning[] = []; - const candidates = new Set([ - ...canonicalCounts.keys(), - ...provisionalCounts.keys(), - ]); - for (const candidateKey of [...candidates].sort(compareText)) { - const canonicalCount = canonicalCounts.get(candidateKey) ?? 0; - const provisionalCount = provisionalCounts.get(candidateKey) ?? 0; - const ambiguous = - canonicalCount > 1 || (canonicalCount === 0 && provisionalCount > 1); - if (!ambiguous || canonicalIdentity(candidateKey) === null) continue; - warnings.push({ - code: "duplicate-agent-key", - agentKey: candidateKey, - message: `Multiple agents use ${candidateKey}; kept each with a local identity.`, - }); - } - - const used = new Set(); - const publicAgents: PackageInventoryAgent[] = []; - const context: AgentInventoryContextItem[] = []; - for (const agent of prepared) { - const canonicalCount = canonicalCounts.get(agent.candidateKey) ?? 0; - const provisionalCount = provisionalCounts.get(agent.candidateKey) ?? 0; - const safeCandidate = canonicalIdentity(agent.candidateKey) !== null; - const duplicate = - safeCandidate && - (agent.canonicalName - ? canonicalCount > 1 - : canonicalCount > 1 || - (canonicalCount === 0 && provisionalCount > 1)); - const shadowedByCanonical = - agent.canonicalName === null && canonicalCount === 1; - // A shared unsettled marker is still only a guess, so it cannot honestly - // serve as either agent's unique public key. Keep both rows provisional - // under their deterministic locations until inspection settles them. - const sharedUnsettledCandidate = - !agent.identitySettled && - (candidateCounts.get(agent.candidateKey) ?? 0) > 1; - let agentKey = - duplicate || shadowedByCanonical || sharedUnsettledCandidate - ? agent.fallbackKey - : agent.candidateKey; - const base = agentKey; - let suffix = 2; - while (used.has(agentKey)) { - agentKey = `${base}~${suffix}`; - suffix += 1; - } - used.add(agentKey); - - const canonical = agent.canonicalName !== null && !duplicate; - const identityIssue = duplicate - ? "duplicate-agent-key" - : agent.identityIssue; - let publicAgent: PackageInventoryAgent; - if (canonical) { - publicAgent = { - agentKey, - identityStatus: "canonical", - path: agent.path, - entrypoint: ENTRYPOINT, - }; - } else if (duplicate) { - const candidateAgentKey = canonicalIdentity(agent.candidateKey); - if (!candidateAgentKey) { - throw new Error("Duplicate inventory identity had no safe candidate"); - } - publicAgent = { - agentKey, - identityStatus: "provisional", - identityIssue: "duplicate-agent-key", - candidateAgentKey, - path: agent.path, - entrypoint: ENTRYPOINT, - }; - } else { - const provisionalIssue = - identityIssue === "duplicate-agent-key" || identityIssue === null - ? "identity-unavailable" - : identityIssue; - publicAgent = { - agentKey, - identityStatus: "provisional", - identityIssue: provisionalIssue, - path: agent.path, - entrypoint: ENTRYPOINT, - }; - } - publicAgents.push(publicAgent); - - const resolutionAliases = uniqueAliases([ - agent.markerAlias, - duplicate ? canonicalIdentity(agent.candidateKey) : null, - ]); - context.push({ - agentKey, - definitionId: agent.definitionId, - definitionSlug: agent.definitionSlug, - label: agent.label, - resolutionAliases, - sourceRoot: agent.sourceRoot, - workflowPath: agent.workflowPath, - path: agent.path, - entrypoint: ENTRYPOINT, - }); - if (!canonical && agent.warnOnIdentityFailure && !duplicate) { - warnings.push({ - code: "inventory-extraction-failed", - agentKey, - message: `Could not resolve ${agent.label}'s source identity; using its provisional identity.`, - }); - } - } - - const inventory = buildWorkingTreeInventory( - scope.workspaceKey, - publicAgents, - consumedUnknownPersistedIdentity ? "degraded" : discoveryStatus, - ); - const contextByAgent = new Map( - context.map((item) => [item.agentKey, item]), - ); - const normalizedContext = inventory.agents.map((agent) => { - const item = contextByAgent.get(agent.agentKey); - if (!item) throw new Error("Package inventory context was incomplete"); - return item; - }); - warnings.sort(warningOrder); - const roots = [ - ...new Map( - inspectionRoots.map((entry) => [entry.sourceRoot, entry]), - ).values(), - ].sort((left, right) => compareText(left.sourceRoot, right.sourceRoot)); - const enrichmentEpoch = this.epoch; - const tasks = roots.map(({ sourceRoot, authorization }) => ({ - sourceRoot, - authorization, - generation: this.generations.get(sourceRoot)!, - epoch: enrichmentEpoch, - freshnessEpoch: this.freshnessEpoch, - })); - return { - inventory, - context: normalizedContext, - warnings, - identitySettled: prepared.every((agent) => agent.identitySettled), - discoveryComplete: - discoveryStatus === "complete" && !consumedUnknownPersistedIdentity, - ...(tasks.length > 0 - ? { - startEnrichment: () => - this.enqueueInspections(tasks, enrichmentEpoch), - } - : {}), - }; - } - - /** Drops settled/pending identity state after a relevant source edit. */ - invalidateSource(sourceRoot: string): void { - const key = canonicalGraphPath(sourceRoot); - this.identityCache.delete(key); - this.generations.set(key, this.nextGeneration++); - this.dropQueuedTasks(key); - this.pendingIdentityChanges.delete(key); - if (this.pendingIdentityChanges.size === 0) { - this.clearIdentityChangeTimer(); - } - } - - /** O(1) fail-closed invalidation for a raw change beneath a graph scope. */ - invalidateScope(_scopeRoot: string): void { - // Conservatively invalidate every queued/active V0 task. This is a true - // O(1) raw-event operation; queue cleanup happens when a worker slot next - // drains, and each task's captured epoch prevents it from launching or - // publishing in the meantime. - this.freshnessEpoch += 1; - } - - private retireInspectionSource(sourceRoot: string): void { - this.identityCache.delete(sourceRoot); - this.generations.delete(sourceRoot); - this.dropQueuedTasks(sourceRoot); - this.pendingIdentityChanges.delete(sourceRoot); - if (this.pendingIdentityChanges.size === 0) { - this.clearIdentityChangeTimer(); - } - } - - /** Explicit Retry may retry failures even when no source fingerprint changed. */ - retryFailedInspections(scope: WorkspaceScope): void { - const root = canonicalGraphPath(scope.root); - for (const [sourceRoot, cached] of this.identityCache) { - if ( - isWithinGraphPath(root, sourceRoot) && - (cached.inspection.status === "failed" || - (cached.inspection.status === "found" && - canonicalIdentity(cached.inspection.name) === null)) - ) { - this.invalidateSource(sourceRoot); - } - } - } - - clear(): void { - this.epoch += 1; - this.identityCache.clear(); - this.generations.clear(); - this.queuedTasks.length = 0; - this.pendingIdentityChanges.clear(); - this.freshnessEpoch += 1; - this.clearIdentityChangeTimer(); - } - - /** Drops cache, queue, and generation state for retired source roots. */ - retainSources(sourceRoots: ReadonlySet): void { - const retained = new Set([...sourceRoots].map(canonicalGraphPath)); - const known = new Set([ - ...this.identityCache.keys(), - ...this.generations.keys(), - ...this.queuedTasks.map((task) => task.sourceRoot), - ]); - for (const sourceRoot of known) { - if (retained.has(sourceRoot)) continue; - this.identityCache.delete(sourceRoot); - this.generations.delete(sourceRoot); - this.dropQueuedTasks(sourceRoot); - this.pendingIdentityChanges.delete(sourceRoot); - } - if (this.pendingIdentityChanges.size === 0) { - this.clearIdentityChangeTimer(); - } - } - - private enqueueInspections( - tasks: readonly IdentityTask[], - requestedEpoch: number, - ): void { - if (!this.options.inspectManifestName || requestedEpoch !== this.epoch) { - return; - } - for (const task of tasks) { - if (!this.isCurrentTask(task)) continue; - this.dropQueuedTasks(task.sourceRoot); - const active = this.activeTasks.get(task.sourceRoot); - if ( - active?.generation === task.generation && - active.epoch === task.epoch && - active.freshnessEpoch === task.freshnessEpoch - ) { - continue; - } - this.queuedTasks.push(task); - } - this.drainInspectionQueue(); - } - - private drainInspectionQueue(): void { - for (let index = this.queuedTasks.length - 1; index >= 0; index -= 1) { - if (!this.isCurrentTask(this.queuedTasks[index]!)) { - this.queuedTasks.splice(index, 1); - } - } - while (this.activeInspections < MANIFEST_INSPECTION_CONCURRENCY) { - const index = this.queuedTasks.findIndex( - (task) => !this.activeTasks.has(task.sourceRoot), - ); - if (index === -1) break; - const [task] = this.queuedTasks.splice(index, 1); - if (!task || !this.isCurrentTask(task)) continue; - this.activeTasks.set(task.sourceRoot, task); - this.activeInspections += 1; - void this.inspectSource(task).finally(() => { - if (this.activeTasks.get(task.sourceRoot) === task) { - this.activeTasks.delete(task.sourceRoot); - this.activeInspections -= 1; - } - this.drainInspectionQueue(); - }); - } - this.scheduleIdentityChangeFlush(); - } - - private async inspectSource(task: IdentityTask): Promise { - const inspect = this.options.inspectManifestName; - if (!inspect || !this.isCurrentTask(task)) return; - let fingerprint: string | null = null; - let inspection: ManifestNameInspection; - try { - if (task.authorization === "marker") { - const validMarker = this.options.revalidateMarker - ? await this.options.revalidateMarker(task.sourceRoot) - : (await inspectAgentProjectMarker(task.sourceRoot)).status === - "valid"; - if (!validMarker || !this.isCurrentTask(task)) return; - } - fingerprint = await ( - this.options.fingerprintSource ?? fingerprintWorkflowSources - )(task.sourceRoot); - if (!this.isCurrentTask(task)) return; - if (task.authorization === "marker") { - const validMarker = this.options.revalidateMarker - ? await this.options.revalidateMarker(task.sourceRoot) - : (await inspectAgentProjectMarker(task.sourceRoot)).status === - "valid"; - if (!validMarker || !this.isCurrentTask(task)) return; - } - const hit = this.identityCache.get(task.sourceRoot); - if (hit?.fingerprint === fingerprint) return; - inspection = await inspect(task.sourceRoot, { - authorizeBeforeLaunch: async () => { - if (!this.isCurrentTask(task)) return false; - if (task.authorization === "linked") return true; - const validMarker = this.options.revalidateMarker - ? await this.options.revalidateMarker(task.sourceRoot) - : (await inspectAgentProjectMarker(task.sourceRoot)).status === - "valid"; - return validMarker && this.isCurrentTask(task); - }, - }); - } catch { - if (!this.isCurrentTask(task)) return; - const hit = this.identityCache.get(task.sourceRoot); - if (fingerprint === null && hit) return; - // The inspector threw, so nothing proved this unchanged source can never - // resolve. Preserve the Retry path instead of freezing a provisional ID. - inspection = { status: "failed", retryable: true }; - } - if (!this.isCurrentTask(task)) return; - this.identityCache.set(task.sourceRoot, { fingerprint, inspection }); - this.pendingIdentityChanges.add(task.sourceRoot); - this.scheduleIdentityChangeFlush(); - } - - private scheduleIdentityChangeFlush(): void { - if (this.pendingIdentityChanges.size === 0) return; - if (this.activeInspections === 0 && this.queuedTasks.length === 0) { - this.clearIdentityChangeTimer(); - this.flushIdentityChanges(); - return; - } - if (this.identityChangeFlushInFlight || this.identityChangeTimer !== null) { - return; - } - this.identityChangeTimer = setTimeout(() => { - this.identityChangeTimer = null; - this.flushIdentityChanges(); - }, this.options.identityChangeCoalesceMs ?? IDENTITY_CHANGE_COALESCE_MS); - } - - private flushIdentityChanges(): void { - if ( - this.identityChangeFlushInFlight || - this.pendingIdentityChanges.size === 0 - ) { - return; - } - this.clearIdentityChangeTimer(); - const sourceRoots = [...this.pendingIdentityChanges].sort(compareText); - this.pendingIdentityChanges.clear(); - const notify = this.options.onIdentityChange; - if (!notify) return; - - this.identityChangeFlushInFlight = true; - void Promise.resolve() - .then(() => notify(sourceRoots)) - .catch(() => { - // A refresh hint cannot make settled identity results disappear. - }) - .finally(() => { - this.identityChangeFlushInFlight = false; - this.scheduleIdentityChangeFlush(); - }); - } - - private clearIdentityChangeTimer(): void { - if (this.identityChangeTimer === null) return; - clearTimeout(this.identityChangeTimer); - this.identityChangeTimer = null; - } - - private dropQueuedTasks(sourceRoot: string): void { - for (let index = this.queuedTasks.length - 1; index >= 0; index -= 1) { - if (this.queuedTasks[index]!.sourceRoot === sourceRoot) { - this.queuedTasks.splice(index, 1); - } - } - } - - private isCurrentTask(task: IdentityTask): boolean { - return ( - task.epoch === this.epoch && - task.generation === this.generations.get(task.sourceRoot) && - task.freshnessEpoch === this.freshnessEpoch - ); - } - - private ensureGeneration(sourceRoot: string): number { - const existing = this.generations.get(sourceRoot); - if (existing !== undefined) return existing; - const generation = this.nextGeneration++; - this.generations.set(sourceRoot, generation); - return generation; - } -} diff --git a/packages/harness/src/core/system-graph-relationships.test.ts b/packages/harness/src/core/system-graph-relationships.test.ts deleted file mode 100644 index 4961d4461..000000000 --- a/packages/harness/src/core/system-graph-relationships.test.ts +++ /dev/null @@ -1,590 +0,0 @@ -import * as fs from "node:fs/promises"; -import * as os from "node:os"; -import * as path from "node:path"; -import { afterEach, describe, expect, it, vi } from "vitest"; - -import type { AgentInventoryItem } from "./system-graph-inventory.js"; -import { - CachedAgentInvocationProvider, - SourceAgentInvocationProvider, - type AgentInvocationProvider, - type AgentInvocationProviderResult, -} from "./system-graph-relationships.js"; - -const temporaryRoots: string[] = []; -const EMPTY_RESULT: AgentInvocationProviderResult = { - invocations: [], - warnings: [], -}; - -function deferred(): { - promise: Promise; - resolve: (value: T) => void; - reject: (error: unknown) => void; -} { - let resolve!: (value: T) => void; - let reject!: (error: unknown) => void; - const promise = new Promise((onResolve, onReject) => { - resolve = onResolve; - reject = onReject; - }); - return { promise, resolve, reject }; -} - -async function callerWithSource(source: string): Promise { - const sourceRoot = await fs.mkdtemp( - path.join(os.tmpdir(), "system-graph-invocations-test-"), - ); - temporaryRoots.push(sourceRoot); - await fs.writeFile(path.join(sourceRoot, "index.ts"), source); - return { - agentKey: "research", - identityStatus: "canonical", - definitionId: 1, - definitionSlug: "research", - label: "Research", - resolutionAliases: ["research"], - sourceRoot, - workflowPath: sourceRoot, - path: ".", - entrypoint: "index.ts", - }; -} - -afterEach(async () => { - await Promise.all( - temporaryRoots - .splice(0) - .map((root) => fs.rm(root, { recursive: true, force: true })), - ); -}); - -describe("SourceAgentInvocationProvider", () => { - it("aggregates evidence by target and mode while preserving distinct modes", async () => { - const caller = await callerWithSource(` -ctx.sapiom.agents.run({ definition: "growth" }); -ctx.sapiom.agents.run({ definition: "growth" }); -ctx.sapiom.agents.launch({ definition: "growth" }); -ctx.sapiom.agents.launch({ definition: dynamicTarget }); -`); - - const result = await new SourceAgentInvocationProvider().listInvocations( - caller, - ); - - expect(result.invocations).toEqual([ - { - target: "growth", - mode: "blocking", - evidence: [ - { file: "index.ts", line: 2, column: 1 }, - { file: "index.ts", line: 3, column: 1 }, - ], - }, - { - target: "growth", - mode: "async", - evidence: [{ file: "index.ts", line: 4, column: 1 }], - }, - ]); - expect(result.warnings).toEqual([ - { - code: "dynamic-target", - mode: "async", - evidence: { file: "index.ts", line: 5, column: 1 }, - }, - ]); - }); - - it("reports only the coordinator's direct invocations without inferring output data flow", async () => { - const caller = { - ...(await callerWithSource(` -import { agents } from "@sapiom/tools"; - -const research = await agents.run({ - definition: "research", -}); - -const summary = formatResearch(research.output); - -await agents.run({ - definition: "growth", - input: { summary }, -}); -`)), - agentKey: "coordinator", - definitionSlug: "coordinator", - label: "Coordinator", - resolutionAliases: ["coordinator"], - }; - - const result = await new SourceAgentInvocationProvider().listInvocations( - caller, - ); - const directInvocations = result.invocations.map(({ target }) => [ - caller.agentKey, - target, - ]); - - expect(directInvocations).toEqual([ - ["coordinator", "research"], - ["coordinator", "growth"], - ]); - expect(directInvocations).not.toContainEqual(["research", "growth"]); - }); - - it("returns identical invocation semantics for unchanged caller input", async () => { - const caller = await callerWithSource( - 'ctx.sapiom.agents.run({ definition: "growth" });\n', - ); - const provider = new SourceAgentInvocationProvider(); - - const first = await provider.listInvocations(caller); - const second = await provider.listInvocations(caller); - - expect(second).toEqual(first); - }); - - it("does not follow a TypeScript symlink outside the workflow", async () => { - const caller = await callerWithSource("export const value = 1;\n"); - const external = await fs.mkdtemp( - path.join(os.tmpdir(), "system-graph-invocations-external-"), - ); - temporaryRoots.push(external); - await fs.writeFile( - path.join(external, "secret.ts"), - 'ctx.sapiom.agents.run({ definition: "outside" });\n', - ); - await fs.symlink( - path.join(external, "secret.ts"), - path.join(caller.sourceRoot, "evil.ts"), - ); - const onBytesRead = vi.fn(); - - const result = await new SourceAgentInvocationProvider({ - onBytesRead, - }).listInvocations(caller); - - expect(result.invocations).toEqual([]); - expect(result.complete).toBe(false); - expect(onBytesRead).toHaveBeenCalledTimes(1); - expect(onBytesRead).toHaveBeenCalledWith( - path.join(caller.sourceRoot, "index.ts"), - expect.any(Number), - ); - expect(onBytesRead).not.toHaveBeenCalledWith( - path.join(external, "secret.ts"), - expect.any(Number), - ); - }); - - it("rejects an ancestor swap before reading invocation source bytes", async () => { - const caller = await callerWithSource("export const value = 1;\n"); - const inside = path.join(caller.sourceRoot, "inside"); - await fs.mkdir(inside); - await fs.writeFile( - path.join(inside, "edge.ts"), - 'ctx.sapiom.agents.run({ definition: "inside" });\n', - ); - const external = await fs.mkdtemp( - path.join(os.tmpdir(), "system-graph-invocations-swap-"), - ); - temporaryRoots.push(external); - await fs.writeFile( - path.join(external, "edge.ts"), - 'ctx.sapiom.agents.run({ definition: "outside" });\n', - ); - const onBytesRead = vi.fn(); - let swapped = false; - - const result = await new SourceAgentInvocationProvider({ - beforeOpen: async (file) => { - if (!file.endsWith(`${path.sep}inside${path.sep}edge.ts`) || swapped) { - return; - } - swapped = true; - await fs.rename(inside, `${inside}-original`); - await fs.symlink(external, inside, "dir"); - }, - onBytesRead, - }).listInvocations(caller); - - expect(result.invocations).toEqual([]); - expect(result.complete).toBe(false); - expect(onBytesRead).not.toHaveBeenCalledWith( - path.join(external, "edge.ts"), - expect.any(Number), - ); - }); -}); - -describe("CachedAgentInvocationProvider", () => { - it("coalesces and reuses unchanged caller extraction", async () => { - const caller = await callerWithSource("export const value = 1;\n"); - const inner: AgentInvocationProvider = { - listInvocations: vi.fn(async () => ({ - invocations: [], - warnings: [], - })), - }; - const fingerprint = vi.fn(async () => "fingerprint-one"); - const provider = new CachedAgentInvocationProvider(inner, fingerprint); - - const first = provider.listInvocations(caller); - await expect(provider.listInvocations(caller)).resolves.toEqual( - await first, - ); - await provider.listInvocations(caller); - - expect(inner.listInvocations).toHaveBeenCalledTimes(1); - expect(fingerprint).toHaveBeenCalledTimes(3); - }); - - it("rescans only after the caller fingerprint changes", async () => { - const caller = await callerWithSource("export const value = 1;\n"); - const inner: AgentInvocationProvider = { - listInvocations: vi.fn(async () => ({ - invocations: [], - warnings: [], - })), - }; - const fingerprint = vi - .fn() - .mockResolvedValueOnce("one") - .mockResolvedValueOnce("two"); - const provider = new CachedAgentInvocationProvider(inner, fingerprint); - - await provider.listInvocations(caller); - await provider.listInvocations(caller); - - expect(inner.listInvocations).toHaveBeenCalledTimes(2); - }); - - it("does not retain a failed caller result", async () => { - const caller = await callerWithSource("export const value = 1;\n"); - const inner: AgentInvocationProvider = { - listInvocations: vi - .fn() - .mockRejectedValueOnce(new Error("not installed")) - .mockResolvedValueOnce({ invocations: [], warnings: [] }), - }; - const provider = new CachedAgentInvocationProvider( - inner, - async () => "same", - ); - - await expect(provider.listInvocations(caller)).rejects.toThrow( - "not installed", - ); - await expect(provider.listInvocations(caller)).resolves.toEqual({ - invocations: [], - warnings: [], - }); - expect(inner.listInvocations).toHaveBeenCalledTimes(2); - }); - - it("evicts removed callers while preserving retained callers", async () => { - const first = await callerWithSource("export const first = 1;\n"); - const second = await callerWithSource("export const second = 1;\n"); - const inner: AgentInvocationProvider = { - listInvocations: vi.fn(async () => ({ - invocations: [], - warnings: [], - })), - }; - const provider = new CachedAgentInvocationProvider( - inner, - async () => "same", - ); - await provider.listInvocations(first); - await provider.listInvocations(second); - - provider.retainCallers([second]); - await provider.listInvocations(first); - await provider.listInvocations(second); - - expect(inner.listInvocations).toHaveBeenCalledTimes(3); - }); - - it("runs background invocation extraction with a fixed concurrency cap", async () => { - const callers = await Promise.all( - Array.from({ length: 9 }, (_, index) => - callerWithSource(`export const value = ${index};\n`), - ), - ); - const releases: Array<() => void> = []; - let active = 0; - let maxActive = 0; - const onChange = vi.fn(); - const inner: AgentInvocationProvider = { - listInvocations: vi.fn(async () => { - active += 1; - maxActive = Math.max(maxActive, active); - await new Promise((resolve) => releases.push(resolve)); - active -= 1; - return EMPTY_RESULT; - }), - }; - const provider = new CachedAgentInvocationProvider( - inner, - async () => "unused", - { concurrency: 4, onChange }, - ); - - provider.startInvocations(callers); - await vi.waitFor(() => { - expect(inner.listInvocations).toHaveBeenCalledTimes(4); - }); - expect(maxActive).toBe(4); - - while (releases.length > 0 || active > 0) { - releases.splice(0).forEach((release) => release()); - await new Promise((resolve) => setTimeout(resolve, 0)); - } - await vi.waitFor(() => { - expect(inner.listInvocations).toHaveBeenCalledTimes(9); - expect(onChange).toHaveBeenCalledTimes(1); - }); - expect(maxActive).toBe(4); - expect( - callers.every( - (caller) => provider.peekInvocations(caller)?.status === "ready", - ), - ).toBe(true); - }); - - it("discards a superseded result and runs the fresh generation afterward", async () => { - const caller = await callerWithSource("export const value = 1;\n"); - const first = deferred(); - const inner: AgentInvocationProvider = { - listInvocations: vi - .fn() - .mockImplementationOnce(() => first.promise) - .mockResolvedValueOnce({ - invocations: [ - { - target: "fresh", - mode: "blocking", - evidence: [{ file: "index.ts", line: 1, column: 1 }], - }, - ], - warnings: [], - }), - }; - const onChange = vi.fn(); - const provider = new CachedAgentInvocationProvider( - inner, - async () => "unused", - { concurrency: 1, onChange }, - ); - - provider.startInvocations([caller]); - await vi.waitFor(() => - expect(inner.listInvocations).toHaveBeenCalledTimes(1), - ); - provider.invalidateSource(caller.sourceRoot); - provider.startInvocations([caller]); - first.resolve({ - invocations: [ - { - target: "stale", - mode: "blocking", - evidence: [{ file: "index.ts", line: 1, column: 1 }], - }, - ], - warnings: [], - }); - - await vi.waitFor(() => { - expect(inner.listInvocations).toHaveBeenCalledTimes(2); - expect( - provider.peekInvocations(caller)?.result.invocations[0]?.target, - ).toBe("fresh"); - }); - expect(onChange).toHaveBeenCalledTimes(1); - }); - - it("keeps failures stable until explicit Retry rearms them", async () => { - const caller = await callerWithSource("export const value = 1;\n"); - const inner: AgentInvocationProvider = { - listInvocations: vi - .fn() - .mockRejectedValueOnce(new Error("transient")) - .mockResolvedValueOnce(EMPTY_RESULT), - }; - const provider = new CachedAgentInvocationProvider(inner); - - provider.startInvocations([caller]); - await vi.waitFor(() => { - expect(provider.peekInvocations(caller)?.status).toBe("failed"); - }); - provider.startInvocations([caller]); - await new Promise((resolve) => setTimeout(resolve, 0)); - expect(inner.listInvocations).toHaveBeenCalledTimes(1); - - provider.retryFailed(caller.sourceRoot); - provider.startInvocations([caller]); - await vi.waitFor(() => { - expect(provider.peekInvocations(caller)?.status).toBe("ready"); - }); - expect(inner.listInvocations).toHaveBeenCalledTimes(2); - }); - - it("rearms an incomplete bounded scan only on explicit Retry", async () => { - const caller = await callerWithSource("export const value = 1;\n"); - const inner: AgentInvocationProvider = { - listInvocations: vi - .fn() - .mockResolvedValueOnce({ ...EMPTY_RESULT, complete: false }) - .mockResolvedValueOnce({ ...EMPTY_RESULT, complete: true }), - }; - const provider = new CachedAgentInvocationProvider(inner); - - provider.startInvocations([caller]); - await vi.waitFor(() => { - expect(provider.peekInvocations(caller)?.result.complete).toBe(false); - }); - provider.startInvocations([caller]); - expect(inner.listInvocations).toHaveBeenCalledTimes(1); - - provider.retryFailed(caller.sourceRoot); - provider.startInvocations([caller]); - await vi.waitFor(() => { - expect(provider.peekInvocations(caller)?.result.complete).toBe(true); - }); - expect(inner.listInvocations).toHaveBeenCalledTimes(2); - }); - - it("caps retained watcher observations fairly and degrades overflow", async () => { - const callers = await Promise.all([ - callerWithSource("export const first = 1;\n"), - callerWithSource("export const second = 2;\n"), - ]); - const inner: AgentInvocationProvider = { - listInvocations: vi.fn(async (caller) => ({ - ...EMPTY_RESULT, - complete: true, - observedPaths: Array.from({ length: 6_000 }, (_, index) => - path.join(caller.sourceRoot, `observed-${index}.ts`), - ), - })), - }; - const provider = new CachedAgentInvocationProvider(inner); - - provider.startInvocations(callers); - await vi.waitFor(() => { - expect( - callers.every( - (caller) => - provider.peekInvocations(caller)?.result.complete === false, - ), - ).toBe(true); - }); - const observations = provider.invocationObservations(); - - expect(observations).toHaveLength(2); - expect(observations.map((entry) => entry.paths.length)).toEqual([ - 5_000, 5_000, - ]); - }); - - it("notifies every retained root when global observation coverage changes", async () => { - const callers = await Promise.all([ - callerWithSource("export const first = 1;\n"), - callerWithSource("export const second = 2;\n"), - ]); - const inner: AgentInvocationProvider = { - listInvocations: vi.fn(async (caller) => ({ - ...EMPTY_RESULT, - complete: true, - observedPaths: Array.from({ length: 6_000 }, (_, index) => - path.join(caller.sourceRoot, `observed-${index}.ts`), - ), - })), - }; - const onChange = vi.fn(); - const provider = new CachedAgentInvocationProvider( - inner, - async () => "unused", - { onChange }, - ); - - provider.startInvocations([callers[0]!]); - await vi.waitFor(() => expect(onChange).toHaveBeenCalledTimes(1)); - expect(provider.peekInvocations(callers[0]!)?.result.complete).toBe(true); - onChange.mockClear(); - - provider.startInvocations(callers); - await vi.waitFor(() => expect(onChange).toHaveBeenCalled()); - expect(onChange.mock.calls.flat(2)).toEqual( - expect.arrayContaining(callers.map((caller) => caller.sourceRoot)), - ); - expect(provider.peekInvocations(callers[0]!)?.result.complete).toBe(false); - onChange.mockClear(); - - provider.retainCallers([callers[0]!]); - await vi.waitFor(() => expect(onChange).toHaveBeenCalledTimes(1)); - expect(onChange).toHaveBeenCalledWith([callers[0]!.sourceRoot]); - expect(provider.peekInvocations(callers[0]!)?.result.complete).toBe(true); - }); - - it("does not notify for a settled result invalidated before its batch flush", async () => { - const callers = await Promise.all([ - callerWithSource("export const fast = 1;\n"), - callerWithSource("export const slow = 2;\n"), - ]); - const slow = deferred(); - const inner: AgentInvocationProvider = { - listInvocations: vi - .fn() - .mockResolvedValueOnce(EMPTY_RESULT) - .mockImplementationOnce(() => slow.promise), - }; - const onChange = vi.fn(); - const provider = new CachedAgentInvocationProvider( - inner, - async () => "unused", - { concurrency: 2, onChange, changeBatchMs: 50 }, - ); - - provider.startInvocations(callers); - await vi.waitFor(() => { - expect(provider.peekInvocations(callers[0]!)?.status).toBe("ready"); - }); - provider.invalidateScope(os.tmpdir()); - slow.resolve(EMPTY_RESULT); - await new Promise((resolve) => setTimeout(resolve, 70)); - - expect(onChange).not.toHaveBeenCalled(); - }); - - it("publishes a settled workspace while an unrelated task remains held", async () => { - const callers = await Promise.all([ - callerWithSource("export const quick = 1;\n"), - callerWithSource("export const held = 2;\n"), - ]); - const held = deferred(); - const inner: AgentInvocationProvider = { - listInvocations: vi - .fn() - .mockResolvedValueOnce(EMPTY_RESULT) - .mockImplementationOnce(() => held.promise), - }; - const onChange = vi.fn(); - const provider = new CachedAgentInvocationProvider( - inner, - async () => "unused", - { concurrency: 2, onChange }, - ); - - provider.startInvocations(callers); - await vi.waitFor(() => expect(onChange).toHaveBeenCalledTimes(1)); - - expect(onChange).toHaveBeenLastCalledWith([callers[0]!.sourceRoot]); - expect(provider.peekInvocations(callers[0]!)?.status).toBe("ready"); - expect(provider.peekInvocations(callers[1]!)).toBeUndefined(); - - held.resolve(EMPTY_RESULT); - await vi.waitFor(() => expect(onChange).toHaveBeenCalledTimes(2)); - }); -}); diff --git a/packages/harness/src/core/system-graph-relationships.ts b/packages/harness/src/core/system-graph-relationships.ts deleted file mode 100644 index 89d41c92e..000000000 --- a/packages/harness/src/core/system-graph-relationships.ts +++ /dev/null @@ -1,522 +0,0 @@ -import * as path from "node:path"; - -import { - detectAgentInvocations, - type AgentInvocationDetectionWarning, - type AgentInvocationMode, - type SourceEvidence, - type WorkflowSourceReadHooks, -} from "./canvas-interconnections.js"; -import { fingerprintWorkflowSources } from "./canvas-cache.js"; -import { canonicalGraphPath } from "./canonical-graph-path.js"; -import type { AgentInventoryItem } from "./system-graph-inventory.js"; - -export const INVOCATION_OBSERVATION_MAX_PATHS = 10_000; - -export interface AgentInvocationCandidate { - /** Inventory key or definition slug to resolve after extraction. */ - target: string; - mode: AgentInvocationMode; - /** Internal-only evidence retained across callsite deduplication. */ - evidence: SourceEvidence[]; -} - -export type AgentInvocationWarning = AgentInvocationDetectionWarning; - -export interface AgentInvocationProviderResult { - invocations: AgentInvocationCandidate[]; - warnings: AgentInvocationWarning[]; - /** Confined files considered by this bounded extraction generation. */ - observedPaths?: readonly string[]; - /** False when an opaque path or work cap prevented a complete scan. */ - complete?: boolean; -} - -export interface AgentInvocationSnapshot { - status: "ready" | "failed"; - result: AgentInvocationProviderResult; -} - -export interface AgentInvocationObservation { - candidateRoot: string; - workspaceRoot: string; - paths: readonly string[]; -} - -/** - * Replaceable per-caller boundary for literal direct invocations consumed by - * the workspace graph projector. The caller is always the source endpoint. - */ -export interface AgentInvocationProvider { - listInvocations( - caller: AgentInventoryItem, - ): Promise; - /** Optional lifecycle hook for providers that retain per-caller state. */ - retainCallers?(callers: readonly AgentInventoryItem[]): void; - /** Cache-only projection used by the first graph phase. */ - peekInvocations?( - caller: AgentInventoryItem, - ): AgentInvocationSnapshot | undefined; - /** Starts bounded work only after the inventory-only graph is committed. */ - startInvocations?(callers: readonly AgentInventoryItem[]): void; - /** Accepted/current invocation metadata consumed by polling watchers. */ - invocationObservations?(): readonly AgentInvocationObservation[]; -} - -interface CachedInvocationEntry { - fingerprint: string; - result: Promise; -} - -interface InvocationTask { - sourceRoot: string; - caller: AgentInventoryItem; - generation: number; - scopeEpoch: number; -} - -interface BackgroundInvocationEntry { - generation: number; - scopeEpoch: number; - snapshot?: AgentInvocationSnapshot; -} - -export interface CachedAgentInvocationProviderOptions { - concurrency?: number; - onChange?: (sourceRoots: readonly string[]) => void | Promise; - /** Small testable coalescing window; settled scopes never await global idle. */ - changeBatchMs?: number; -} - -/** - * Successful per-caller invocation extraction behind the same cheap source - * fingerprint used by Canvas. Projection can therefore rebuild against a new - * inventory without re-walking unchanged caller trees. - */ -export class CachedAgentInvocationProvider implements AgentInvocationProvider { - private readonly entries = new Map(); - private readonly background = new Map(); - private readonly queued: InvocationTask[] = []; - private readonly active = new Map(); - private readonly pendingChanges = new Set(); - private readonly invalidatedScopes = new Map(); - private nextGeneration = 1; - private nextScopeEpoch = 1; - private activeCount = 0; - private observationsTruncated = false; - private changeFlushTimer: ReturnType | null = null; - - constructor( - private readonly inner: AgentInvocationProvider = new SourceAgentInvocationProvider(), - private readonly fingerprint: ( - sourceRoot: string, - ) => Promise = fingerprintWorkflowSources, - private readonly options: CachedAgentInvocationProviderOptions = {}, - ) {} - - async listInvocations( - caller: AgentInventoryItem, - ): Promise { - const key = canonicalGraphPath(caller.sourceRoot); - let fingerprint: string; - try { - fingerprint = await this.fingerprint(key); - } catch (error) { - this.entries.delete(key); - throw error; - } - - const hit = this.entries.get(key); - if (hit?.fingerprint === fingerprint) return hit.result; - - let result: Promise; - try { - result = Promise.resolve(this.inner.listInvocations(caller)); - } catch (error) { - result = Promise.reject(error); - } - const entry = { fingerprint, result }; - this.entries.set(key, entry); - void result.catch(() => { - if (this.entries.get(key) === entry) this.entries.delete(key); - }); - return result; - } - - invalidateSource(sourceRoot: string): void { - const key = canonicalGraphPath(sourceRoot); - this.entries.delete(key); - this.background.set(key, { - generation: this.nextGeneration++, - scopeEpoch: this.scopeEpochForSource(key), - }); - this.dropQueued(key); - this.pendingChanges.delete(key); - } - - /** O(1) conservative invalidation for an ambiguous workspace event. */ - invalidateScope(scopeRoot: string): void { - this.invalidatedScopes.set( - canonicalGraphPath(scopeRoot), - this.nextScopeEpoch++, - ); - } - - /** Explicit graph Retry re-arms terminal failures without read-loop churn. */ - retryFailed(scopeRoot: string): void { - const root = canonicalGraphPath(scopeRoot); - for (const [sourceRoot, entry] of this.background) { - const relative = path.relative(root, sourceRoot); - if ( - (entry.snapshot?.status !== "failed" && - !( - entry.snapshot?.status === "ready" && - entry.snapshot.result.complete === false - )) || - relative === ".." || - relative.startsWith(`..${path.sep}`) || - path.isAbsolute(relative) - ) { - continue; - } - this.background.set(sourceRoot, { - generation: this.nextGeneration++, - scopeEpoch: this.scopeEpochForSource(sourceRoot), - }); - this.dropQueued(sourceRoot); - } - } - - retainCallers(callers: readonly AgentInventoryItem[]): void { - const retained = new Set( - callers.map((caller) => canonicalGraphPath(caller.sourceRoot)), - ); - for (const sourceRoot of this.entries.keys()) { - if (!retained.has(sourceRoot)) this.entries.delete(sourceRoot); - } - for (const sourceRoot of this.background.keys()) { - if (retained.has(sourceRoot)) continue; - this.background.delete(sourceRoot); - this.dropQueued(sourceRoot); - this.pendingChanges.delete(sourceRoot); - } - for (const scopeRoot of this.invalidatedScopes.keys()) { - if ( - [...retained].some((sourceRoot) => - this.scopeContainsSource(scopeRoot, sourceRoot), - ) - ) { - continue; - } - this.invalidatedScopes.delete(scopeRoot); - } - this.refreshObservationCoverage(); - } - - clear(): void { - this.entries.clear(); - this.background.clear(); - this.queued.length = 0; - this.pendingChanges.clear(); - if (this.changeFlushTimer) clearTimeout(this.changeFlushTimer); - this.changeFlushTimer = null; - this.invalidatedScopes.clear(); - this.nextGeneration += 1; - this.nextScopeEpoch += 1; - this.observationsTruncated = false; - } - - peekInvocations( - caller: AgentInventoryItem, - ): AgentInvocationSnapshot | undefined { - const sourceRoot = canonicalGraphPath(caller.sourceRoot); - const entry = this.background.get(sourceRoot); - if (entry?.scopeEpoch !== this.scopeEpochForSource(sourceRoot)) { - return undefined; - } - if ( - this.observationsTruncated && - entry.snapshot?.status === "ready" && - entry.snapshot.result.complete !== false - ) { - return { - status: "ready", - result: { ...entry.snapshot.result, complete: false }, - }; - } - return entry.snapshot; - } - - startInvocations(callers: readonly AgentInventoryItem[]): void { - for (const caller of callers) { - const sourceRoot = canonicalGraphPath(caller.sourceRoot); - let entry = this.background.get(sourceRoot); - const scopeEpoch = this.scopeEpochForSource(sourceRoot); - if (!entry || entry.scopeEpoch !== scopeEpoch) { - entry = { generation: this.nextGeneration++, scopeEpoch }; - this.background.set(sourceRoot, entry); - this.dropQueued(sourceRoot); - } - if (entry.snapshot) continue; - if ( - this.active.get(sourceRoot)?.generation === entry.generation || - this.queued.some( - (task) => - task.sourceRoot === sourceRoot && - task.generation === entry!.generation, - ) - ) { - continue; - } - this.dropQueued(sourceRoot); - this.queued.push({ - sourceRoot, - caller, - generation: entry.generation, - scopeEpoch: entry.scopeEpoch, - }); - } - this.drain(); - } - - invocationObservations(): readonly AgentInvocationObservation[] { - const entries = [...this.background.entries()] - .filter( - ([sourceRoot, entry]) => - entry.scopeEpoch === this.scopeEpochForSource(sourceRoot) && - (entry.snapshot?.result.observedPaths?.length ?? 0) > 0, - ) - .sort(([left], [right]) => left.localeCompare(right)); - const selected = new Map(); - let remaining = INVOCATION_OBSERVATION_MAX_PATHS; - let round = 0; - while (remaining > 0) { - let added = false; - for (const [sourceRoot, entry] of entries) { - if (remaining === 0) break; - const observed = entry.snapshot?.result.observedPaths?.[round]; - if (!observed) continue; - const paths = selected.get(sourceRoot) ?? []; - paths.push(observed); - selected.set(sourceRoot, paths); - remaining -= 1; - added = true; - } - if (!added) break; - round += 1; - } - return [...selected.entries()].map(([sourceRoot, paths]) => ({ - candidateRoot: sourceRoot, - workspaceRoot: sourceRoot, - paths, - })); - } - - private current(task: InvocationTask): boolean { - const entry = this.background.get(task.sourceRoot); - return ( - entry?.generation === task.generation && - entry.scopeEpoch === task.scopeEpoch && - task.scopeEpoch === this.scopeEpochForSource(task.sourceRoot) - ); - } - - private scopeContainsSource(scopeRoot: string, sourceRoot: string): boolean { - const relative = path.relative(scopeRoot, sourceRoot); - return ( - relative !== ".." && - !relative.startsWith(`..${path.sep}`) && - !path.isAbsolute(relative) - ); - } - - private scopeEpochForSource(sourceRoot: string): number { - let epoch = 0; - for (const [scopeRoot, candidateEpoch] of this.invalidatedScopes) { - if (this.scopeContainsSource(scopeRoot, sourceRoot)) { - epoch = Math.max(epoch, candidateEpoch); - } - } - return epoch; - } - - private refreshObservationCoverage(): void { - let count = 0; - let truncated = false; - for (const [sourceRoot, entry] of this.background) { - if (entry.scopeEpoch !== this.scopeEpochForSource(sourceRoot)) continue; - count += entry.snapshot?.result.observedPaths?.length ?? 0; - if (count > INVOCATION_OBSERVATION_MAX_PATHS) { - truncated = true; - break; - } - } - if (truncated === this.observationsTruncated) return; - this.observationsTruncated = truncated; - // Coverage is part of every retained ready snapshot's effective - // completeness. Crossing the global observation cap (in either direction) - // therefore changes more than the task that happened to settle/retire. - for (const [sourceRoot, entry] of this.background) { - if ( - entry.snapshot && - entry.scopeEpoch === this.scopeEpochForSource(sourceRoot) - ) { - this.pendingChanges.add(sourceRoot); - } - } - this.scheduleChanges(); - } - - private dropQueued(sourceRoot: string): void { - for (let index = this.queued.length - 1; index >= 0; index -= 1) { - if (this.queued[index]!.sourceRoot === sourceRoot) { - this.queued.splice(index, 1); - } - } - } - - private drain(): void { - for (let index = this.queued.length - 1; index >= 0; index -= 1) { - if (!this.current(this.queued[index]!)) this.queued.splice(index, 1); - } - const concurrency = Math.max(1, this.options.concurrency ?? 4); - while (this.activeCount < concurrency) { - const index = this.queued.findIndex( - (task) => !this.active.has(task.sourceRoot), - ); - if (index === -1) break; - const [task] = this.queued.splice(index, 1); - if (!task || !this.current(task)) continue; - this.active.set(task.sourceRoot, task); - this.activeCount += 1; - void this.run(task).finally(() => { - if (this.active.get(task.sourceRoot) === task) { - this.active.delete(task.sourceRoot); - this.activeCount -= 1; - } - this.drain(); - }); - } - } - - private async run(task: InvocationTask): Promise { - let snapshot: AgentInvocationSnapshot; - try { - snapshot = { - status: "ready", - result: await this.inner.listInvocations(task.caller), - }; - } catch { - snapshot = { - status: "failed", - result: { invocations: [], warnings: [] }, - }; - } - if (!this.current(task)) return; - this.background.set(task.sourceRoot, { - generation: task.generation, - scopeEpoch: task.scopeEpoch, - snapshot, - }); - this.refreshObservationCoverage(); - this.pendingChanges.add(task.sourceRoot); - this.scheduleChanges(); - } - - private scheduleChanges(): void { - if (this.changeFlushTimer) return; - this.changeFlushTimer = setTimeout(() => { - this.changeFlushTimer = null; - this.flushChanges(); - }, this.options.changeBatchMs ?? 0); - } - - private flushChanges(): void { - if (this.pendingChanges.size === 0) return; - const changed = [...this.pendingChanges] - .filter((sourceRoot) => { - const entry = this.background.get(sourceRoot); - return ( - entry?.snapshot !== undefined && - entry.scopeEpoch === this.scopeEpochForSource(sourceRoot) - ); - }) - .sort(); - this.pendingChanges.clear(); - if (changed.length === 0) return; - void Promise.resolve() - .then(() => this.options.onChange?.(changed)) - .catch(() => { - // Refresh hints cannot invalidate current invocation evidence. - }); - } -} - -function evidenceOrder(left: SourceEvidence, right: SourceEvidence): number { - return ( - left.file.localeCompare(right.file) || - left.line - right.line || - left.column - right.column - ); -} - -const MODE_ORDER: Record = { - blocking: 0, - async: 1, -}; - -/** - * V0 per-agent filesystem adapter for literal direct invocations. - * - * It scans only the caller's inventoried source root. It remains syntax-only - * and has no inventory target resolution, input-provenance analysis, package - * router scan, renderer, transport, deployment, or session dependencies. - */ -export class SourceAgentInvocationProvider implements AgentInvocationProvider { - constructor(private readonly readHooks: WorkflowSourceReadHooks = {}) {} - - async listInvocations( - caller: AgentInventoryItem, - ): Promise { - const scan = await detectAgentInvocations( - caller.sourceRoot, - new Set(), - this.readHooks, - ); - const grouped = new Map(); - - for (const detectedInvocation of scan.invocations) { - const key = `${detectedInvocation.slug}\0${detectedInvocation.mode}`; - const candidate = grouped.get(key); - if (candidate) { - candidate.evidence.push(detectedInvocation.evidence); - } else { - grouped.set(key, { - target: detectedInvocation.slug, - mode: detectedInvocation.mode, - evidence: [detectedInvocation.evidence], - }); - } - } - - const invocations = [...grouped.values()]; - for (const candidate of invocations) { - candidate.evidence.sort(evidenceOrder); - } - invocations.sort( - (left, right) => - left.evidence[0]!.file.localeCompare(right.evidence[0]!.file) || - left.evidence[0]!.line - right.evidence[0]!.line || - left.evidence[0]!.column - right.evidence[0]!.column || - MODE_ORDER[left.mode] - MODE_ORDER[right.mode] || - left.target.localeCompare(right.target), - ); - - return { - invocations, - warnings: scan.warnings, - observedPaths: scan.observedPaths, - complete: scan.complete, - }; - } -} diff --git a/packages/harness/src/core/system-graph-store.test.ts b/packages/harness/src/core/system-graph-store.test.ts deleted file mode 100644 index cc14f7ae6..000000000 --- a/packages/harness/src/core/system-graph-store.test.ts +++ /dev/null @@ -1,578 +0,0 @@ -import { describe, expect, it, vi } from "vitest"; - -import type { - SystemGraph, - SystemGraphSnapshot, -} from "../shared/system-graph.js"; -import type { - SystemGraphBuildResult, - SystemGraphBuilder, - WorkspaceScope, -} from "./system-graph.js"; -import { SystemGraphStore } from "./system-graph-store.js"; - -const scope: WorkspaceScope = { - workspaceKey: "workspace-one", - root: "/private/one", -}; - -function graphFor(label: string): SystemGraph { - return { - kind: "system", - scope: { kind: "working-tree", workspaceKey: scope.workspaceKey }, - nodes: [{ id: `agent:${label}`, agentKey: label, label }], - edges: [], - warnings: [], - }; -} - -function buildResult(label: string, cacheable = true): SystemGraphBuildResult { - return { - cacheable, - graph: graphFor(label), - navigation: [{ agentKey: label, workflowPath: `/private/${label}` }], - }; -} - -function deferred(): { - promise: Promise; - resolve: (value: T) => void; - reject: (error: Error) => void; -} { - let resolve!: (value: T) => void; - let reject!: (error: Error) => void; - const promise = new Promise((res, rej) => { - resolve = res; - reject = rej; - }); - return { promise, resolve, reject }; -} - -describe("SystemGraphStore", () => { - it("coalesces cold reads and retains an unchanged ready snapshot", async () => { - const pending = deferred(); - const builder: SystemGraphBuilder = { - build: vi.fn(() => pending.promise), - }; - const store = new SystemGraphStore(builder); - - const first = store.get(scope); - expect(store.get(scope)).toBe(first); - pending.resolve(buildResult("first")); - - const ready = await first; - expect(ready).toMatchObject({ state: "ready", graph: graphFor("first") }); - expect(store.peekNavigation(scope.workspaceKey)).toEqual({ - workspaceKey: scope.workspaceKey, - revision: ready.revision, - targets: [{ agentKey: "first", workflowPath: "/private/first" }], - }); - await expect(store.get(scope)).resolves.toBe(ready); - expect(builder.build).toHaveBeenCalledTimes(1); - }); - - it("keeps the last-good graph visible while a refresh runs", async () => { - const refresh = deferred(); - const build = vi - .fn() - .mockResolvedValueOnce(buildResult("first")) - .mockReturnValueOnce(refresh.promise); - const changes: SystemGraphSnapshot[] = []; - const store = new SystemGraphStore( - { build }, - { onChange: (snapshot) => changes.push(snapshot) }, - ); - await store.get(scope); - - const stale = store.requestRefresh(scope); - expect(stale).toMatchObject({ state: "stale", graph: graphFor("first") }); - await expect(store.get(scope)).resolves.toBe(stale); - expect(store.peekNavigation(scope.workspaceKey)).toMatchObject({ - revision: stale.revision, - targets: [{ agentKey: "first", workflowPath: "/private/first" }], - }); - - refresh.resolve(buildResult("second")); - await vi.waitFor(() => { - expect(store.peek(scope.workspaceKey)).toMatchObject({ - state: "ready", - graph: graphFor("second"), - }); - }); - expect(changes.map((change) => change.state)).toContain("stale"); - }); - - it("does not let a builder mutate last-good navigation after commit", async () => { - const refresh = deferred(); - const navigation = [{ agentKey: "first", workflowPath: "/private/first" }]; - const build = vi - .fn() - .mockResolvedValueOnce({ - cacheable: true, - graph: graphFor("first"), - navigation, - }) - .mockReturnValueOnce(refresh.promise); - const store = new SystemGraphStore({ build }); - await store.get(scope); - - navigation[0]!.workflowPath = "/private/mutated"; - store.requestRefresh(scope); - - expect(store.peekNavigation(scope.workspaceKey)?.targets).toEqual([ - { agentKey: "first", workflowPath: "/private/first" }, - ]); - }); - - it("discards an older refresh and commits the newest edit", async () => { - const oldRefresh = deferred(); - const newestRefresh = deferred(); - const build = vi - .fn() - .mockResolvedValueOnce(buildResult("initial")) - .mockReturnValueOnce(oldRefresh.promise) - .mockReturnValueOnce(newestRefresh.promise); - const store = new SystemGraphStore({ build }); - await store.get(scope); - - store.requestRefresh(scope); - store.requestRefresh(scope); - oldRefresh.resolve(buildResult("obsolete")); - await vi.waitFor(() => expect(build).toHaveBeenCalledTimes(3)); - expect(store.peek(scope.workspaceKey)?.graph).toEqual(graphFor("initial")); - - newestRefresh.resolve(buildResult("newest")); - await vi.waitFor(() => { - expect(store.peek(scope.workspaceKey)).toMatchObject({ - state: "ready", - graph: graphFor("newest"), - }); - }); - }); - - it("preserves last-good data after a hard refresh failure", async () => { - const failed = deferred(); - const build = vi - .fn() - .mockResolvedValueOnce(buildResult("initial")) - .mockReturnValueOnce(failed.promise) - .mockResolvedValueOnce(buildResult("recovered")); - const store = new SystemGraphStore({ build }); - await store.get(scope); - - const refreshing = store.requestRefresh(scope); - failed.reject(new Error("scan failed")); - - await vi.waitFor(() => { - expect(store.peek(scope.workspaceKey)).toMatchObject({ - state: "stale", - graph: graphFor("initial"), - }); - expect(store.peek(scope.workspaceKey)!.revision).toBeGreaterThan( - refreshing.revision, - ); - }); - expect(store.peekNavigation(scope.workspaceKey)).toMatchObject({ - revision: store.peek(scope.workspaceKey)?.revision, - targets: [{ agentKey: "initial", workflowPath: "/private/initial" }], - }); - - await store.get(scope); - await vi.waitFor(() => { - expect(store.peek(scope.workspaceKey)).toMatchObject({ - state: "ready", - graph: graphFor("recovered"), - }); - }); - }); - - it("publishes the current partial graph instead of retaining failed edges", async () => { - const build = vi - .fn() - .mockResolvedValueOnce(buildResult("initial")) - .mockResolvedValueOnce(buildResult("partial", false)); - const store = new SystemGraphStore({ build }); - await store.get(scope); - - store.requestRefresh(scope); - - await vi.waitFor(() => { - expect(store.peek(scope.workspaceKey)).toMatchObject({ - state: "degraded", - graph: graphFor("partial"), - }); - }); - }); - - it("keeps the newest partial graph visible during its next refresh", async () => { - const recovery = deferred(); - const build = vi - .fn() - .mockResolvedValueOnce(buildResult("initial")) - .mockResolvedValueOnce(buildResult("partial", false)) - .mockReturnValueOnce(recovery.promise); - const store = new SystemGraphStore({ build }); - await store.get(scope); - - store.requestRefresh(scope); - await vi.waitFor(() => { - expect(store.peek(scope.workspaceKey)).toMatchObject({ - state: "degraded", - graph: graphFor("partial"), - }); - }); - - const refreshing = store.requestRefresh(scope); - expect(refreshing).toMatchObject({ - state: "stale", - graph: graphFor("partial"), - }); - expect(store.peekNavigation(scope.workspaceKey)).toEqual({ - workspaceKey: scope.workspaceKey, - revision: refreshing.revision, - targets: [{ agentKey: "partial", workflowPath: "/private/partial" }], - }); - - recovery.resolve(buildResult("recovered")); - await vi.waitFor(() => { - expect(store.peek(scope.workspaceKey)).toMatchObject({ - state: "ready", - graph: graphFor("recovered"), - }); - }); - }); - - it("keeps the newest partial graph after an inventory refresh failure", async () => { - const build = vi - .fn() - .mockResolvedValueOnce(buildResult("initial")) - .mockResolvedValueOnce(buildResult("partial", false)); - const store = new SystemGraphStore({ build }); - await store.get(scope); - - store.requestRefresh(scope); - await vi.waitFor(() => { - expect(store.peek(scope.workspaceKey)).toMatchObject({ - state: "degraded", - graph: graphFor("partial"), - }); - }); - - const stale = store.reportRefreshFailure(scope); - expect(stale).toMatchObject({ - state: "stale", - graph: graphFor("partial"), - }); - expect(store.peekNavigation(scope.workspaceKey)).toEqual({ - workspaceKey: scope.workspaceKey, - revision: stale.revision, - targets: [{ agentKey: "partial", workflowPath: "/private/partial" }], - }); - }); - - it("keeps last-good data stale after a failed inventory refresh", async () => { - const pending = deferred(); - const build = vi - .fn() - .mockResolvedValueOnce(buildResult("initial")) - .mockReturnValueOnce(pending.promise); - const store = new SystemGraphStore({ build }); - await store.get(scope); - - store.requestRefresh(scope); - const stale = store.reportRefreshFailure(scope); - expect(stale).toMatchObject({ - state: "stale", - graph: graphFor("initial"), - }); - expect(store.peekNavigation(scope.workspaceKey)).toMatchObject({ - revision: stale.revision, - targets: [{ agentKey: "initial", workflowPath: "/private/initial" }], - }); - - pending.resolve(buildResult("obsolete")); - await vi.waitFor(() => expect(build).toHaveBeenCalledTimes(2)); - expect(store.peek(scope.workspaceKey)).toBe(stale); - }); - - it("does not publish a new revision for repeated inventory failures", async () => { - const onChange = vi.fn(); - const store = new SystemGraphStore( - { build: vi.fn().mockResolvedValue(buildResult("initial")) }, - { onChange }, - ); - await store.get(scope); - onChange.mockClear(); - - const firstFailure = store.reportRefreshFailure(scope); - const repeatedFailure = store.reportRefreshFailure(scope); - - expect(repeatedFailure).toBe(firstFailure); - expect(firstFailure.state).toBe("stale"); - expect(onChange).toHaveBeenCalledTimes(1); - }); - - it("arms background enrichment even when its build is superseded", async () => { - const pending = deferred(); - const startEnrichment = vi.fn(); - const store = new SystemGraphStore({ build: vi.fn(() => pending.promise) }); - - const cold = store.get(scope); - store.reportRefreshFailure(scope); - pending.resolve({ - ...buildResult("initial", false), - afterCommit: startEnrichment, - }); - await cold; - - expect(startEnrichment).toHaveBeenCalledTimes(1); - }); - - it("allows an explicit refresh after automatic recovery was exhausted", async () => { - const build = vi - .fn() - .mockResolvedValueOnce(buildResult("initial")) - .mockResolvedValueOnce(buildResult("recovered")); - const store = new SystemGraphStore({ build }); - await store.get(scope); - store.reportRefreshFailure(scope); - - await expect(store.refresh(scope)).resolves.toMatchObject({ - state: "ready", - graph: graphFor("recovered"), - }); - expect(build).toHaveBeenCalledTimes(2); - }); - - it("returns an honest cold degraded snapshot when no graph can be built", async () => { - const store = new SystemGraphStore({ - build: vi.fn().mockRejectedValue(new Error("unavailable")), - }); - - await expect(store.get(scope)).resolves.toMatchObject({ - state: "degraded", - graph: null, - }); - }); - - it("starts enrichment only after its provisional graph and resolver commit", async () => { - const afterCommit = vi.fn(() => { - const snapshot = store.peek(scope.workspaceKey); - const navigation = store.peekNavigation(scope.workspaceKey); - expect(snapshot).toMatchObject({ state: "degraded" }); - expect(navigation?.revision).toBe(snapshot?.revision); - expect(navigation?.targets).toEqual([ - { agentKey: "pending", workflowPath: "/private/pending" }, - ]); - }); - const store = new SystemGraphStore({ - build: vi.fn(async () => ({ - ...buildResult("pending", false), - afterCommit, - })), - }); - - const snapshot = await store.get(scope); - - expect(snapshot.state).toBe("degraded"); - expect(afterCommit).toHaveBeenCalledTimes(1); - }); - - it("allows one later-open retry for a partial projection", async () => { - const retry = deferred(); - const build = vi - .fn() - .mockResolvedValueOnce(buildResult("partial", false)) - .mockReturnValueOnce(retry.promise); - const store = new SystemGraphStore({ build }); - - const degraded = await store.get(scope); - expect(degraded.state).toBe("degraded"); - const retrying = store.get(scope); - expect(store.peek(scope.workspaceKey)).toMatchObject({ - state: "degraded", - graph: graphFor("partial"), - }); - await store.get(scope); - expect(build).toHaveBeenCalledTimes(2); - - retry.resolve(buildResult("recovered")); - await expect(retrying).resolves.toMatchObject({ - state: "degraded", - graph: graphFor("partial"), - }); - await vi.waitFor(() => { - expect(store.peek(scope.workspaceKey)?.state).toBe("ready"); - }); - }); - - it("atomically publishes changed navigation from a same-graph degraded recovery", async () => { - const graph = graphFor("partial"); - const build = vi - .fn() - .mockResolvedValueOnce({ - cacheable: false, - graph, - navigation: [{ agentKey: "partial", workflowPath: "/private/before" }], - }) - .mockResolvedValueOnce({ - cacheable: false, - graph, - navigation: [{ agentKey: "partial", workflowPath: "/private/after" }], - }); - const onChange = vi.fn(); - const store = new SystemGraphStore({ build }, { onChange }); - const initial = await store.get(scope); - onChange.mockClear(); - - await store.get(scope); - await vi.waitFor(() => - expect(store.peekNavigation(scope.workspaceKey)?.targets).toEqual([ - { agentKey: "partial", workflowPath: "/private/after" }, - ]), - ); - - expect(store.peek(scope.workspaceKey)?.revision).toBeGreaterThan( - initial.revision, - ); - expect(onChange).toHaveBeenCalledTimes(1); - }); - - it("does not publish or retain an in-flight build after scope retirement", async () => { - const pending = deferred(); - const onChange = vi.fn(); - const store = new SystemGraphStore( - { build: vi.fn(() => pending.promise) }, - { onChange }, - ); - const initial = store.get(scope); - store.retire(scope.workspaceKey); - pending.resolve(buildResult("retired")); - await initial; - - expect(store.peek(scope.workspaceKey)).toBeNull(); - expect(onChange).not.toHaveBeenCalled(); - }); - - it("retires only projections outside the retained workspace set", async () => { - const secondScope = { - workspaceKey: "workspace-two", - root: "/private/two", - }; - const store = new SystemGraphStore({ - build: vi.fn().mockResolvedValue(buildResult("ready")), - }); - await Promise.all([store.get(scope), store.get(secondScope)]); - - store.retain(new Set([scope.workspaceKey])); - - expect(store.peek(scope.workspaceKey)).not.toBeNull(); - expect(store.peek(secondScope.workspaceKey)).toBeNull(); - }); - - it("keeps revisions monotonic when a retired workspace returns", async () => { - const store = new SystemGraphStore({ - build: vi.fn().mockResolvedValue(buildResult("ready")), - }); - const first = await store.get(scope); - store.retire(scope.workspaceKey); - - const returned = await store.get(scope); - - expect(returned.revision).toBeGreaterThan(first.revision); - }); - - it("does not build a cold projection until its inventory prerequisite is accepted", async () => { - const build = vi.fn().mockResolvedValue(buildResult("accepted")); - const store = new SystemGraphStore({ build }); - - const blocked = store.markStale(scope, "scan:workspace"); - await expect(store.get(scope)).resolves.toBe(blocked); - expect(build).not.toHaveBeenCalled(); - - store.releasePrerequisite(scope, "scan:workspace"); - await vi.waitFor(() => expect(build).toHaveBeenCalledTimes(1)); - await vi.waitFor(() => { - expect(store.peek(scope.workspaceKey)).toMatchObject({ - state: "ready", - graph: graphFor("accepted"), - }); - }); - }); - - it("keeps overlapping prerequisites stale until every scan accepts", async () => { - const build = vi - .fn() - .mockResolvedValueOnce(buildResult("initial")) - .mockResolvedValueOnce(buildResult("accepted")); - const store = new SystemGraphStore({ build }); - await store.get(scope); - - store.markStale(scope, "scan:parent"); - store.markStale(scope, "scan:child"); - store.releasePrerequisite(scope, "scan:child"); - store.requestRefresh(scope); // Late identity enrichment cannot bypass it. - - expect(store.peek(scope.workspaceKey)).toMatchObject({ - state: "stale", - graph: graphFor("initial"), - }); - expect(build).toHaveBeenCalledTimes(1); - - store.releasePrerequisite(scope, "scan:parent"); - await vi.waitFor(() => expect(build).toHaveBeenCalledTimes(2)); - await vi.waitFor(() => { - expect(store.peek(scope.workspaceKey)).toMatchObject({ - state: "ready", - graph: graphFor("accepted"), - }); - }); - }); - - it("does not let a superseded build or identity refresh bypass a prerequisite", async () => { - const obsolete = deferred(); - const accepted = deferred(); - const build = vi - .fn() - .mockResolvedValueOnce(buildResult("initial")) - .mockReturnValueOnce(obsolete.promise) - .mockReturnValueOnce(accepted.promise); - const store = new SystemGraphStore({ build }); - await store.get(scope); - store.requestRefresh(scope); - - store.markStale(scope, "scan:workspace"); - store.requestRefresh(scope); // An older identity task settles while blocked. - obsolete.resolve(buildResult("obsolete")); - await Promise.resolve(); - await Promise.resolve(); - - expect(build).toHaveBeenCalledTimes(2); - expect(store.peek(scope.workspaceKey)).toMatchObject({ - state: "stale", - graph: graphFor("initial"), - }); - - store.releasePrerequisite(scope, "scan:workspace"); - await vi.waitFor(() => expect(build).toHaveBeenCalledTimes(3)); - accepted.resolve(buildResult("accepted")); - await vi.waitFor(() => { - expect(store.peek(scope.workspaceKey)?.graph).toEqual( - graphFor("accepted"), - ); - }); - }); - - it("does not recreate a retired scope while awaiting an accepted build", async () => { - const store = new SystemGraphStore({ - build: vi.fn().mockResolvedValue(buildResult("ready")), - }); - store.markStale(scope, "scan:workspace"); - store.retire(scope.workspaceKey); - - await expect( - store.waitForCurrentRefresh(scope.workspaceKey), - ).resolves.toBeNull(); - expect(store.peek(scope.workspaceKey)).toBeNull(); - }); -}); diff --git a/packages/harness/src/core/system-graph-store.ts b/packages/harness/src/core/system-graph-store.ts deleted file mode 100644 index 2fdec923a..000000000 --- a/packages/harness/src/core/system-graph-store.ts +++ /dev/null @@ -1,484 +0,0 @@ -import type { - SystemGraph, - SystemGraphLifecycleState, - SystemGraphNavigationResponse, - SystemGraphNavigationTarget, - SystemGraphSnapshot, - WorkspaceKey, -} from "../shared/system-graph.js"; -import type { SystemGraphBuilder, WorkspaceScope } from "./system-graph.js"; - -export interface SystemGraphStoreOptions { - /** Called only for an accepted lifecycle transition. */ - onChange?: (snapshot: SystemGraphSnapshot) => void; -} - -interface SystemGraphEntry { - scope: WorkspaceScope; - snapshot: SystemGraphSnapshot; - navigation: SystemGraphNavigationResponse; - activeBuild: Promise | null; - generation: number; - refreshPending: boolean; - automaticRetryUsed: boolean; - prerequisiteTokens: Set; - retired: boolean; -} - -function visibleProjection(entry: SystemGraphEntry): { - graph: SystemGraph | null; - navigation: readonly SystemGraphNavigationTarget[]; -} { - return { - graph: entry.snapshot.graph, - navigation: entry.navigation.targets, - }; -} - -function sameNavigation( - left: readonly SystemGraphNavigationTarget[], - right: readonly SystemGraphNavigationTarget[], -): boolean { - return ( - left.length === right.length && - left.every( - (target, index) => - target.agentKey === right[index]?.agentKey && - target.workflowPath === right[index]?.workflowPath, - ) - ); -} - -/** - * Process-lifetime, workspace-scoped projection store. - * - * Cold reads coalesce behind one build. Later refreshes keep the last usable - * graph visible as stale, serialize rebuilds, and reject an older generation's - * result when another edit arrives while it is in flight. - */ -export class SystemGraphStore { - private readonly entries = new Map(); - private readonly revisionFloors = new Map(); - - constructor( - private readonly builder: SystemGraphBuilder, - private readonly options: SystemGraphStoreOptions = {}, - ) {} - - get(scope: WorkspaceScope): Promise { - const entry = this.ensureEntry(scope); - if (entry.prerequisiteTokens.size > 0) { - return Promise.resolve(entry.snapshot); - } - if (entry.activeBuild) { - return entry.snapshot.graph === null - ? entry.activeBuild - : Promise.resolve(entry.snapshot); - } - if (entry.snapshot.state === "building" && entry.snapshot.graph === null) { - return this.startBuild(entry); - } - - // Non-ready projections are deliberately not healthy cache hits. One - // later open awaits a recovery build, while a permanent failure cannot - // charge every collapse/expand forever. - if ( - (entry.snapshot.state === "degraded" || - entry.snapshot.state === "stale") && - !entry.automaticRetryUsed - ) { - entry.automaticRetryUsed = true; - this.queueRefresh(entry, entry.snapshot.state === "degraded"); - } - return Promise.resolve(entry.snapshot); - } - - /** - * Cold-initialize resolver data without treating an existing degraded/stale - * projection as a later graph open. Navigation reads must be lifecycle - * side-effect-free for the exact revision the browser already displays. - */ - ensureInitialized(scope: WorkspaceScope): Promise { - const entry = this.entries.get(scope.workspaceKey); - if (!entry) return this.get(scope); - if (entry.prerequisiteTokens.size > 0) { - return Promise.resolve(entry.snapshot); - } - if (entry.activeBuild && entry.snapshot.graph === null) { - return entry.activeBuild; - } - return Promise.resolve(entry.snapshot); - } - - /** Marks a workspace dirty and starts (or queues) a background refresh. */ - requestRefresh(scope: WorkspaceScope): SystemGraphSnapshot { - const entry = this.ensureEntry(scope); - entry.automaticRetryUsed = false; - if (entry.prerequisiteTokens.size > 0) { - entry.refreshPending = true; - return entry.snapshot; - } - this.queueRefresh(entry); - return entry.snapshot; - } - - /** - * Fails closed on a raw inventory/source signal without projecting the old - * registry snapshot. The reconciliation coordinator starts the replacement - * build only after its atomic snapshot commit succeeds. - */ - markStale( - scope: WorkspaceScope, - prerequisiteToken = "inventory", - ): SystemGraphSnapshot { - const entry = this.ensureEntry(scope); - entry.prerequisiteTokens.add(prerequisiteToken); - entry.generation += 1; - entry.refreshPending = false; - entry.automaticRetryUsed = true; - const visible = visibleProjection(entry); - return visible.graph === null - ? this.transition(entry, "building", null) - : this.transition( - entry, - "stale", - visible.graph, - false, - visible.navigation, - ); - } - - /** Explicit user recovery: start a fresh projection and await its result. */ - refresh(scope: WorkspaceScope): Promise { - const entry = this.ensureEntry(scope); - entry.automaticRetryUsed = false; - if (entry.prerequisiteTokens.size > 0) { - entry.refreshPending = true; - return entry.activeBuild ?? Promise.resolve(entry.snapshot); - } - return this.queueRefresh(entry) ?? Promise.resolve(entry.snapshot); - } - - /** - * Releases one accepted inventory prerequisite. A projection is rebuilt - * only after every overlapping scan has accepted its current generation. - */ - releasePrerequisite( - scope: WorkspaceScope, - prerequisiteToken = "inventory", - ): SystemGraphSnapshot { - const entry = this.ensureEntry(scope); - if (!entry.prerequisiteTokens.delete(prerequisiteToken)) { - return entry.snapshot; - } - if (entry.prerequisiteTokens.size > 0) return entry.snapshot; - entry.automaticRetryUsed = false; - this.queueRefresh(entry); - return entry.snapshot; - } - - /** Retires a failed prerequisite without projecting the pre-mutation cache. */ - cancelPrerequisite( - workspaceKey: WorkspaceKey, - prerequisiteToken = "inventory", - ): SystemGraphSnapshot | null { - const entry = this.entries.get(workspaceKey); - if (!entry) return null; - entry.prerequisiteTokens.delete(prerequisiteToken); - return entry.snapshot; - } - - /** Awaits the already-started accepted-snapshot build without queuing one. */ - waitForCurrentRefresh( - workspaceKey: WorkspaceKey, - ): Promise { - const entry = this.entries.get(workspaceKey); - return entry?.activeBuild ?? Promise.resolve(entry?.snapshot ?? null); - } - - peek(workspaceKey: WorkspaceKey): SystemGraphSnapshot | null { - return this.entries.get(workspaceKey)?.snapshot ?? null; - } - - /** Resolver data stamped with the exact graph revision it accompanies. */ - peekNavigation( - workspaceKey: WorkspaceKey, - ): SystemGraphNavigationResponse | null { - return this.entries.get(workspaceKey)?.navigation ?? null; - } - - /** Records a refresh prerequisite failure while preserving visible data. */ - reportRefreshFailure(scope: WorkspaceScope): SystemGraphSnapshot { - const entry = this.ensureEntry(scope); - entry.generation += 1; - entry.refreshPending = false; - // Registry recovery must happen before projection. Do not let a later - // graph read rebuild from the stale inventory and relabel it ready; the - // watcher retries the failed inventory callback instead. - entry.automaticRetryUsed = true; - const visible = visibleProjection(entry); - return visible.graph === null - ? this.transition(entry, "degraded", null) - : this.transition( - entry, - "stale", - visible.graph, - false, - visible.navigation, - ); - } - - /** Retires projections for workspace scopes Studio no longer exposes. */ - retain(workspaceKeys: ReadonlySet): void { - for (const workspaceKey of [...this.entries.keys()]) { - if (!workspaceKeys.has(workspaceKey)) this.retire(workspaceKey); - } - } - - /** Stops retaining a scope that Studio no longer exposes. */ - retire(workspaceKey: WorkspaceKey): void { - const entry = this.entries.get(workspaceKey); - if (!entry) return; - entry.retired = true; - entry.generation += 1; - this.revisionFloors.set(workspaceKey, entry.snapshot.revision); - this.entries.delete(workspaceKey); - this.retainBuilderWorkspaces(); - } - - /** Backward-compatible alias for callers that explicitly drop a snapshot. */ - invalidate(workspaceKey: WorkspaceKey): void { - this.retire(workspaceKey); - } - - clear(): void { - for (const workspaceKey of [...this.entries.keys()]) { - this.retire(workspaceKey); - } - this.revisionFloors.clear(); - } - - private ensureEntry(scope: WorkspaceScope): SystemGraphEntry { - const existing = this.entries.get(scope.workspaceKey); - if (existing) { - existing.scope = scope; - return existing; - } - const entry: SystemGraphEntry = { - scope, - snapshot: { - workspaceKey: scope.workspaceKey, - revision: this.revisionFloors.get(scope.workspaceKey) ?? 0, - state: "building", - graph: null, - }, - navigation: { - workspaceKey: scope.workspaceKey, - revision: this.revisionFloors.get(scope.workspaceKey) ?? 0, - targets: [], - }, - activeBuild: null, - generation: 0, - refreshPending: false, - automaticRetryUsed: false, - prerequisiteTokens: new Set(), - retired: false, - }; - this.entries.set(scope.workspaceKey, entry); - return entry; - } - - private queueRefresh( - entry: SystemGraphEntry, - preserveLifecycle = false, - ): Promise | null { - if (entry.retired) return null; - entry.generation += 1; - entry.refreshPending = true; - const visible = visibleProjection(entry); - if (!preserveLifecycle) { - this.transition( - entry, - visible.graph === null ? "building" : "stale", - visible.graph, - false, - visible.navigation, - ); - } - if (entry.activeBuild) return entry.activeBuild; - entry.refreshPending = false; - return this.startBuild(entry); - } - - private startBuild(entry: SystemGraphEntry): Promise { - if (entry.activeBuild) return entry.activeBuild; - const generation = entry.generation; - entry.refreshPending = false; - const visible = visibleProjection(entry); - if (entry.snapshot.state !== "degraded") { - this.transition( - entry, - visible.graph === null ? "building" : "stale", - visible.graph, - false, - visible.navigation, - ); - } - - let build: Promise>>; - try { - build = Promise.resolve(this.builder.build(entry.scope)); - } catch (error) { - build = Promise.reject(error); - } - - const active = build.then( - (result) => this.finishBuild(entry, generation, result), - () => this.finishFailure(entry, generation), - ); - entry.activeBuild = active; - return active; - } - - private finishBuild( - entry: SystemGraphEntry, - generation: number, - result: Awaited>, - ): SystemGraphSnapshot | Promise { - // The superseded build can carry the only callback that starts background - // identity or invocation enrichment. Arm it after the commit decision on - // both paths: before that decision a synchronous refresh could supersede - // the result being committed; omitting it from the losing path can leave - // enrichment pending forever with no follow-up queued. - if (!this.canCommit(entry, generation)) { - const superseded = this.continueAfterSupersededBuild(entry); - this.afterCommit(result.afterCommit); - return superseded; - } - entry.activeBuild = null; - const navigation = (result.navigation ?? []).map((target) => ({ - ...target, - })); - if (result.cacheable) { - entry.automaticRetryUsed = false; - const snapshot = this.transition( - entry, - "ready", - result.graph, - false, - navigation, - ); - this.afterCommit(result.afterCommit); - return snapshot; - } - const snapshot = this.transition( - entry, - "degraded", - result.graph, - false, - navigation, - ); - this.afterCommit(result.afterCommit); - return snapshot; - } - - private finishFailure( - entry: SystemGraphEntry, - generation: number, - ): SystemGraphSnapshot | Promise { - if (!this.canCommit(entry, generation)) { - return this.continueAfterSupersededBuild(entry); - } - entry.activeBuild = null; - const visible = visibleProjection(entry); - return visible.graph === null - ? this.transition(entry, "degraded", null) - : this.transition( - entry, - "stale", - visible.graph, - true, - visible.navigation, - ); - } - - private canCommit(entry: SystemGraphEntry, generation: number): boolean { - return ( - !entry.retired && - this.entries.get(entry.scope.workspaceKey) === entry && - entry.generation === generation - ); - } - - private continueAfterSupersededBuild( - entry: SystemGraphEntry, - ): SystemGraphSnapshot | Promise { - entry.activeBuild = null; - if (entry.retired || this.entries.get(entry.scope.workspaceKey) !== entry) { - this.retainBuilderWorkspaces(); - return entry.snapshot; - } - if (entry.prerequisiteTokens.size > 0) { - return entry.snapshot; - } - if (entry.refreshPending) { - entry.refreshPending = false; - return this.startBuild(entry); - } - return entry.snapshot; - } - - private retainBuilderWorkspaces(): void { - try { - this.builder.retainWorkspaces?.(new Set(this.entries.keys())); - } catch { - // Cache pruning cannot make graph reads or scope retirement fail. - } - } - - private transition( - entry: SystemGraphEntry, - state: SystemGraphLifecycleState, - graph: SystemGraph | null, - forceRevision = false, - navigation: readonly SystemGraphNavigationTarget[] = graph === null - ? [] - : entry.navigation.targets, - ): SystemGraphSnapshot { - if ( - !forceRevision && - entry.snapshot.state === state && - entry.snapshot.graph === graph && - sameNavigation(entry.navigation.targets, navigation) - ) { - return entry.snapshot; - } - entry.snapshot = { - workspaceKey: entry.scope.workspaceKey, - revision: entry.snapshot.revision + 1, - state, - graph, - }; - entry.navigation = { - workspaceKey: entry.scope.workspaceKey, - revision: entry.snapshot.revision, - targets: navigation.map((target) => ({ ...target })), - }; - this.revisionFloors.set(entry.scope.workspaceKey, entry.snapshot.revision); - try { - this.options.onChange?.(entry.snapshot); - } catch { - // Observers (the event bus) cannot make graph refreshes fail. - } - return entry.snapshot; - } - - private afterCommit(callback: (() => void) | undefined): void { - if (!callback) return; - try { - callback(); - } catch { - // Background enrichment is a refresh hint, not part of the committed read. - } - } -} diff --git a/packages/harness/src/core/system-graph-watcher.test.ts b/packages/harness/src/core/system-graph-watcher.test.ts deleted file mode 100644 index 1a33ee4b2..000000000 --- a/packages/harness/src/core/system-graph-watcher.test.ts +++ /dev/null @@ -1,657 +0,0 @@ -import * as fs from "node:fs/promises"; -import * as os from "node:os"; -import * as path from "node:path"; -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; - -import type { WorkspaceScope } from "./system-graph.js"; -import { SystemGraphWatcherManager } from "./system-graph-watcher.js"; -import { - SharedWorkspaceWatchBroker, - type WorkspaceWatchFactory, - type WorkspaceWatchHandle, -} from "./workspace-watch-broker.js"; -import { - snapshotWorkflowSourceRootsAsync, - snapshotWorkspaceWorkflowsAsync, - WorkspaceWatcherManager, -} from "./workspace-watcher.js"; - -const sleep = (ms: number): Promise => - new Promise((resolve) => setTimeout(resolve, ms)); - -let root: string; -let scope: WorkspaceScope; -let manager: SystemGraphWatcherManager; -let onSourceChange: ReturnType; -let onInventoryChange: ReturnType; -let sourceRoots: Set; -let sourceObservations: Map>; - -async function scaffoldAgent(name: string): Promise { - const agentRoot = path.join(root, name); - await fs.mkdir(agentRoot, { recursive: true }); - await fs.writeFile( - path.join(agentRoot, "sapiom.json"), - JSON.stringify({ name }), - ); - await fs.writeFile(path.join(agentRoot, "index.ts"), "export {};\n"); - sourceRoots.add(agentRoot); - sourceObservations.set( - agentRoot, - new Set([path.join(agentRoot, "index.ts")]), - ); - return agentRoot; -} - -describe("SystemGraphWatcherManager", () => { - beforeEach(async () => { - root = await fs.mkdtemp(path.join(os.tmpdir(), "system-graph-watch-")); - scope = { workspaceKey: "workspace-test", root }; - onSourceChange = vi.fn(); - onInventoryChange = vi.fn(); - sourceRoots = new Set(); - sourceObservations = new Map(); - manager = new SystemGraphWatcherManager( - { - listSourceRoots: () => [...sourceRoots], - listSourceObservations: () => - [...sourceObservations].map(([candidateRoot, paths]) => ({ - candidateRoot, - workspaceRoot: root, - paths: [...paths], - })), - onSourceChange, - onInventoryChange, - }, - { - forcePolling: true, - sourceDebounceMs: 10, - inventoryDebounceMs: 10, - inventoryRetryBaseMs: 20, - maxInventoryRetries: 2, - pollIntervalMs: 25, - }, - ); - }); - - afterEach(async () => { - manager.stopAll(); - await fs.rm(root, { recursive: true, force: true }); - }); - - it("refreshes source invocations without reporting inventory churn", async () => { - const agentRoot = await scaffoldAgent("research"); - await scaffoldAgent("growth"); - await manager.start(scope); - await sleep(100); - onSourceChange.mockClear(); - onInventoryChange.mockClear(); - - await fs.writeFile( - path.join(agentRoot, "index.ts"), - 'ctx.sapiom.agents.run({ definition: "growth" });\n', - ); - await vi.waitFor(() => expect(onSourceChange).toHaveBeenCalled(), { - timeout: 2_000, - interval: 20, - }); - - expect(onSourceChange).toHaveBeenCalled(); - expect(onSourceChange.mock.calls.at(-1)?.[0]).toEqual(scope); - expect(onSourceChange.mock.calls.at(-1)?.[1]).toEqual([agentRoot]); - expect(onInventoryChange).not.toHaveBeenCalled(); - }); - - it("routes native paths, ignores generated churn, and recovers via polling", async () => { - let watchListener!: Parameters[1]; - let errorListener!: (error: Error) => void; - const close = vi.fn(); - const watchFactory: WorkspaceWatchFactory = (_watchRoot, listener) => { - watchListener = listener; - const handle: WorkspaceWatchHandle = { - close, - on: (_event, onError) => { - errorListener = onError; - return handle; - }, - }; - return handle; - }; - manager = new SystemGraphWatcherManager( - { - listSourceRoots: () => [...sourceRoots], - listSourceObservations: () => - [...sourceObservations].map(([candidateRoot, paths]) => ({ - candidateRoot, - workspaceRoot: root, - paths: [...paths], - })), - onSourceChange, - onInventoryChange, - }, - { - watchFactory, - sourceDebounceMs: 10, - inventoryDebounceMs: 10, - pollIntervalMs: 25, - }, - ); - const agentRoot = await scaffoldAgent("research"); - await manager.start(scope); - await sleep(100); - onSourceChange.mockClear(); - - watchListener("change", "research/index.ts"); - await vi.waitFor(() => expect(onSourceChange).toHaveBeenCalled(), { - timeout: 2_000, - interval: 20, - }); - expect(onSourceChange.mock.calls.at(-1)?.[1]).toEqual([ - path.join(agentRoot, "index.ts"), - ]); - - onSourceChange.mockClear(); - watchListener("change", "node_modules/pkg/index.ts"); - await sleep(50); - expect(onSourceChange).not.toHaveBeenCalled(); - - onInventoryChange.mockClear(); - watchListener("rename", "research/.git"); - await vi.waitFor(() => expect(onInventoryChange).toHaveBeenCalledOnce(), { - timeout: 2_000, - interval: 20, - }); - onInventoryChange.mockClear(); - watchListener("rename", "research/.git/objects/pack-1"); - await sleep(50); - expect(onInventoryChange).not.toHaveBeenCalled(); - - errorListener(new Error("recursive watch unavailable")); - expect(close).toHaveBeenCalledTimes(1); - await sleep(100); - onSourceChange.mockClear(); - await fs.writeFile( - path.join(agentRoot, "index.ts"), - "export const recovered = true;\n", - ); - await vi.waitFor(() => expect(onSourceChange).toHaveBeenCalled(), { - timeout: 2_000, - interval: 20, - }); - expect(onSourceChange.mock.calls.at(-1)?.[1]).toEqual([agentRoot]); - }); - - it("reports agent inventory additions and removals", async () => { - await manager.start(scope); - await sleep(100); - const agentRoot = await scaffoldAgent("growth"); - await vi.waitFor( - () => expect(onInventoryChange).toHaveBeenCalledWith(scope), - { timeout: 2_000, interval: 20 }, - ); - - onInventoryChange.mockClear(); - sourceRoots.delete(agentRoot); - await fs.rm(agentRoot, { recursive: true, force: true }); - await vi.waitFor( - () => expect(onInventoryChange).toHaveBeenCalledWith(scope), - { timeout: 2_000, interval: 20 }, - ); - }); - - it("retries a failed inventory refresh without another filesystem edit", async () => { - onInventoryChange - .mockRejectedValueOnce(new Error("registry unavailable")) - .mockResolvedValue(undefined); - await manager.start(scope); - await scaffoldAgent("growth"); - - await vi.waitFor(() => expect(onInventoryChange).toHaveBeenCalledTimes(2), { - timeout: 2_000, - interval: 20, - }); - }); - - it("bounds inventory retries until a later filesystem change", async () => { - onInventoryChange.mockRejectedValue(new Error("registry unavailable")); - await manager.start(scope); - await scaffoldAgent("growth"); - - await vi.waitFor(() => expect(onInventoryChange).toHaveBeenCalledTimes(3), { - timeout: 2_000, - interval: 20, - }); - await sleep(200); - expect(onInventoryChange).toHaveBeenCalledTimes(3); - - await scaffoldAgent("reporting"); - await vi.waitFor( - () => expect(onInventoryChange.mock.calls.length).toBeGreaterThan(3), - { timeout: 2_000, interval: 20 }, - ); - }); - - it("bounds source retries until a later raw event rearms recovery", async () => { - let watchListener!: Parameters[1]; - const watchFactory: WorkspaceWatchFactory = (_watchRoot, listener) => { - watchListener = listener; - const handle: WorkspaceWatchHandle = { - close: vi.fn(), - on: () => handle, - }; - return handle; - }; - const agentRoot = await scaffoldAgent("retry-source"); - onSourceChange.mockRejectedValue(new Error("registry unavailable")); - manager = new SystemGraphWatcherManager( - { - listSourceRoots: () => [...sourceRoots], - listSourceObservations: () => [], - onSourceChange, - onInventoryChange, - }, - { - watchFactory, - sourceDebounceMs: 1, - inventoryRetryBaseMs: 10, - maxSourceRetries: 2, - }, - ); - await manager.start(scope); - - vi.useFakeTimers(); - try { - watchListener( - "change", - path.relative(root, path.join(agentRoot, "index.ts")), - ); - await vi.advanceTimersByTimeAsync(1); - expect(onSourceChange).toHaveBeenCalledTimes(1); - await vi.advanceTimersByTimeAsync(10); - expect(onSourceChange).toHaveBeenCalledTimes(2); - await vi.advanceTimersByTimeAsync(20); - expect(onSourceChange).toHaveBeenCalledTimes(3); - await vi.advanceTimersByTimeAsync(10_000); - expect(onSourceChange).toHaveBeenCalledTimes(3); - - watchListener( - "change", - path.relative(root, path.join(agentRoot, "index.ts")), - ); - await vi.advanceTimersByTimeAsync(1); - await vi.advanceTimersByTimeAsync(10); - await vi.advanceTimersByTimeAsync(20); - expect(onSourceChange).toHaveBeenCalledTimes(6); - } finally { - manager.stopAll(); - vi.useRealTimers(); - } - }); - - it("polls every registered source file past Canvas's project-sized cap", async () => { - const agentRoot = await scaffoldAgent("large"); - await Promise.all( - Array.from({ length: 425 }, (_, index) => - fs.writeFile( - path.join(agentRoot, `step-${index.toString().padStart(3, "0")}.ts`), - `export const step${index} = ${index};\n`, - ), - ), - ); - sourceObservations.get(agentRoot)?.add(path.join(agentRoot, "step-424.ts")); - await manager.start(scope); - await sleep(200); - onSourceChange.mockClear(); - - await fs.writeFile( - path.join(agentRoot, "step-424.ts"), - "export const step424 = 424_424;\n", - ); - - await vi.waitFor(() => expect(onSourceChange).toHaveBeenCalled(), { - timeout: 2_000, - interval: 20, - }); - }); - - it("ignores non-source/generated churn but notices an unregistered source candidate", async () => { - await manager.start(scope); - await sleep(100); - onSourceChange.mockClear(); - onInventoryChange.mockClear(); - await fs.writeFile(path.join(root, "README.md"), "notes\n"); - await fs.mkdir(path.join(root, "node_modules", "pkg"), { - recursive: true, - }); - await fs.writeFile( - path.join(root, "node_modules", "pkg", "index.ts"), - "export {};\n", - ); - await fs.mkdir(path.join(root, "unregistered"), { recursive: true }); - await fs.writeFile( - path.join(root, "unregistered", "index.ts"), - "export const ignored = true;\n", - ); - await sleep(300); - - expect(onSourceChange).not.toHaveBeenCalled(); - expect(onInventoryChange).toHaveBeenCalledWith(scope); - }); - - it("does not re-baseline an existing workspace on repeated opens", async () => { - await Promise.all([manager.start(scope), manager.start(scope)]); - expect(manager.size).toBe(1); - }); - - it("retires watchers for scopes no longer exposed by Studio", async () => { - await manager.start(scope); - manager.retain(new Set()); - expect(manager.size).toBe(0); - }); - - it("closes and suppresses a pending watcher immediately when its scope retires", async () => { - let releaseBaseline!: () => void; - const baselineGate = new Promise((resolve) => { - releaseBaseline = resolve; - }); - let watchListener!: Parameters[1]; - const close = vi.fn(); - const onPotentialChange = vi.fn(); - const watchFactory: WorkspaceWatchFactory = (_watchRoot, listener) => { - watchListener = listener; - const handle: WorkspaceWatchHandle = { - close, - on: () => handle, - }; - return handle; - }; - manager = new SystemGraphWatcherManager( - { - listSourceRoots: () => [], - onSourceChange, - onInventoryChange, - onPotentialChange, - }, - { - watchFactory, - beforeInitialSnapshot: () => baselineGate, - sourceDebounceMs: 5, - inventoryDebounceMs: 5, - }, - ); - - const starting = manager.start(scope); - manager.retain(new Set()); - - expect(close).toHaveBeenCalledTimes(1); - expect(manager.size).toBe(0); - watchListener("rename", "agent/index.ts"); - await sleep(20); - expect(onPotentialChange).not.toHaveBeenCalled(); - expect(onSourceChange).not.toHaveBeenCalled(); - expect(onInventoryChange).not.toHaveBeenCalled(); - - releaseBaseline(); - await starting; - expect(manager.size).toBe(0); - expect(close).toHaveBeenCalledTimes(1); - }); - - it("closes an armed watcher when its initial baseline rejects", async () => { - let watchListener!: Parameters[1]; - const close = vi.fn(); - const onPotentialChange = vi.fn(); - const watchFactory: WorkspaceWatchFactory = (_watchRoot, listener) => { - watchListener = listener; - const handle: WorkspaceWatchHandle = { - close, - on: () => handle, - }; - return handle; - }; - manager = new SystemGraphWatcherManager( - { - listSourceRoots: () => [], - onSourceChange, - onInventoryChange, - onPotentialChange, - }, - { - watchFactory, - beforeInitialSnapshot: () => - Promise.reject(new Error("baseline unavailable")), - sourceDebounceMs: 5, - inventoryDebounceMs: 5, - }, - ); - - await expect(manager.start(scope)).rejects.toThrow("baseline unavailable"); - expect(close).toHaveBeenCalledTimes(1); - expect(manager.size).toBe(0); - watchListener("rename", "agent/index.ts"); - await sleep(20); - expect(onPotentialChange).not.toHaveBeenCalled(); - expect(onSourceChange).not.toHaveBeenCalled(); - expect(onInventoryChange).not.toHaveBeenCalled(); - }); - - it("reconciles every retained root when an ambiguous event races the initial baseline", async () => { - const agentRoot = await scaffoldAgent("nested-checkout"); - let releaseBaseline!: () => void; - const baselineGate = new Promise((resolve) => { - releaseBaseline = resolve; - }); - let watchListener!: Parameters[1]; - const watchFactory: WorkspaceWatchFactory = (_watchRoot, listener) => { - watchListener = listener; - const handle: WorkspaceWatchHandle = { - close: vi.fn(), - on: () => handle, - }; - return handle; - }; - manager = new SystemGraphWatcherManager( - { - listSourceRoots: () => [...sourceRoots], - listSourceObservations: () => [], - onSourceChange, - onInventoryChange, - }, - { - watchFactory, - beforeInitialSnapshot: () => baselineGate, - sourceDebounceMs: 5, - inventoryDebounceMs: 5, - }, - ); - - const starting = manager.start(scope); - watchListener("rename", null); - - await vi.waitFor(() => expect(onSourceChange).toHaveBeenCalled(), { - timeout: 2_000, - interval: 10, - }); - expect(onSourceChange.mock.calls.at(-1)?.[1]).toEqual([agentRoot]); - - releaseBaseline(); - await starting; - }); - - it("owns one polling baseline and reconciles an edit absorbed into it", async () => { - const agentRoot = await scaffoldAgent("polling-baseline"); - let releaseBaseline!: () => void; - const baselineGate = new Promise((resolve) => { - releaseBaseline = resolve; - }); - const snapshotWorkspace = vi.fn(snapshotWorkspaceWorkflowsAsync); - const snapshotSources = vi.fn(snapshotWorkflowSourceRootsAsync); - const onPotentialChange = vi.fn(); - manager = new SystemGraphWatcherManager( - { - listSourceRoots: () => [...sourceRoots], - listSourceObservations: () => [], - onSourceChange, - onInventoryChange, - onPotentialChange, - }, - { - forcePolling: true, - beforeInitialSnapshot: () => baselineGate, - snapshotWorkspace, - snapshotSources, - sourceDebounceMs: 5, - pollIntervalMs: 60_000, - }, - ); - - const starting = manager.start(scope); - await Promise.resolve(); - expect(snapshotWorkspace).not.toHaveBeenCalled(); - expect(snapshotSources).not.toHaveBeenCalled(); - - await fs.writeFile( - path.join(agentRoot, "index.ts"), - "export const changedDuringBaseline = true;\n", - ); - releaseBaseline(); - await starting; - - await vi.waitFor(() => expect(onSourceChange).toHaveBeenCalledOnce(), { - timeout: 2_000, - interval: 10, - }); - expect(snapshotWorkspace).toHaveBeenCalledTimes(1); - expect(snapshotSources).toHaveBeenCalledTimes(1); - expect(onPotentialChange).toHaveBeenCalledOnce(); - expect(onPotentialChange).toHaveBeenCalledWith(scope, null); - expect(onSourceChange).toHaveBeenCalledWith(scope, [agentRoot]); - }); - - it("shares one canonical-root watcher across two sessions and a graph caller", async () => { - const agentRoot = await scaffoldAgent("shared-agent"); - let watchListener!: Parameters[1]; - const close = vi.fn(); - const watchFactory = vi.fn( - (_watchRoot, listener) => { - watchListener = listener; - const handle: WorkspaceWatchHandle = { - close, - on: () => handle, - }; - return handle; - }, - ); - const broker = new SharedWorkspaceWatchBroker({ - watchFactory, - sourceDebounceMs: 5, - inventoryDebounceMs: 5, - }); - const sessionChange = vi.fn(); - const sessionPotential = vi.fn(); - const sessions = new WorkspaceWatcherManager({ - sharedWatchBroker: broker, - listSourceRoots: () => [...sourceRoots], - listSourceObservations: () => [], - onPotentialChange: sessionPotential, - onChange: sessionChange, - }); - const graphSourceChange = vi.fn(); - const graphPotential = vi.fn(); - manager = new SystemGraphWatcherManager( - { - listSourceRoots: () => [...sourceRoots], - listSourceObservations: () => [], - onPotentialChange: graphPotential, - onSourceChange: graphSourceChange, - onInventoryChange, - }, - { sharedBroker: broker }, - ); - - sessions.start("session-a", root); - sessions.start("session-b", path.join(root, ".")); - await manager.start(scope); - - expect(watchFactory).toHaveBeenCalledTimes(1); - expect(broker.size).toBe(1); - watchListener( - "change", - path.relative(root, path.join(agentRoot, "index.ts")), - ); - - await vi.waitFor(() => expect(graphSourceChange).toHaveBeenCalledOnce(), { - timeout: 2_000, - interval: 10, - }); - expect(sessionChange).toHaveBeenCalledTimes(2); - expect(sessionChange.mock.calls.map((call) => call[0]).sort()).toEqual([ - "session-a", - "session-b", - ]); - expect(sessionChange.mock.calls.map((call) => call[1])).toEqual([ - [agentRoot], - [agentRoot], - ]); - expect(sessionPotential).toHaveBeenCalledTimes(2); - expect(graphPotential).toHaveBeenCalledOnce(); - - sessions.stopAll(); - expect(broker.size).toBe(1); - expect(close).not.toHaveBeenCalled(); - sessionChange.mockClear(); - graphSourceChange.mockClear(); - watchListener( - "change", - path.relative(root, path.join(agentRoot, "index.ts")), - ); - await vi.waitFor(() => expect(graphSourceChange).toHaveBeenCalledOnce(), { - timeout: 2_000, - interval: 10, - }); - expect(sessionChange).not.toHaveBeenCalled(); - - manager.retain(new Set()); - expect(broker.size).toBe(0); - expect(close).toHaveBeenCalledTimes(1); - }); - - it("cleans a rejected shared subscription so the same scope can retry", async () => { - let attempts = 0; - const closes: Array> = []; - const watchFactory = vi.fn(() => { - const close = vi.fn(); - closes.push(close); - const handle: WorkspaceWatchHandle = { - close, - on: () => handle, - }; - return handle; - }); - const broker = new SharedWorkspaceWatchBroker({ - watchFactory, - beforeInitialSnapshot: () => { - attempts += 1; - if (attempts === 1) throw new Error("first baseline failed"); - }, - }); - manager = new SystemGraphWatcherManager( - { - listSourceRoots: () => [], - onSourceChange, - onInventoryChange, - }, - { sharedBroker: broker }, - ); - - await expect(manager.start(scope)).rejects.toThrow("first baseline failed"); - expect(manager.size).toBe(0); - expect(broker.size).toBe(0); - expect(closes[0]).toHaveBeenCalledTimes(1); - - await manager.start(scope); - expect(watchFactory).toHaveBeenCalledTimes(2); - expect(manager.size).toBe(1); - expect(broker.size).toBe(1); - }); -}); diff --git a/packages/harness/src/core/system-graph-watcher.ts b/packages/harness/src/core/system-graph-watcher.ts deleted file mode 100644 index ab94d577b..000000000 --- a/packages/harness/src/core/system-graph-watcher.ts +++ /dev/null @@ -1,169 +0,0 @@ -import type { WorkspaceKey } from "../shared/system-graph.js"; -import { canonicalGraphPath } from "./canonical-graph-path.js"; -import type { WorkspaceScope } from "./system-graph.js"; -import type { WorkflowSourceObservation } from "./workspace-watcher.js"; -import { - type SharedWorkspaceWatchBrokerLike, - WorkspaceRootWatcher, - type WorkspaceWatchOptions, -} from "./workspace-watch-broker.js"; - -export interface SystemGraphWatcherCallbacks { - /** Current registry roots inside this scope; read lazily on every poll. */ - listSourceRoots: (scope: WorkspaceScope) => readonly string[]; - listSourceObservations?: ( - scope: WorkspaceScope, - ) => readonly WorkflowSourceObservation[]; - onSourceChange: ( - scope: WorkspaceScope, - /** Null when the platform can only report a workspace-level change. */ - sourcePaths: readonly string[] | null, - ) => void | Promise; - onInventoryChange: (scope: WorkspaceScope) => void | Promise; - /** Synchronous raw-event fail-close hook, before debounce or async I/O. */ - onPotentialChange?: ( - scope: WorkspaceScope, - sourcePaths: readonly string[] | null, - ) => void; -} - -export interface SystemGraphWatcherOptions extends WorkspaceWatchOptions { - /** Optional process-wide root broker shared with session watchers. */ - sharedBroker?: SharedWorkspaceWatchBrokerLike; -} - -/** One watcher per requested workspace, independent of harness sessions. */ -export class SystemGraphWatcherManager { - private readonly watchers = new Map(); - private readonly pendingStarts = new Map< - WorkspaceKey, - { - root: string; - token: object; - watcher: WorkspaceRootWatcher; - promise: Promise; - } - >(); - private readonly sharedSubscriptions = new Map< - WorkspaceKey, - { root: string; key: object } - >(); - - constructor( - private readonly callbacks: SystemGraphWatcherCallbacks, - private readonly options: SystemGraphWatcherOptions = {}, - ) {} - - start(scope: WorkspaceScope): Promise { - const sharedBroker = this.options.sharedBroker; - if (sharedBroker) { - const canonicalRoot = canonicalGraphPath(scope.root); - const existingShared = this.sharedSubscriptions.get(scope.workspaceKey); - if (existingShared?.root === canonicalRoot) return Promise.resolve(); - this.stop(scope.workspaceKey); - const key = {}; - this.sharedSubscriptions.set(scope.workspaceKey, { - root: canonicalRoot, - key, - }); - return sharedBroker - .subscribe(key, { - root: scope.root, - listSourceRoots: () => this.callbacks.listSourceRoots(scope), - listSourceObservations: () => - this.callbacks.listSourceObservations?.(scope) ?? [], - onPotentialChange: (paths) => - this.callbacks.onPotentialChange?.(scope, paths), - onSourceChange: (paths) => - this.callbacks.onSourceChange(scope, paths), - onInventoryChange: () => this.callbacks.onInventoryChange(scope), - }) - .catch((error: unknown) => { - if (this.sharedSubscriptions.get(scope.workspaceKey)?.key === key) { - this.sharedSubscriptions.delete(scope.workspaceKey); - } - throw error; - }); - } - const existing = this.watchers.get(scope.workspaceKey); - if (existing?.root === scope.root) return Promise.resolve(); - const pending = this.pendingStarts.get(scope.workspaceKey); - if (pending?.root === scope.root) return pending.promise; - this.stop(scope.workspaceKey); - const token = {}; - const started = WorkspaceRootWatcher.begin( - scope.root, - { - listSourceRoots: () => this.callbacks.listSourceRoots(scope), - listSourceObservations: () => - this.callbacks.listSourceObservations?.(scope) ?? [], - onPotentialChange: (paths) => - this.callbacks.onPotentialChange?.(scope, paths), - onSourceChange: (paths) => this.callbacks.onSourceChange(scope, paths), - onInventoryChange: () => this.callbacks.onInventoryChange(scope), - }, - this.options, - ); - const promise = started.ready - .then( - () => { - const current = this.pendingStarts.get(scope.workspaceKey); - if (current?.token !== token) { - started.watcher.close(); - return; - } - this.watchers.set(scope.workspaceKey, started.watcher); - }, - (error: unknown) => { - started.watcher.close(); - throw error; - }, - ) - .finally(() => { - if (this.pendingStarts.get(scope.workspaceKey)?.token === token) { - this.pendingStarts.delete(scope.workspaceKey); - } - }); - this.pendingStarts.set(scope.workspaceKey, { - root: scope.root, - token, - watcher: started.watcher, - promise, - }); - return promise; - } - - retain(workspaceKeys: ReadonlySet): void { - const tracked = new Set([ - ...this.watchers.keys(), - ...this.pendingStarts.keys(), - ...this.sharedSubscriptions.keys(), - ]); - for (const workspaceKey of tracked) { - if (!workspaceKeys.has(workspaceKey)) this.stop(workspaceKey); - } - } - - stop(workspaceKey: WorkspaceKey): void { - const shared = this.sharedSubscriptions.get(workspaceKey); - if (shared) this.options.sharedBroker?.unsubscribe(shared.key); - this.sharedSubscriptions.delete(workspaceKey); - this.pendingStarts.get(workspaceKey)?.watcher.close(); - this.pendingStarts.delete(workspaceKey); - this.watchers.get(workspaceKey)?.close(); - this.watchers.delete(workspaceKey); - } - - stopAll(): void { - const tracked = new Set([ - ...this.watchers.keys(), - ...this.pendingStarts.keys(), - ...this.sharedSubscriptions.keys(), - ]); - for (const workspaceKey of tracked) this.stop(workspaceKey); - } - - get size(): number { - return this.watchers.size + this.sharedSubscriptions.size; - } -} diff --git a/packages/harness/src/core/system-graph.test.ts b/packages/harness/src/core/system-graph.test.ts deleted file mode 100644 index 67c1427ca..000000000 --- a/packages/harness/src/core/system-graph.test.ts +++ /dev/null @@ -1,1423 +0,0 @@ -import * as path from "node:path"; -import { fileURLToPath } from "node:url"; -import { describe, expect, it, vi } from "vitest"; - -import type { PackageInventoryAgent } from "@sapiom/agent"; -import type { WorkflowInfo } from "../shared/types.js"; -import { - HarnessRegistryInventoryProvider, - CachedAgentInvocationProvider, - StaticSystemGraphBuilder, - type AgentInventoryProvider, - type AgentInventoryResult, - type AgentInvocationProvider, - type AgentInvocationProviderResult, - type WorkspaceScope, -} from "./system-graph.js"; - -const FIXTURE = path.join( - path.dirname(fileURLToPath(import.meta.url)), - "__fixtures__", - "system-graph-workspace", -); - -function workflow( - name: string, - relativePath: string, - definitionSlug: string | null, -): WorkflowInfo { - return { - name, - path: path.join(FIXTURE, relativePath), - definitionId: definitionSlug ? 1 : null, - definitionSlug, - source: "scan", - }; -} - -async function buildGraph( - builder: StaticSystemGraphBuilder, - scope: WorkspaceScope, -) { - return (await builder.build(scope)).graph; -} - -function invocationProvider( - listInvocations: ( - sourceRoot: string, - ) => Promise, -): AgentInvocationProvider { - return { - listInvocations: vi.fn((caller) => listInvocations(caller.sourceRoot)), - }; -} - -const EMPTY_INVOCATIONS: AgentInvocationProviderResult = { - invocations: [], - warnings: [], -}; - -const EVIDENCE = [{ file: "index.ts", line: 1, column: 1 }]; -const REVISION = `sha256:${"a".repeat(64)}` as const; - -function inventoryResult( - scope: WorkspaceScope, - agents: Array<{ - agentKey: string; - label: string; - sourceRoot?: string; - workflowPath?: string; - definitionId?: number | null; - definitionSlug?: string | null; - resolutionAliases?: string[]; - provisional?: boolean; - identityIssue?: - | "identity-pending" - | "identity-unavailable" - | "identity-invalid" - | "duplicate-agent-key"; - candidateAgentKey?: string; - }>, - options: { - warnings?: AgentInventoryResult["warnings"]; - degraded?: boolean; - identitySettled?: boolean; - discoveryComplete?: boolean; - } = {}, -): AgentInventoryResult { - const records = agents.map((agent) => { - const sourceRoot = - agent.sourceRoot ?? path.join(scope.root, agent.agentKey); - const relative = - path.relative(scope.root, sourceRoot).split(path.sep).join("/") || "."; - const provisional = - agent.provisional ?? agent.agentKey.startsWith("local:"); - let publicAgent: PackageInventoryAgent; - if (!provisional) { - publicAgent = { - agentKey: agent.agentKey, - identityStatus: "canonical", - path: relative, - entrypoint: "index.ts", - }; - } else if (agent.identityIssue === "duplicate-agent-key") { - if (!agent.candidateAgentKey) { - throw new Error( - "Duplicate inventory fixtures require a candidate agent key", - ); - } - publicAgent = { - agentKey: agent.agentKey, - identityStatus: "provisional", - identityIssue: "duplicate-agent-key", - candidateAgentKey: agent.candidateAgentKey, - path: relative, - entrypoint: "index.ts", - }; - } else { - publicAgent = { - agentKey: agent.agentKey, - identityStatus: "provisional", - identityIssue: agent.identityIssue ?? "identity-unavailable", - path: relative, - entrypoint: "index.ts", - }; - } - return { - public: publicAgent, - context: { - agentKey: agent.agentKey, - definitionId: agent.definitionId ?? null, - definitionSlug: agent.definitionSlug ?? null, - label: agent.label, - resolutionAliases: agent.resolutionAliases ?? [], - sourceRoot, - workflowPath: agent.workflowPath ?? sourceRoot, - path: relative, - entrypoint: "index.ts", - }, - }; - }); - const degraded = - options.degraded ?? - records.some((record) => record.public.identityStatus === "provisional"); - return { - inventory: { - protocol: 1, - version: { - kind: "working-tree", - workspaceKey: scope.workspaceKey, - revision: REVISION, - }, - status: degraded ? "degraded" : "complete", - agents: records.map((record) => record.public), - }, - context: records.map((record) => record.context), - warnings: options.warnings ?? [], - identitySettled: - options.identitySettled ?? - !records.some( - (record) => - record.public.identityStatus === "provisional" && - record.public.identityIssue === "identity-pending", - ), - discoveryComplete: options.discoveryComplete ?? true, - }; -} - -describe("StaticSystemGraphBuilder", () => { - const scope: WorkspaceScope = { - workspaceKey: "workspace-fixture", - root: FIXTURE, - }; - - it("projects literal Research -> Growth blocking and async calls into the public contract", async () => { - const inventory: AgentInventoryProvider = { - listAgents: vi.fn(async () => - inventoryResult(scope, [ - { - agentKey: "growth", - label: "Growth", - sourceRoot: path.join(FIXTURE, "growth"), - resolutionAliases: ["growth"], - }, - { - agentKey: "research", - label: "Research", - sourceRoot: path.join(FIXTURE, "research"), - resolutionAliases: ["research"], - }, - ]), - ), - }; - - const builder = new StaticSystemGraphBuilder(inventory); - const first = await builder.build(scope); - - // The cold phase is inventory-only: all cards and navigation are available - // before bounded project invocation I/O starts. - expect(first.cacheable).toBe(false); - expect(first.graph.nodes).toHaveLength(2); - expect(first.graph.edges).toEqual([]); - expect(first.navigation).toHaveLength(2); - first.afterCommit?.(); - - let graph = first.graph; - await vi.waitFor(async () => { - graph = (await builder.build(scope)).graph; - expect(graph.edges).toHaveLength(2); - }); - - expect(graph).toEqual({ - kind: "system", - scope: { kind: "working-tree", workspaceKey: "workspace-fixture" }, - nodes: [ - { id: "agent:growth", agentKey: "growth", label: "Growth" }, - { id: "agent:research", agentKey: "research", label: "Research" }, - ], - edges: [ - { - from: "agent:research", - to: "agent:growth", - kind: "invokes", - basis: "static-invocation", - mode: "blocking", - }, - { - from: "agent:research", - to: "agent:growth", - kind: "invokes", - basis: "static-invocation", - mode: "async", - }, - ], - warnings: [], - }); - expect(JSON.stringify(graph)).not.toContain(FIXTURE); - }); - - it("returns inventory navigation while invocation extraction is still held", async () => { - const inventory: AgentInventoryProvider = { - listAgents: vi.fn(async () => - inventoryResult(scope, [ - { - agentKey: "growth", - label: "Growth", - resolutionAliases: ["growth"], - }, - { - agentKey: "research", - label: "Research", - resolutionAliases: ["research"], - }, - ]), - ), - }; - let release!: (result: AgentInvocationProviderResult) => void; - const held = new Promise((resolve) => { - release = resolve; - }); - const inner = invocationProvider(async (root) => - root.endsWith("research") ? held : EMPTY_INVOCATIONS, - ); - const onChange = vi.fn(); - const invocations = new CachedAgentInvocationProvider( - inner, - async () => "unused", - { concurrency: 1, onChange }, - ); - const builder = new StaticSystemGraphBuilder(inventory, invocations); - - const cold = await builder.build(scope); - - expect(inner.listInvocations).not.toHaveBeenCalled(); - expect(cold.cacheable).toBe(false); - expect(cold.graph.nodes.map((node) => node.agentKey)).toEqual([ - "growth", - "research", - ]); - expect(cold.graph.edges).toEqual([]); - expect(cold.navigation?.map((target) => target.agentKey)).toEqual([ - "growth", - "research", - ]); - - cold.afterCommit?.(); - await vi.waitFor(() => expect(inner.listInvocations).toHaveBeenCalled()); - // The held project task cannot withhold the already-returned inventory. - expect(cold.graph.nodes).toHaveLength(2); - release({ - invocations: [ - { - target: "growth", - mode: "blocking", - evidence: EVIDENCE, - }, - ], - warnings: [], - }); - - await vi.waitFor(() => expect(onChange).toHaveBeenCalledTimes(1)); - const enriched = await builder.build(scope); - expect(enriched.graph.edges).toEqual([ - { - from: "agent:research", - to: "agent:growth", - kind: "invokes", - basis: "static-invocation", - mode: "blocking", - }, - ]); - expect(enriched.cacheable).toBe(true); - }); - - it("deduplicates by mode, retains dual-mode edges, and reports duplicate and unresolved targets", async () => { - const inventory: AgentInventoryProvider = { - listAgents: vi.fn(async () => - inventoryResult(scope, [ - { - agentKey: "research", - definitionId: 1, - definitionSlug: "research", - label: "Research", - resolutionAliases: ["research"], - }, - { - agentKey: "growth", - definitionId: 2, - definitionSlug: "growth", - label: "Growth", - resolutionAliases: ["growth"], - }, - ]), - ), - }; - const invocations = invocationProvider(async (root) => - root.endsWith("research") - ? { - invocations: [ - { - target: "growth", - mode: "blocking", - evidence: [ - ...EVIDENCE, - { file: "second.ts", line: 2, column: 1 }, - ], - }, - { target: "growth", mode: "async", evidence: EVIDENCE }, - { target: "research", mode: "async", evidence: EVIDENCE }, - { target: "missing", mode: "async", evidence: EVIDENCE }, - ], - warnings: [], - } - : EMPTY_INVOCATIONS, - ); - - const graph = await buildGraph( - new StaticSystemGraphBuilder(inventory, invocations), - scope, - ); - expect(graph.edges).toEqual([ - { - from: "agent:research", - to: "agent:growth", - kind: "invokes", - basis: "static-invocation", - mode: "blocking", - }, - { - from: "agent:research", - to: "agent:growth", - kind: "invokes", - basis: "static-invocation", - mode: "async", - }, - ]); - expect(graph.warnings.map((warning) => warning.code)).toEqual([ - "duplicate-edge", - "unresolved-target", - ]); - expect(graph.warnings[0]).toEqual({ - code: "duplicate-edge", - agentKey: "research", - message: "Research invokes Growth more than once.", - }); - expect(JSON.stringify(graph)).not.toContain("/private/"); - }); - - it("projects dynamic extraction warnings without degrading cacheability or leaking evidence", async () => { - const inventory: AgentInventoryProvider = { - listAgents: vi.fn(async () => - inventoryResult(scope, [ - { - agentKey: "research", - definitionId: 1, - definitionSlug: "research", - label: "Research", - resolutionAliases: ["research"], - }, - ]), - ), - }; - const invocations = invocationProvider(async () => ({ - invocations: [], - warnings: [ - { - code: "dynamic-target", - mode: "blocking", - evidence: { file: "private/index.ts", line: 8, column: 5 }, - }, - ], - })); - - const built = await new StaticSystemGraphBuilder( - inventory, - invocations, - ).build(scope); - - expect(built.cacheable).toBe(true); - expect(built.graph.edges).toEqual([]); - expect(built.graph.warnings).toEqual([ - { - code: "dynamic-target", - agentKey: "research", - message: "Research has a dynamic agent target that V0 cannot resolve.", - }, - ]); - expect(JSON.stringify(built.graph)).not.toContain("private/index.ts"); - }); - - it("keeps duplicate definition slugs as unique nodes and reports ambiguous launches", async () => { - const inventory: AgentInventoryProvider = { - listAgents: vi.fn(async () => - inventoryResult( - scope, - [ - { - agentKey: "caller", - label: "Caller", - resolutionAliases: ["caller"], - }, - { - agentKey: "local:growth", - label: "First copy", - sourceRoot: path.join(FIXTURE, "growth"), - resolutionAliases: ["shared"], - provisional: true, - identityIssue: "duplicate-agent-key", - candidateAgentKey: "shared", - }, - { - agentKey: "local:research", - label: "Second copy", - sourceRoot: path.join(FIXTURE, "research"), - resolutionAliases: ["shared"], - provisional: true, - identityIssue: "duplicate-agent-key", - candidateAgentKey: "shared", - }, - ], - { - degraded: true, - warnings: [ - { - code: "duplicate-agent-key", - agentKey: "shared", - message: - "Multiple agents use shared; kept each with a local identity.", - }, - ], - }, - ), - ), - }; - const invocations = invocationProvider(async (root) => - root.endsWith("caller") - ? { - invocations: [ - { target: "shared", mode: "async", evidence: EVIDENCE }, - ], - warnings: [], - } - : EMPTY_INVOCATIONS, - ); - - const graph = await buildGraph( - new StaticSystemGraphBuilder(inventory, invocations), - scope, - ); - - expect(graph.nodes.map((node) => node.id)).toEqual([ - "agent:caller", - "agent:local:growth", - "agent:local:research", - ]); - expect(new Set(graph.nodes.map((node) => node.id)).size).toBe(3); - expect(graph.edges).toEqual([]); - expect(graph.warnings).toEqual([ - { - code: "duplicate-agent-key", - agentKey: "shared", - message: "Multiple agents use shared; kept each with a local identity.", - }, - { - code: "unresolved-target", - agentKey: "caller", - message: "Caller invokes ambiguous agent shared.", - }, - ]); - expect(JSON.stringify(graph)).not.toContain(FIXTURE); - }); - - it("synthesizes a duplicate warning from public identity evidence", async () => { - const result = inventoryResult( - scope, - [ - { - agentKey: "local:only", - label: "Only", - sourceRoot: path.join(FIXTURE, "only"), - provisional: true, - identityIssue: "duplicate-agent-key", - candidateAgentKey: "shared", - resolutionAliases: ["shared"], - }, - ], - { degraded: true, warnings: [] }, - ); - const graph = await buildGraph( - new StaticSystemGraphBuilder( - { listAgents: async () => result }, - invocationProvider(async () => EMPTY_INVOCATIONS), - ), - scope, - ); - - expect(graph.warnings).toEqual([ - { - code: "duplicate-agent-key", - agentKey: "shared", - message: "Multiple agents use shared; kept each with a local identity.", - }, - ]); - }); - - it("deduplicates redundant provider duplicate warnings", async () => { - const duplicateWarning = { - code: "duplicate-agent-key" as const, - agentKey: "shared", - message: "provider-owned private wording", - }; - const result = inventoryResult( - scope, - [ - { - agentKey: "local:only", - label: "Only", - sourceRoot: path.join(FIXTURE, "only"), - provisional: true, - identityIssue: "duplicate-agent-key", - candidateAgentKey: "shared", - resolutionAliases: ["shared"], - }, - ], - { - degraded: true, - warnings: [duplicateWarning, duplicateWarning], - }, - ); - const graph = await buildGraph( - new StaticSystemGraphBuilder( - { listAgents: async () => result }, - invocationProvider(async () => EMPTY_INVOCATIONS), - ), - scope, - ); - - expect(graph.warnings).toEqual([ - { - code: "duplicate-agent-key", - agentKey: "shared", - message: "Multiple agents use shared; kept each with a local identity.", - }, - ]); - expect(JSON.stringify(graph)).not.toContain("provider-owned"); - }); - - it("rejects a provider duplicate warning without matching public evidence", async () => { - const result = inventoryResult( - scope, - [{ agentKey: "reporting", label: "Reporting" }], - { - warnings: [ - { - code: "duplicate-agent-key", - agentKey: "unsupported", - message: "private", - }, - ], - }, - ); - - await expect( - buildGraph( - new StaticSystemGraphBuilder( - { listAgents: async () => result }, - invocationProvider(async () => EMPTY_INVOCATIONS), - ), - scope, - ), - ).rejects.toThrow("inventory warning was invalid"); - }); - - it("resolves an exact canonical key before a stale compatibility alias", async () => { - const inventory = inventoryResult( - scope, - [ - { - agentKey: "caller", - label: "Caller", - sourceRoot: path.join(FIXTURE, "caller"), - }, - { - agentKey: "payments", - label: "Payments", - sourceRoot: path.join(FIXTURE, "payments"), - }, - { - agentKey: "local:pending", - label: "Pending", - sourceRoot: path.join(FIXTURE, "pending"), - provisional: true, - identityIssue: "identity-unavailable", - resolutionAliases: ["payments"], - }, - ], - { degraded: true }, - ); - const graph = await buildGraph( - new StaticSystemGraphBuilder( - { listAgents: async () => inventory }, - invocationProvider(async (sourceRoot) => - sourceRoot.endsWith("caller") - ? { - invocations: [ - { target: "payments", mode: "async", evidence: EVIDENCE }, - ], - warnings: [], - } - : EMPTY_INVOCATIONS, - ), - ), - scope, - ); - - expect(graph.edges).toEqual([ - { - from: "agent:caller", - to: "agent:payments", - kind: "invokes", - basis: "static-invocation", - mode: "async", - }, - ]); - }); - - it("keeps a invocation ambiguous when only multiple aliases match", async () => { - const inventory = inventoryResult( - scope, - [ - { - agentKey: "caller", - label: "Caller", - sourceRoot: path.join(FIXTURE, "caller"), - }, - { - agentKey: "local:first", - label: "First", - sourceRoot: path.join(FIXTURE, "first"), - provisional: true, - resolutionAliases: ["legacy"], - }, - { - agentKey: "local:second", - label: "Second", - sourceRoot: path.join(FIXTURE, "second"), - provisional: true, - resolutionAliases: ["legacy"], - }, - ], - { degraded: true }, - ); - const graph = await buildGraph( - new StaticSystemGraphBuilder( - { listAgents: async () => inventory }, - invocationProvider(async (sourceRoot) => - sourceRoot.endsWith("caller") - ? { - invocations: [ - { target: "legacy", mode: "async", evidence: EVIDENCE }, - ], - warnings: [], - } - : EMPTY_INVOCATIONS, - ), - ), - scope, - ); - - expect(graph.edges).toEqual([]); - expect(graph.warnings).toContainEqual({ - code: "unresolved-target", - agentKey: "caller", - message: "Caller invokes ambiguous agent legacy.", - }); - }); - - it("keeps a provisional public key ambiguous with another agent's alias", async () => { - const inventory = inventoryResult( - scope, - [ - { - agentKey: "caller", - label: "Caller", - sourceRoot: path.join(FIXTURE, "caller"), - }, - { - agentKey: "legacy", - label: "Provisional", - sourceRoot: path.join(FIXTURE, "provisional"), - provisional: true, - identityIssue: "identity-unavailable", - }, - { - agentKey: "current", - label: "Current", - sourceRoot: path.join(FIXTURE, "current"), - resolutionAliases: ["legacy"], - }, - ], - { degraded: true }, - ); - const graph = await buildGraph( - new StaticSystemGraphBuilder( - { listAgents: async () => inventory }, - invocationProvider(async (sourceRoot) => - sourceRoot.endsWith("caller") - ? { - invocations: [ - { target: "legacy", mode: "async", evidence: EVIDENCE }, - ], - warnings: [], - } - : EMPTY_INVOCATIONS, - ), - ), - scope, - ); - - expect(graph.edges).toEqual([]); - expect(graph.warnings).toContainEqual({ - code: "unresolved-target", - agentKey: "caller", - message: "Caller invokes ambiguous agent legacy.", - }); - }); - - it("rejects an arbitrary provider that violates the public or private boundary", async () => { - const duplicate = inventoryResult(scope, [ - { agentKey: "alpha", label: "Alpha" }, - { agentKey: "beta", label: "Beta" }, - ]); - duplicate.inventory = { - ...duplicate.inventory, - agents: duplicate.inventory.agents.map((agent) => ({ - ...agent, - agentKey: "alpha", - })), - }; - const inventory: AgentInventoryProvider = { - listAgents: vi.fn(async () => duplicate), - }; - - await expect( - buildGraph( - new StaticSystemGraphBuilder( - inventory, - invocationProvider(async () => EMPTY_INVOCATIONS), - ), - scope, - ), - ).rejects.toThrow(); - - const outside = inventoryResult(scope, [ - { - agentKey: "alpha", - label: "Alpha", - sourceRoot: path.join(FIXTURE, "growth"), - }, - ]); - outside.context[0]!.sourceRoot = "/outside/private-agent"; - await expect( - buildGraph( - new StaticSystemGraphBuilder( - { listAgents: async () => outside }, - invocationProvider(async () => EMPTY_INVOCATIONS), - ), - scope, - ), - ).rejects.toThrow("inventory context was invalid"); - - const mismatchedLocation = inventoryResult(scope, [ - { - agentKey: "alpha", - label: "Alpha", - sourceRoot: path.join(FIXTURE, "alpha"), - }, - ]); - mismatchedLocation.context[0]!.sourceRoot = path.join(FIXTURE, "growth"); - mismatchedLocation.context[0]!.workflowPath = path.join(FIXTURE, "growth"); - await expect( - buildGraph( - new StaticSystemGraphBuilder( - { listAgents: async () => mismatchedLocation }, - invocationProvider(async () => EMPTY_INVOCATIONS), - ), - scope, - ), - ).rejects.toThrow("inventory context was invalid"); - }); - - it("degrades a scanner failure into a path-free warning", async () => { - const inventory: AgentInventoryProvider = { - listAgents: vi.fn(async () => - inventoryResult(scope, [ - { - agentKey: "research", - definitionId: 1, - definitionSlug: "research", - label: "Research", - resolutionAliases: ["research"], - }, - ]), - ), - }; - const built = await new StaticSystemGraphBuilder( - inventory, - invocationProvider(async () => { - throw new Error("boom at private source"); - }), - ).build(scope); - const graph = built.graph; - - expect(built.cacheable).toBe(false); - expect(graph.warnings).toEqual([ - { - code: "projection-failed", - agentKey: "research", - message: "Could not inspect Research.", - }, - ]); - expect(JSON.stringify(graph)).not.toContain("/private/"); - }); - - it("keeps path-shaped registry and extraction values out of the public graph", async () => { - const inventory = new HarnessRegistryInventoryProvider({ - listWorkflows: () => [ - { - ...workflow(FIXTURE, "reporting", FIXTURE), - definitionId: null, - }, - ], - inspectManifestName: vi.fn(async () => ({ - status: "found" as const, - name: FIXTURE, - })), - }); - - const graph = await buildGraph( - new StaticSystemGraphBuilder( - inventory, - invocationProvider(async () => EMPTY_INVOCATIONS), - ), - scope, - ); - - expect(graph.nodes).toEqual([ - { - id: "agent:local:reporting", - agentKey: "local:reporting", - label: "reporting", - }, - ]); - expect(graph.warnings).toEqual([]); - expect(JSON.stringify(graph)).not.toContain(FIXTURE); - }); - - it("keeps marker-resolved edges when source identity inspection fails", async () => { - const changed = vi.fn(); - const inventory = new HarnessRegistryInventoryProvider({ - listWorkflows: () => [ - workflow("Caller", "caller", "caller-marker"), - workflow("Target", "target", "target-marker"), - ], - inspectManifestName: vi.fn(async () => ({ - status: "failed" as const, - retryable: false, - })), - fingerprintSource: async (sourceRoot) => `fingerprint:${sourceRoot}`, - onIdentityChange: changed, - }); - const builder = new StaticSystemGraphBuilder( - inventory, - invocationProvider(async (sourceRoot) => - sourceRoot.endsWith("caller") - ? { - invocations: [ - { - target: "target-marker", - mode: "async", - evidence: EVIDENCE, - }, - ], - warnings: [], - } - : EMPTY_INVOCATIONS, - ), - ); - const initial = await builder.build(scope); - initial.afterCommit?.(); - await vi.waitFor(() => expect(changed).toHaveBeenCalledTimes(1)); - - const failed = await builder.build(scope); - - expect(failed.graph.nodes.map((node) => node.agentKey)).toEqual([ - "caller-marker", - "target-marker", - ]); - expect(failed.graph.edges).toEqual([ - { - from: "agent:caller-marker", - to: "agent:target-marker", - kind: "invokes", - basis: "static-invocation", - mode: "async", - }, - ]); - expect(failed.graph.warnings.map((warning) => warning.code)).toEqual([ - "inventory-extraction-failed", - "inventory-extraction-failed", - ]); - expect(JSON.stringify(failed.graph)).not.toContain(FIXTURE); - }); - - it("sanitizes private labels and warning messages at an arbitrary provider boundary", async () => { - const leakedPath = "/private/provider-secret"; - const result = inventoryResult( - scope, - [ - { - agentKey: "local:reporting", - label: `${leakedPath}\u0085`, - sourceRoot: path.join(FIXTURE, "reporting"), - provisional: true, - }, - ], - { - degraded: true, - warnings: [ - { - code: "inventory-extraction-failed", - agentKey: "local:reporting", - message: `inspection failed at ${leakedPath}`, - }, - ], - }, - ); - - const graph = await buildGraph( - new StaticSystemGraphBuilder( - { listAgents: async () => result }, - invocationProvider(async () => EMPTY_INVOCATIONS), - ), - scope, - ); - - expect(graph.nodes).toEqual([ - { - id: "agent:local:reporting", - agentKey: "local:reporting", - label: "reporting", - }, - ]); - expect(graph.warnings).toEqual([ - { - code: "inventory-extraction-failed", - agentKey: "local:reporting", - message: - "Could not resolve reporting's source identity; using its provisional identity.", - }, - ]); - expect(JSON.stringify(graph)).not.toContain(leakedPath); - expect(JSON.stringify(graph)).not.toContain("\u0085"); - }); - - it("preserves a scoped package display label without admitting path-shaped labels", async () => { - const result = inventoryResult(scope, [ - { - agentKey: "reporting", - label: "@acme/proj-a", - sourceRoot: path.join(FIXTURE, "reporting"), - }, - ]); - - const graph = await buildGraph( - new StaticSystemGraphBuilder( - { listAgents: async () => result }, - invocationProvider(async () => EMPTY_INVOCATIONS), - ), - scope, - ); - - expect(graph.nodes).toEqual([ - { - id: "agent:reporting", - agentKey: "reporting", - label: "@acme/proj-a", - }, - ]); - }); - - it("rejects a provider warning whose identity is not inventory-owned", async () => { - const result = inventoryResult( - scope, - [ - { - agentKey: "local:reporting", - label: "Reporting", - sourceRoot: path.join(FIXTURE, "reporting"), - provisional: true, - }, - ], - { - degraded: true, - warnings: [ - { - code: "inventory-extraction-failed", - agentKey: "/private/provider-secret", - message: "private", - }, - ], - }, - ); - - await expect( - buildGraph( - new StaticSystemGraphBuilder( - { listAgents: async () => result }, - invocationProvider(async () => EMPTY_INVOCATIONS), - ), - scope, - ), - ).rejects.toThrow("inventory warning was invalid"); - }); - - it("rejects extraction warnings unsupported by parsed identity evidence", async () => { - const unsupported = [ - { - agentKey: "canonical", - result: inventoryResult(scope, [ - { agentKey: "canonical", label: "Canonical" }, - ]), - }, - { - agentKey: "local:pending", - result: inventoryResult( - scope, - [ - { - agentKey: "local:pending", - label: "Pending", - provisional: true, - identityIssue: "identity-pending", - }, - ], - { degraded: true }, - ), - }, - { - agentKey: "local:duplicate", - result: inventoryResult( - scope, - [ - { - agentKey: "local:duplicate", - label: "Duplicate", - provisional: true, - identityIssue: "duplicate-agent-key", - candidateAgentKey: "shared", - }, - ], - { degraded: true }, - ), - }, - ]; - - for (const { agentKey, result } of unsupported) { - result.warnings = [ - { - code: "inventory-extraction-failed", - agentKey, - message: "private", - }, - ]; - await expect( - buildGraph( - new StaticSystemGraphBuilder( - { listAgents: async () => result }, - invocationProvider(async () => EMPTY_INVOCATIONS), - ), - scope, - ), - ).rejects.toThrow("inventory warning was invalid"); - } - }); - - it.each([ - ["path alias", ["private/agent"]], - ["control alias", ["agent\u0085name"]], - ["reserved local alias", ["local:agent"]], - ])("rejects an arbitrary provider %s", async (_case, resolutionAliases) => { - const result = inventoryResult(scope, [ - { - agentKey: "reporting", - label: "Reporting", - sourceRoot: path.join(FIXTURE, "reporting"), - resolutionAliases, - }, - ]); - - await expect( - buildGraph( - new StaticSystemGraphBuilder( - { listAgents: async () => result }, - invocationProvider(async () => EMPTY_INVOCATIONS), - ), - scope, - ), - ).rejects.toThrow("inventory context was invalid"); - }); - - it("normalizes arbitrary provider aliases before invocation resolution", async () => { - const result = inventoryResult(scope, [ - { - agentKey: "reporting", - label: "Reporting", - sourceRoot: path.join(FIXTURE, "reporting"), - resolutionAliases: ["zeta", "alpha", "zeta"], - }, - ]); - const listInvocations = vi.fn( - async () => EMPTY_INVOCATIONS, - ); - - await buildGraph( - new StaticSystemGraphBuilder( - { listAgents: async () => result }, - { listInvocations }, - ), - scope, - ); - - expect(listInvocations.mock.calls[0]?.[0].resolutionAliases).toEqual([ - "alpha", - "zeta", - ]); - }); - - it("projects disconnected inventory nodes and merges inventory warnings", async () => { - const inventory: AgentInventoryProvider = { - listAgents: vi.fn(async () => - inventoryResult( - scope, - [ - { - agentKey: "research", - definitionId: 1, - definitionSlug: "research", - label: "Research", - resolutionAliases: ["research"], - }, - { - agentKey: "local:reporting", - label: "Reporting", - provisional: true, - }, - ], - { - degraded: true, - warnings: [ - { - code: "inventory-extraction-failed", - agentKey: "local:reporting", - message: - "Could not inspect Reporting; using its local identity.", - }, - ], - }, - ), - ), - }; - - const graph = await buildGraph( - new StaticSystemGraphBuilder( - inventory, - invocationProvider(async () => EMPTY_INVOCATIONS), - ), - scope, - ); - - expect(graph.nodes.map((node) => node.agentKey)).toEqual([ - "local:reporting", - "research", - ]); - expect(graph.edges).toEqual([]); - expect(graph.warnings).toEqual([ - { - code: "inventory-extraction-failed", - agentKey: "local:reporting", - message: - "Could not resolve Reporting's source identity; using its provisional identity.", - }, - ]); - expect(JSON.stringify(graph)).not.toContain("/private/"); - }); - - it("keeps degraded cache policy outside the public graph contract", async () => { - const inventory: AgentInventoryProvider = { - listAgents: vi.fn(async () => - inventoryResult( - scope, - [ - { - agentKey: "local:pending", - label: "Pending", - provisional: true, - identityIssue: "identity-pending", - }, - ], - { degraded: true }, - ), - ), - }; - - const built = await new StaticSystemGraphBuilder( - inventory, - invocationProvider(async () => EMPTY_INVOCATIONS), - ).build(scope); - - expect(built.cacheable).toBe(false); - expect(built.graph).toEqual({ - kind: "system", - scope: { kind: "working-tree", workspaceKey: scope.workspaceKey }, - nodes: [ - { - id: "agent:local:pending", - agentKey: "local:pending", - label: "Pending", - }, - ], - edges: [], - warnings: [], - }); - expect(built.graph).not.toHaveProperty("cacheable"); - }); - - it("caches a settled provisional identity while preserving its warning", async () => { - const result = inventoryResult( - scope, - [ - { - agentKey: "local:dashboard", - label: "Dashboard", - provisional: true, - identityIssue: "identity-unavailable", - }, - ], - { - degraded: true, - identitySettled: true, - warnings: [ - { - code: "inventory-extraction-failed", - agentKey: "local:dashboard", - message: "private provider wording", - }, - ], - }, - ); - - const built = await new StaticSystemGraphBuilder( - { listAgents: async () => result }, - invocationProvider(async () => EMPTY_INVOCATIONS), - ).build(scope); - - expect(built.cacheable).toBe(true); - expect(built.graph.warnings).toEqual([ - { - code: "inventory-extraction-failed", - agentKey: "local:dashboard", - message: - "Could not resolve Dashboard's source identity; using its provisional identity.", - }, - ]); - }); - - it("does not cache a settled identity when workspace discovery was incomplete", async () => { - const result = inventoryResult( - scope, - [ - { - agentKey: "dashboard", - label: "Dashboard", - }, - ], - { - degraded: true, - identitySettled: true, - discoveryComplete: false, - }, - ); - - const built = await new StaticSystemGraphBuilder( - { listAgents: async () => result }, - invocationProvider(async () => EMPTY_INVOCATIONS), - ).build(scope); - - expect(built.cacheable).toBe(false); - }); - - it("uses normalized identity state even if a provider mutates inventory status", async () => { - let release!: () => void; - const invocationsPending = new Promise((resolve) => { - release = resolve; - }); - const result = inventoryResult( - scope, - [ - { - agentKey: "local:pending", - label: "Pending", - sourceRoot: path.join(FIXTURE, "pending"), - provisional: true, - identityIssue: "identity-pending", - }, - ], - { degraded: true }, - ); - const listInvocations = vi.fn(async () => { - await invocationsPending; - return EMPTY_INVOCATIONS; - }); - const building = new StaticSystemGraphBuilder( - { listAgents: async () => result }, - { listInvocations }, - ).build(scope); - await vi.waitFor(() => expect(listInvocations).toHaveBeenCalledTimes(1)); - - (result.inventory as { status: "complete" | "degraded" }).status = - "complete"; - release(); - const built = await building; - - expect(built.cacheable).toBe(false); - }); - - it("retains caller caches across active workspaces and prunes retired ones", async () => { - const secondScope: WorkspaceScope = { - workspaceKey: "workspace-second", - root: "/private/second", - }; - const retainSources = vi.fn<(sources: ReadonlySet) => void>(); - const inventory: AgentInventoryProvider = { - listAgents: vi.fn(async (activeScope) => { - const second = activeScope.workspaceKey === secondScope.workspaceKey; - const agentKey = second ? "second" : "first"; - return inventoryResult(activeScope, [ - { - agentKey, - definitionSlug: agentKey, - label: agentKey, - resolutionAliases: [agentKey], - sourceRoot: path.join(activeScope.root, agentKey), - }, - ]); - }), - retainSources, - }; - const retainCallers = vi.fn(); - const invocations: AgentInvocationProvider = { - listInvocations: vi.fn(async () => EMPTY_INVOCATIONS), - retainCallers, - }; - const builder = new StaticSystemGraphBuilder(inventory, invocations); - - await builder.build(scope); - await builder.build(secondScope); - expect( - retainCallers.mock.calls - .at(-1)?.[0] - .map((caller: { agentKey: string }) => caller.agentKey), - ).toEqual(["first", "second"]); - - builder.retainWorkspaces(new Set([secondScope.workspaceKey])); - expect( - retainCallers.mock.calls - .at(-1)?.[0] - .map((caller: { agentKey: string }) => caller.agentKey), - ).toEqual(["second"]); - expect([...(retainSources.mock.calls.at(-1)?.[0] ?? [])]).toEqual([ - "/private/second/second", - ]); - }); -}); diff --git a/packages/harness/src/core/system-graph.ts b/packages/harness/src/core/system-graph.ts deleted file mode 100644 index 74c0aa5f8..000000000 --- a/packages/harness/src/core/system-graph.ts +++ /dev/null @@ -1,524 +0,0 @@ -export { LocalWorkspaceScopeCatalog } from "./workspace-scope-catalog.js"; -export type { WorkspaceScopeResolver, WorkspaceScopeCatalog } from "./workspace-scope-catalog.js"; -import { packageInventorySchema } from "@sapiom/agent"; - -import type { - GraphWarning, - StaticInvocationGraphEdge, - SystemGraph, - SystemGraphNavigationTarget, - WorkspaceKey, -} from "../shared/system-graph.js"; -import { - canonicalGraphPath, - inventorySourceRoot, - isWithinGraphPath, - type AgentInventoryItem, - type AgentInventoryProvider, - type AgentInventoryWarning, - type WorkspaceScope, -} from "./system-graph-inventory.js"; -import { - CachedAgentInvocationProvider, - SourceAgentInvocationProvider, - type AgentInvocationProvider, - type AgentInvocationProviderResult, -} from "./system-graph-relationships.js"; - -export { HarnessRegistryInventoryProvider } from "./system-graph-inventory.js"; -export type { - AgentInventoryItem, - AgentInventoryProvider, - AgentInventoryResult, - AgentInventoryWarning, - WorkspaceScope, -} from "./system-graph-inventory.js"; -export { - CachedAgentInvocationProvider, - SourceAgentInvocationProvider, -} from "./system-graph-relationships.js"; -export type { - AgentInvocationCandidate, - AgentInvocationProvider, - AgentInvocationProviderResult, - AgentInvocationWarning, -} from "./system-graph-relationships.js"; - -export interface SystemGraphBuilder { - build(scope: WorkspaceScope): Promise; - /** Optional lifecycle hook for builders with workspace-scoped caches. */ - retainWorkspaces?(workspaceKeys: ReadonlySet): void; -} - -export interface SystemGraphBuildResult { - /** Internal cache policy; only graph crosses the HTTP boundary. */ - cacheable: boolean; - graph: SystemGraph; - /** Private resolver data committed atomically with the graph revision. */ - navigation?: SystemGraphNavigationTarget[]; - /** Starts non-blocking enrichment only after this result is visible. */ - afterCommit?: () => void; -} - -function warningOrder(left: GraphWarning, right: GraphWarning): number { - return ( - left.code.localeCompare(right.code) || - (left.agentKey ?? "").localeCompare(right.agentKey ?? "") || - left.message.localeCompare(right.message) - ); -} - -function hasControlCharacter(value: string): boolean { - return [...value].some((character) => { - const code = character.codePointAt(0)!; - return code <= 0x1f || (code >= 0x7f && code <= 0x9f); - }); -} - -function fallbackLabel(agentKey: string): string { - if (!agentKey.startsWith("local:")) return agentKey; - return agentKey.slice("local:".length).split("/").at(-1) ?? "Agent"; -} - -function isScopedPackageLabel(value: string): boolean { - return /^@[a-z0-9][a-z0-9._~-]*\/[a-z0-9][a-z0-9._~-]*$/.test(value); -} - -function safeContextLabel(label: unknown, agentKey: string): string { - if (typeof label !== "string") return fallbackLabel(agentKey); - const trimmed = label.trim(); - return trimmed === "" || - hasControlCharacter(trimmed) || - trimmed.includes("\\") || - (trimmed.includes("/") && !isScopedPackageLabel(trimmed)) - ? fallbackLabel(agentKey) - : trimmed; -} - -function normalizeResolutionAliases(value: unknown): string[] { - if (!Array.isArray(value)) { - throw new Error("System graph inventory context was invalid"); - } - const aliases = value.map((alias) => { - if ( - typeof alias !== "string" || - alias === "" || - alias !== alias.trim() || - alias === "." || - alias === ".." || - alias.startsWith("local:") || - hasControlCharacter(alias) || - alias.includes("/") || - alias.includes("\\") - ) { - throw new Error("System graph inventory context was invalid"); - } - return alias; - }); - return [...new Set(aliases)].sort((left, right) => - left === right ? 0 : left < right ? -1 : 1, - ); -} - -function sanitizeInventoryWarnings( - warnings: readonly AgentInventoryWarning[], - publicAgents: ReturnType["agents"], - agents: readonly AgentInventoryItem[], -): GraphWarning[] { - const agentsByKey = new Map(agents.map((agent) => [agent.agentKey, agent])); - const publicAgentsByKey = new Map( - publicAgents.map((agent) => [agent.agentKey, agent]), - ); - const duplicateCandidates = new Set(); - for (const agent of publicAgents) { - if ( - agent.identityStatus === "provisional" && - agent.identityIssue === "duplicate-agent-key" - ) { - duplicateCandidates.add(agent.candidateAgentKey); - } - } - - const sanitized: GraphWarning[] = [...duplicateCandidates].map( - (candidateAgentKey) => ({ - code: "duplicate-agent-key", - agentKey: candidateAgentKey, - message: `Multiple agents use ${candidateAgentKey}; kept each with a local identity.`, - }), - ); - const seenExtractionFailures = new Set(); - for (const warning of warnings) { - if ( - !warning || - typeof warning !== "object" || - typeof warning.agentKey !== "string" || - typeof warning.message !== "string" - ) { - throw new Error("System graph inventory warning was invalid"); - } - if (warning.code === "duplicate-agent-key") { - if (!duplicateCandidates.has(warning.agentKey)) { - throw new Error("System graph inventory warning was invalid"); - } - continue; - } - if (warning.code === "inventory-extraction-failed") { - const agent = agentsByKey.get(warning.agentKey); - const publicAgent = publicAgentsByKey.get(warning.agentKey); - if ( - !agent || - !publicAgent || - publicAgent.identityStatus !== "provisional" || - (publicAgent.identityIssue !== "identity-unavailable" && - publicAgent.identityIssue !== "identity-invalid") - ) { - throw new Error("System graph inventory warning was invalid"); - } - if (seenExtractionFailures.has(warning.agentKey)) continue; - seenExtractionFailures.add(warning.agentKey); - sanitized.push({ - code: warning.code, - agentKey: warning.agentKey, - message: `Could not resolve ${agent.label}'s source identity; using its provisional identity.`, - }); - continue; - } - throw new Error("System graph inventory warning was invalid"); - } - return sanitized.sort(warningOrder); -} - -interface ConsumedInventory { - agents: AgentInventoryItem[]; - warnings: GraphWarning[]; - /** Every identity has finished resolving, however it resolved. */ - identitySettled: boolean; - /** The accepted workspace walk considered every eligible discovery path. */ - discoveryComplete: boolean; - startEnrichment?: () => void; -} - -/** - * Re-parse the public contract and join private context at the last boundary - * before graph projection. A future adapter cannot bypass inventory safety or - * smuggle an outside navigation target into the resolver. - */ -function consumeInventory( - scope: WorkspaceScope, - result: Awaited>, -): ConsumedInventory { - const inventory = packageInventorySchema.parse(result.inventory); - if ( - inventory.version.kind !== "working-tree" || - inventory.version.workspaceKey !== scope.workspaceKey - ) { - throw new Error("System graph received an inventory for another scope"); - } - const canonicalScope = canonicalGraphPath(scope.root); - const context = new Map( - result.context.map((item) => [`${item.path}\0${item.entrypoint}`, item]), - ); - if ( - context.size !== result.context.length || - result.context.length !== inventory.agents.length - ) { - throw new Error( - "System graph inventory context did not match public locations", - ); - } - const agents = inventory.agents.map((agent) => { - const key = `${agent.path}\0${agent.entrypoint}`; - const item = context.get(key); - const sourceRoot = item ? canonicalGraphPath(item.sourceRoot) : ""; - const workflowPath = item ? canonicalGraphPath(item.workflowPath) : ""; - const expectedSourceRoot = inventorySourceRoot(scope.root, agent.path); - if ( - !item || - item.agentKey !== agent.agentKey || - !isWithinGraphPath(canonicalScope, sourceRoot) || - !isWithinGraphPath(expectedSourceRoot, sourceRoot) || - !isWithinGraphPath(sourceRoot, expectedSourceRoot) || - !isWithinGraphPath(sourceRoot, workflowPath) || - !isWithinGraphPath(workflowPath, sourceRoot) - ) { - throw new Error("System graph inventory context was invalid"); - } - return { - ...item, - identityStatus: agent.identityStatus, - label: safeContextLabel(item.label, item.agentKey), - resolutionAliases: normalizeResolutionAliases(item.resolutionAliases), - }; - }); - return { - agents, - warnings: sanitizeInventoryWarnings( - result.warnings, - inventory.agents, - agents, - ), - identitySettled: - result.identitySettled && - !inventory.agents.some( - (agent) => - agent.identityStatus === "provisional" && - agent.identityIssue === "identity-pending", - ), - discoveryComplete: result.discoveryComplete === true, - ...(typeof result.startEnrichment === "function" - ? { startEnrichment: result.startEnrichment } - : {}), - }; -} - -export class StaticSystemGraphBuilder implements SystemGraphBuilder { - private readonly callersByWorkspace = new Map< - WorkspaceKey, - readonly AgentInventoryItem[] - >(); - - constructor( - private readonly inventory: AgentInventoryProvider, - private readonly invocations: AgentInvocationProvider = new CachedAgentInvocationProvider( - new SourceAgentInvocationProvider(), - ), - ) {} - - async build(scope: WorkspaceScope): Promise { - const inventory = await this.inventory.listAgents(scope); - const consumed = consumeInventory(scope, inventory); - const agents = consumed.agents; - this.callersByWorkspace.set(scope.workspaceKey, agents); - this.retainInvocationCallers(); - const nodes = agents.map((agent) => ({ - id: `agent:${agent.agentKey}`, - agentKey: agent.agentKey, - label: agent.label, - })); - const canonicalTargets = new Map(); - const candidateTargets = new Map(); - const registerCandidate = ( - key: string, - agent: AgentInventoryItem, - ): void => { - const candidates = candidateTargets.get(key) ?? []; - if ( - !candidates.some((candidate) => candidate.agentKey === agent.agentKey) - ) { - candidates.push(agent); - candidateTargets.set(key, candidates); - } - }; - for (const agent of agents) { - if (agent.identityStatus === "canonical") { - canonicalTargets.set(agent.agentKey, agent); - } else { - registerCandidate(agent.agentKey, agent); - } - for (const alias of agent.resolutionAliases) { - registerCandidate(alias, agent); - } - } - - const edges: StaticInvocationGraphEdge[] = []; - const warnings: GraphWarning[] = [...consumed.warnings]; - const seenEdges = new Set(); - let invocationsComplete = true; - - const supportsBackgroundInvocations = - typeof this.invocations.peekInvocations === "function" && - typeof this.invocations.startInvocations === "function"; - // Production is deliberately two-phase: project cache-only inventory now, - // then perform bounded invocation I/O after nodes/navigation are visible. - // Legacy/test providers without the cache surface retain the old awaited - // adapter behavior. - const scans = supportsBackgroundInvocations - ? agents.map((caller) => { - const snapshot = this.invocations.peekInvocations!(caller); - return { - caller, - result: - snapshot?.result ?? - ({ - invocations: [], - warnings: [], - } satisfies AgentInvocationProviderResult), - failed: snapshot?.status === "failed", - pending: snapshot === undefined, - }; - }) - : await Promise.all( - agents.map(async (caller) => { - try { - return { - caller, - result: await this.invocations.listInvocations(caller), - failed: false, - pending: false, - }; - } catch { - return { - caller, - result: { - invocations: [], - warnings: [], - } satisfies AgentInvocationProviderResult, - failed: true, - pending: false, - }; - } - }), - ); - - for (const { caller, result, failed, pending } of scans) { - if (pending) { - invocationsComplete = false; - continue; - } - if (failed) { - invocationsComplete = false; - warnings.push({ - code: "projection-failed", - agentKey: caller.agentKey, - message: `Could not inspect ${caller.label}.`, - }); - continue; - } - if (result.complete === false) { - invocationsComplete = false; - warnings.push({ - code: "projection-failed", - agentKey: caller.agentKey, - message: `Could not fully inspect ${caller.label}.`, - }); - } - - for (const warning of result.warnings) { - if (warning.code === "dynamic-target") { - warnings.push({ - code: "dynamic-target", - agentKey: caller.agentKey, - message: `${caller.label} has a dynamic agent target that V0 cannot resolve.`, - }); - } - } - - for (const invocation of result.invocations) { - const exact = canonicalTargets.get(invocation.target); - const candidates = exact - ? [exact] - : (candidateTargets.get(invocation.target) ?? []); - if (candidates.length !== 1) { - const target = /^[A-Za-z0-9@_.:-]+$/.test(invocation.target) - ? invocation.target - : null; - warnings.push({ - code: "unresolved-target", - agentKey: caller.agentKey, - message: - candidates.length === 0 - ? target - ? `${caller.label} invokes unknown agent ${target}.` - : `${caller.label} invokes an invalid agent target.` - : `${caller.label} invokes ambiguous agent ${target ?? "target"}.`, - }); - continue; - } - const target = candidates[0]!; - if (target.agentKey === caller.agentKey) continue; - const from = `agent:${caller.agentKey}`; - const to = `agent:${target.agentKey}`; - const edgeKey = `${from}\0${to}\0${invocation.mode}`; - if (invocation.evidence.length > 1 || seenEdges.has(edgeKey)) { - warnings.push({ - code: "duplicate-edge", - agentKey: caller.agentKey, - message: `${caller.label} invokes ${target.label} more than once.`, - }); - } - if (seenEdges.has(edgeKey)) continue; - seenEdges.add(edgeKey); - edges.push({ - from, - to, - kind: "invokes", - basis: "static-invocation", - mode: invocation.mode, - }); - } - } - - const modeOrder = { blocking: 0, async: 1 } as const; - edges.sort( - (left, right) => - left.from.localeCompare(right.from) || - left.to.localeCompare(right.to) || - modeOrder[left.mode] - modeOrder[right.mode], - ); - const uniqueWarnings = [ - ...new Map( - warnings.map((warning) => [ - `${warning.code}\0${warning.agentKey ?? ""}\0${warning.message}`, - warning, - ]), - ).values(), - ].sort(warningOrder); - - const afterCommit = - consumed.startEnrichment || supportsBackgroundInvocations - ? () => { - consumed.startEnrichment?.(); - if (supportsBackgroundInvocations) { - this.invocations.startInvocations!(agents); - } - } - : undefined; - return { - cacheable: - consumed.identitySettled && - consumed.discoveryComplete && - invocationsComplete, - graph: { - kind: "system", - scope: { kind: "working-tree", workspaceKey: scope.workspaceKey }, - nodes, - edges, - warnings: uniqueWarnings, - }, - navigation: agents.map(({ agentKey, workflowPath }) => ({ - agentKey, - workflowPath, - })), - ...(afterCommit ? { afterCommit } : {}), - }; - } - - retainWorkspaces(workspaceKeys: ReadonlySet): void { - for (const workspaceKey of this.callersByWorkspace.keys()) { - if (!workspaceKeys.has(workspaceKey)) { - this.callersByWorkspace.delete(workspaceKey); - } - } - try { - this.inventory.retainSources?.( - new Set( - [...this.callersByWorkspace.values()] - .flat() - .map((caller) => caller.sourceRoot), - ), - ); - } catch { - // Private cache pruning cannot make graph projection fail. - } - this.retainInvocationCallers(); - } - - private retainInvocationCallers(): void { - const callers = [...this.callersByWorkspace.values()].flat(); - try { - this.invocations.retainCallers?.(callers); - } catch { - // Cache pruning is an optimization and cannot make projection fail. - } - } -} diff --git a/packages/harness/src/server/events-ws.test.ts b/packages/harness/src/server/events-ws.test.ts index 517b66f07..0e1bbc55b 100644 --- a/packages/harness/src/server/events-ws.test.ts +++ b/packages/harness/src/server/events-ws.test.ts @@ -42,33 +42,6 @@ describe("createEventsWebSocketHandler", () => { expect(sent).toEqual([JSON.stringify({ type: "canvas.reload", harnessSessionId: "sess-1" })]); }); - it("forwards path-free workspace graph revisions", () => { - const bus = new EventBus(); - const handler = createEventsWebSocketHandler(bus, BOOT_TOKEN); - const { ws, sent } = createFakeWs(); - - handler( - ws, - {} as IncomingMessage, - new URLSearchParams({ token: BOOT_TOKEN }), - ); - bus.publish({ - type: "system-graph.changed", - workspaceKey: "workspace-test", - revision: 4, - state: "stale", - }); - - expect(sent).toEqual([ - JSON.stringify({ - type: "system-graph.changed", - workspaceKey: "workspace-test", - revision: 4, - state: "stale", - }), - ]); - }); - it("unsubscribes from the bus once the socket closes", () => { const bus = new EventBus(); const handler = createEventsWebSocketHandler(bus, BOOT_TOKEN); diff --git a/packages/harness/src/server/system-graph.test.ts b/packages/harness/src/server/system-graph.test.ts deleted file mode 100644 index 7e1014db5..000000000 --- a/packages/harness/src/server/system-graph.test.ts +++ /dev/null @@ -1,311 +0,0 @@ -import type { AddressInfo } from "node:net"; -import express from "express"; -import { afterEach, describe, expect, it, vi } from "vitest"; - -import { SystemGraphStore } from "../core/system-graph-store.js"; -import type { - SystemGraphBuilder, - WorkspaceScopeResolver, -} from "../core/system-graph.js"; -import { - SYSTEM_GRAPH_CACHE_HEADER, - type SystemGraph, - type SystemGraphSnapshot, -} from "../shared/system-graph.js"; -import { createBootTokenMiddleware } from "./auth.js"; -import { createSystemGraphRouter } from "./system-graph.js"; - -const workspaceKey = "workspace-known"; -const graph: SystemGraph = { - kind: "system", - scope: { kind: "working-tree", workspaceKey }, - nodes: [ - { id: "agent:research", agentKey: "research", label: "Research" }, - { id: "agent:growth", agentKey: "growth", label: "Growth" }, - ], - edges: [ - { - from: "agent:research", - to: "agent:growth", - kind: "invokes", - basis: "static-invocation", - mode: "async", - }, - ], - warnings: [], -}; - -describe("createSystemGraphRouter", () => { - let server: ReturnType | undefined; - - afterEach(async () => { - if (server) - await new Promise((resolve) => server!.close(() => resolve())); - server = undefined; - }); - - function start(cacheable = true, onScopeAccess = vi.fn()) { - const scopeResolver: WorkspaceScopeResolver = { - resolve: vi.fn(async (key: string) => - key === workspaceKey - ? { workspaceKey: key, root: "/private/workspace" } - : null, - ), - }; - const builder: SystemGraphBuilder = { - build: vi.fn(async () => ({ - cacheable, - graph, - navigation: [ - { agentKey: "research", workflowPath: "/private/workspace/research" }, - { agentKey: "growth", workflowPath: "/private/workspace/growth" }, - ], - })), - }; - const store = new SystemGraphStore(builder); - const app = express(); - app.use("/api", createBootTokenMiddleware("test-token")); - app.use( - "/api", - createSystemGraphRouter({ - scopeResolver, - store, - onScopeAccess, - }), - ); - server = app.listen(0); - const address = server.address() as AddressInfo; - return { - baseUrl: `http://127.0.0.1:${address.port}`, - scopeResolver, - builder, - store, - onScopeAccess, - }; - } - - it("is boot-token protected and returns the cached public graph", async () => { - const { baseUrl, builder, onScopeAccess } = start(); - const route = `${baseUrl}/api/workspaces/${workspaceKey}/system-graph`; - - expect((await fetch(route)).status).toBe(401); - const first = await fetch(route, { - headers: { "X-Harness-Token": "test-token" }, - }); - const second = await fetch(route, { - headers: { "X-Harness-Token": "test-token" }, - }); - - expect(first.status).toBe(200); - expect(first.headers.get(SYSTEM_GRAPH_CACHE_HEADER)).toBe("complete"); - expect((await first.json()) as SystemGraphSnapshot).toEqual({ - workspaceKey, - revision: 1, - state: "ready", - graph, - }); - expect(second.status).toBe(200); - expect(builder.build).toHaveBeenCalledTimes(1); - expect(onScopeAccess).toHaveBeenCalledTimes(2); - }); - - it("reports degradation and bounds re-enrichment to one later request", async () => { - const { baseUrl, builder } = start(false); - const route = `${baseUrl}/api/workspaces/${workspaceKey}/system-graph`; - const request = () => - fetch(route, { headers: { "X-Harness-Token": "test-token" } }); - - const first = await request(); - const second = await request(); - const third = await request(); - - expect(first.headers.get(SYSTEM_GRAPH_CACHE_HEADER)).toBe("degraded"); - expect(second.headers.get(SYSTEM_GRAPH_CACHE_HEADER)).toBe("degraded"); - expect(third.headers.get(SYSTEM_GRAPH_CACHE_HEADER)).toBe("degraded"); - expect((await third.json()) as SystemGraphSnapshot).toMatchObject({ - workspaceKey, - state: "degraded", - graph, - }); - expect(builder.build).toHaveBeenCalledTimes(2); - }); - - it("rebuilds the projection through the protected explicit refresh route", async () => { - const { baseUrl, builder } = start(); - const route = `${baseUrl}/api/workspaces/${workspaceKey}/system-graph`; - const headers = { "X-Harness-Token": "test-token" }; - await fetch(route, { headers }); - - expect((await fetch(`${route}/refresh`, { method: "POST" })).status).toBe( - 401, - ); - const refreshed = await fetch(`${route}/refresh`, { - method: "POST", - headers, - }); - - expect(refreshed.status).toBe(200); - expect((await refreshed.json()) as SystemGraphSnapshot).toMatchObject({ - workspaceKey, - state: "ready", - graph, - }); - expect(builder.build).toHaveBeenCalledTimes(2); - }); - - it("serves a separately protected resolver stamped with the graph revision", async () => { - const { baseUrl, builder } = start(); - const graphRoute = `${baseUrl}/api/workspaces/${workspaceKey}/system-graph`; - const navigationRoute = `${graphRoute}/navigation`; - const headers = { "X-Harness-Token": "test-token" }; - const snapshot = (await ( - await fetch(graphRoute, { headers }) - ).json()) as SystemGraphSnapshot; - - expect((await fetch(navigationRoute)).status).toBe(401); - const response = await fetch(navigationRoute, { headers }); - - expect(response.status).toBe(200); - expect(response.headers.get("Cache-Control")).toBe("no-store"); - expect(await response.json()).toEqual({ - workspaceKey, - revision: snapshot.revision, - targets: [ - { - agentKey: "research", - workflowPath: "/private/workspace/research", - }, - { - agentKey: "growth", - workflowPath: "/private/workspace/growth", - }, - ], - }); - expect(builder.build).toHaveBeenCalledTimes(1); - }); - - it("serves degraded navigation without consuming a graph recovery retry", async () => { - const { baseUrl, builder } = start(false); - const graphRoute = `${baseUrl}/api/workspaces/${workspaceKey}/system-graph`; - const headers = { "X-Harness-Token": "test-token" }; - const snapshot = (await ( - await fetch(graphRoute, { headers }) - ).json()) as SystemGraphSnapshot; - - const navigation = await fetch(`${graphRoute}/navigation`, { headers }); - - expect(navigation.status).toBe(200); - expect(await navigation.json()).toMatchObject({ - workspaceKey, - revision: snapshot.revision, - }); - expect(builder.build).toHaveBeenCalledTimes(1); - }); - - it("does not send a projection retired while its HTTP build is in flight", async () => { - let resolveBuild!: ( - value: Awaited>, - ) => void; - const pending = new Promise< - Awaited> - >((resolve) => { - resolveBuild = resolve; - }); - const builder: SystemGraphBuilder = { - build: vi.fn(() => pending), - }; - const store = new SystemGraphStore(builder); - const scopeResolver: WorkspaceScopeResolver = { - resolve: vi.fn(async () => ({ - workspaceKey, - root: "/private/workspace", - })), - }; - const app = express(); - app.use("/api", createBootTokenMiddleware("test-token")); - app.use("/api", createSystemGraphRouter({ scopeResolver, store })); - server = app.listen(0); - const address = server.address() as AddressInfo; - const response = fetch( - `http://127.0.0.1:${address.port}/api/workspaces/${workspaceKey}/system-graph`, - { headers: { "X-Harness-Token": "test-token" } }, - ); - await vi.waitFor(() => expect(builder.build).toHaveBeenCalledTimes(1)); - - store.retire(workspaceKey); - resolveBuild({ - cacheable: true, - graph, - navigation: [], - }); - - expect((await response).status).toBe(404); - }); - - it("serves the current accepted revision when afterCommit immediately refreshes", async () => { - const builder: SystemGraphBuilder = { - build: vi - .fn() - .mockResolvedValueOnce({ - cacheable: false, - graph, - navigation: [], - afterCommit: () => - store.requestRefresh({ - workspaceKey, - root: "/private/workspace", - }), - }) - .mockResolvedValueOnce({ cacheable: true, graph, navigation: [] }), - }; - const store = new SystemGraphStore(builder); - const app = express(); - app.use("/api", createBootTokenMiddleware("test-token")); - app.use( - "/api", - createSystemGraphRouter({ - scopeResolver: { - resolve: async () => ({ - workspaceKey, - root: "/private/workspace", - }), - }, - store, - }), - ); - server = app.listen(0); - const address = server.address() as AddressInfo; - - const response = await fetch( - `http://127.0.0.1:${address.port}/api/workspaces/${workspaceKey}/system-graph`, - { headers: { "X-Harness-Token": "test-token" } }, - ); - const body = (await response.json()) as SystemGraphSnapshot; - - expect(response.status).toBe(200); - expect(body.revision).toBe(store.peek(workspaceKey)?.revision); - expect(body.revision).toBeGreaterThan(1); - }); - - it("rejects an unknown opaque workspace key without scanning", async () => { - const { baseUrl, builder } = start(); - const response = await fetch( - `${baseUrl}/api/workspaces/unknown/system-graph`, - { - headers: { "X-Harness-Token": "test-token" }, - }, - ); - - expect(response.status).toBe(404); - expect(await response.json()).toEqual({ error: "Workspace not found" }); - expect(builder.build).not.toHaveBeenCalled(); - expect( - ( - await fetch( - `${baseUrl}/api/workspaces/unknown/system-graph/navigation`, - { headers: { "X-Harness-Token": "test-token" } }, - ) - ).status, - ).toBe(404); - }); -}); diff --git a/packages/harness/src/server/system-graph.ts b/packages/harness/src/server/system-graph.ts deleted file mode 100644 index 40b36366b..000000000 --- a/packages/harness/src/server/system-graph.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { - Router, - type NextFunction, - type Request, - type Response, -} from "express"; - -import type { - WorkspaceScope, - WorkspaceScopeResolver, -} from "../core/system-graph.js"; -import type { SystemGraphStore } from "../core/system-graph-store.js"; -import { - SYSTEM_GRAPH_CACHE_HEADER, - type SystemGraphCacheStatus, - type SystemGraphNavigationResponse, - type SystemGraphSnapshot, -} from "../shared/system-graph.js"; - -export interface SystemGraphRouterOptions { - scopeResolver: WorkspaceScopeResolver; - store: SystemGraphStore; - onScopeAccess?: (scope: WorkspaceScope) => void | Promise; - /** Re-run registry prerequisites before an explicit user retry. */ - onScopeRefresh?: ( - scope: WorkspaceScope, - ) => SystemGraphSnapshot | Promise; -} - -/** Mounted beneath the boot-token-protected `/api` boundary. */ -export function createSystemGraphRouter( - options: SystemGraphRouterOptions, -): Router { - const router = Router(); - const route = "/workspaces/:workspaceKey/system-graph"; - - const serve = async ( - req: Request, - res: Response, - next: NextFunction, - refresh: boolean, - ): Promise => { - try { - const scope = await options.scopeResolver.resolve( - req.params.workspaceKey, - ); - if (!scope) { - res.status(404).json({ error: "Workspace not found" }); - return; - } - try { - void Promise.resolve(options.onScopeAccess?.(scope)).catch(() => { - // Watcher/discovery setup is best-effort and detached. Graph reads - // are strictly cache-backed and never await a baseline or scan. - }); - } catch { - // Synchronous setup failures are best-effort too. - } - await (refresh - ? (options.onScopeRefresh?.(scope) ?? options.store.refresh(scope)) - : options.store.get(scope)); - const snapshot = options.store.peek(scope.workspaceKey); - if (!snapshot) { - res.status(404).json({ error: "Workspace not found" }); - return; - } - const cacheStatus: SystemGraphCacheStatus = - snapshot.state === "ready" ? "complete" : "degraded"; - res.set(SYSTEM_GRAPH_CACHE_HEADER, cacheStatus).json(snapshot); - } catch (err) { - next(err); - } - }; - - router.get(route, (req, res, next) => { - void serve(req, res, next, false); - }); - router.post(`${route}/refresh`, (req, res, next) => { - void serve(req, res, next, true); - }); - - router.get(`${route}/navigation`, async (req, res, next) => { - try { - const scope = await options.scopeResolver.resolve( - req.params.workspaceKey, - ); - if (!scope) { - res.status(404).json({ error: "Workspace not found" }); - return; - } - try { - void Promise.resolve(options.onScopeAccess?.(scope)).catch(() => { - // Resolver reads remain cache-backed while freshness arms in the - // background. - }); - } catch { - // Synchronous setup failures are best-effort too. - } - await options.store.ensureInitialized(scope); - if (!options.store.peek(scope.workspaceKey)) { - res.status(404).json({ error: "Workspace not found" }); - return; - } - const navigation = options.store.peekNavigation(scope.workspaceKey); - if (!navigation) { - res.status(404).json({ error: "System graph not found" }); - return; - } - res.setHeader("Cache-Control", "no-store"); - res.json(navigation satisfies SystemGraphNavigationResponse); - } catch (err) { - next(err); - } - }); - - return router; -} diff --git a/packages/harness/src/shared/system-graph.ts b/packages/harness/src/shared/system-graph.ts deleted file mode 100644 index 152d890ff..000000000 --- a/packages/harness/src/shared/system-graph.ts +++ /dev/null @@ -1,78 +0,0 @@ -/** Retired graph contracts, pending engine deletion. */ -import type { WorkspaceKey } from "./workspace-scope.js"; -import type { AgentInvocationMode } from "../core/canvas-interconnections.js"; -export type { WorkspaceKey, WorkspaceScopeSummary } from "./workspace-scope.js"; -export { workspaceRelativeLocalKey } from "./workspace-scope.js"; -export type { AgentInvocationMode } from "../core/canvas-interconnections.js"; -export type AgentKey = string; - -/** Internal HTTP metadata; it is deliberately not part of SystemGraph JSON. */ -export const SYSTEM_GRAPH_CACHE_HEADER = "X-Sapiom-System-Graph-Cache"; -export type SystemGraphCacheStatus = "complete" | "degraded"; - -export interface SystemGraphNode { - id: string; - agentKey: AgentKey; - label: string; -} - -export interface StaticInvocationGraphEdge { - from: string; - to: string; - kind: "invokes"; - basis: "static-invocation"; - mode: AgentInvocationMode; -} - -export type SystemGraphEdge = StaticInvocationGraphEdge; - -export interface GraphWarning { - code: - | "unresolved-target" - | "dynamic-target" - | "duplicate-edge" - | "projection-failed" - | "duplicate-agent-key" - | "inventory-extraction-failed"; - message: string; - agentKey?: AgentKey; -} - -export interface SystemGraph { - kind: "system"; - scope: { - kind: "working-tree"; - workspaceKey: WorkspaceKey; - }; - nodes: SystemGraphNode[]; - edges: SystemGraphEdge[]; - warnings: GraphWarning[]; -} -export type SystemGraphLifecycleState = - | "building" - | "ready" - | "stale" - | "degraded"; - -/** Path-free lifecycle envelope for one workspace projection. */ -export interface SystemGraphSnapshot { - workspaceKey: WorkspaceKey; - /** Monotonic within one server process and workspace. */ - revision: number; - state: SystemGraphLifecycleState; - /** Null only before a usable projection exists. */ - graph: SystemGraph | null; -} - -/** Protected local resolver payload. Paths remain separate from SystemGraph. */ -export interface SystemGraphNavigationTarget { - agentKey: AgentKey; - workflowPath: string; -} - -export interface SystemGraphNavigationResponse { - workspaceKey: WorkspaceKey; - /** Must equal the displayed SystemGraphSnapshot revision before use. */ - revision: number; - targets: SystemGraphNavigationTarget[]; -} diff --git a/packages/harness/src/shared/types.ts b/packages/harness/src/shared/types.ts index 46a1c4a20..8ca43656a 100644 --- a/packages/harness/src/shared/types.ts +++ b/packages/harness/src/shared/types.ts @@ -6,11 +6,6 @@ * integration boundary. */ -import type { - SystemGraphLifecycleState, - WorkspaceKey, -} from "./system-graph.js"; - // --------------------------------------------------------------------------- // Constants & well-known paths // --------------------------------------------------------------------------- @@ -592,12 +587,6 @@ export type BusMessage = target: "prod" | "local"; } | { type: "workflows.changed" } - | { - type: "system-graph.changed"; - workspaceKey: WorkspaceKey; - revision: number; - state: SystemGraphLifecycleState; - } | { type: "agent-map.proposal.changed"; delta: import("./agent-map.js").AcceptedProposalDelta; diff --git a/packages/harness/web/src/lib/bus-message-type.test.ts b/packages/harness/web/src/lib/bus-message-type.test.ts new file mode 100644 index 000000000..9ae4a2309 --- /dev/null +++ b/packages/harness/web/src/lib/bus-message-type.test.ts @@ -0,0 +1,26 @@ +import { describe, expect, it } from "vitest"; +import { hasKnownBusMessageType } from "./bus-message-type"; + +describe("event transport discriminators", () => { + it("keeps session, Canvas and durable-map events supported", () => { + for (const type of [ + "session.status", + "canvas.reload", + "agent-map.proposal.changed", + ]) + expect(hasKnownBusMessageType({ type })).toBe(true); + }); + + it.each([ + null, + [], + "canvas.reload", + {}, + { type: "system-graph.changed" }, + { type: "future.event" }, + { type: "toString" }, + { type: 1 }, + ])("ignores retired, unknown or malformed event envelopes: %j", (value) => + expect(hasKnownBusMessageType(value)).toBe(false), + ); +}); diff --git a/packages/harness/web/src/lib/bus-message-type.ts b/packages/harness/web/src/lib/bus-message-type.ts new file mode 100644 index 000000000..5e0237334 --- /dev/null +++ b/packages/harness/web/src/lib/bus-message-type.ts @@ -0,0 +1,30 @@ +import type { BusMessage } from "@shared/types"; + +// Keep the transport's supported discriminators exhaustive as the protocol +// evolves. Removed or unknown events never reach mounted state subscribers. +const supportedTypes: Record = { + "session.status": true, + "session.record.changed": true, + "canvas.reload": true, + "port.detected": true, + "execution.started": true, + "workflows.changed": true, + "agent-map.proposal.changed": true, + "agent-map.initialization.changed": true, + "task.status": true, + "session.activity": true, + "auth.changed": true, +}; + +/** Checks the envelope's type only; consumers still own payload validation. */ +export function hasKnownBusMessageType( + value: unknown, +): value is { type: BusMessage["type"] } { + return ( + typeof value === "object" && + value !== null && + "type" in value && + typeof value.type === "string" && + Object.hasOwn(supportedTypes, value.type) + ); +} diff --git a/packages/harness/web/src/lib/events.test.ts b/packages/harness/web/src/lib/events.test.ts new file mode 100644 index 000000000..a7f05013f --- /dev/null +++ b/packages/harness/web/src/lib/events.test.ts @@ -0,0 +1,37 @@ +import { afterEach, expect, it, vi } from "vitest"; +import type { BusMessage } from "@shared/types"; + +vi.mock("./api", () => ({ + isMockMode: () => true, + isDemoSeedEnabled: () => false, + getBootToken: () => "test-token", + DEMO_SESSION_ID: "demo", +})); + +import { publishMockBusMessage, subscribeEvents } from "./events"; + +afterEach(() => { + vi.clearAllTimers(); + vi.useRealTimers(); +}); + +it("delivers supported events, ignores retired frames and removes its exact subscription", () => { + vi.useFakeTimers(); + const listener = vi.fn(); + const unsubscribe = subscribeEvents(listener); + const message: BusMessage = { + type: "canvas.reload", + harnessSessionId: "session-1", + }; + try { + for (const type of ["system-graph.changed", "future.event", "toString"]) + publishMockBusMessage({ type } as unknown as BusMessage); + expect(listener).not.toHaveBeenCalled(); + publishMockBusMessage(message); + expect(listener).toHaveBeenCalledExactlyOnceWith(message); + } finally { + unsubscribe(); + } + publishMockBusMessage(message); + expect(listener).toHaveBeenCalledTimes(1); +}); diff --git a/packages/harness/web/src/lib/events.ts b/packages/harness/web/src/lib/events.ts index d5ff0d591..69f7b1db1 100644 --- a/packages/harness/web/src/lib/events.ts +++ b/packages/harness/web/src/lib/events.ts @@ -12,6 +12,7 @@ import { isMockMode, } from "./api"; import { MOCK_ACTIVITY_SESSION_ID } from "./mock-data"; +import { hasKnownBusMessageType } from "./bus-message-type"; export type BusListener = (message: BusMessage) => void; export type EventReconnectListener = () => void; @@ -65,8 +66,11 @@ export function subscribeEvents( onMessage: BusListener, onReconnect?: EventReconnectListener, ): () => void { + const deliver = (message: unknown): void => { + if (hasKnownBusMessageType(message)) onMessage(message as BusMessage); + }; if (isMockMode()) { - mockListeners.add(onMessage); + mockListeners.add(deliver); if (!mockActivitySimulated) { mockActivitySimulated = true; // Fixture nicety, not test infrastructure: shows the tab strip's busy @@ -102,7 +106,7 @@ export function subscribeEvents( ); }, DEMO_RUN_DELAY_MS); } - return () => mockListeners.delete(onMessage); + return () => mockListeners.delete(deliver); } const url = new URL("/ws/events", window.location.href); @@ -122,7 +126,7 @@ export function subscribeEvents( }); socket.addEventListener("message", (event) => { try { - onMessage(JSON.parse(event.data as string) as BusMessage); + deliver(JSON.parse(event.data as string)); } catch { // Ignore malformed frames rather than tearing down the socket. } diff --git a/packages/harness/web/src/lib/use-harness-state.ts b/packages/harness/web/src/lib/use-harness-state.ts index e860f4048..e186c453e 100644 --- a/packages/harness/web/src/lib/use-harness-state.ts +++ b/packages/harness/web/src/lib/use-harness-state.ts @@ -1217,7 +1217,6 @@ export function useHarnessState(): HarnessStateHook { useEffect(() => { return subscribeEvents( (message) => { - if (message.type === "system-graph.changed") return; // SessionRecord invalidations have a targeted listener below. Keeping // them out of the legacy last-message slot avoids repainting the entire // Studio for records no mounted transcript is watching. diff --git a/scripts/agent-studio-terminology-allowlist.json b/scripts/agent-studio-terminology-allowlist.json index e96a91213..f153ceaf7 100644 --- a/scripts/agent-studio-terminology-allowlist.json +++ b/scripts/agent-studio-terminology-allowlist.json @@ -517,6 +517,13 @@ "occurrences": 2, "reason": "Test IDs inside the mock canvas document; the e2e suite selects on them." }, + { + "id": "web-bus-workflow-change-event", + "path": "packages/harness/web/src/lib/bus-message-type.ts", + "pattern": "^workflows\\.changed$", + "occurrences": 1, + "reason": "The transport accepts the retained source-discovery WebSocket event by its existing protocol name." + }, { "id": "web-api-workflow-change-event", "path": "packages/harness/web/src/lib/api.ts", From 38df935aefbdec383dd500790900309b17bb05b9 Mon Sep 17 00:00:00 2001 From: Yash Date: Wed, 9 Sep 2026 23:28:04 +0000 Subject: [PATCH 2/6] docs(harness): record cumulative graph retirement evidence (SAP-3091) --- .../authority-retirement.md | 106 ++++++++++++++++-- .../retirement-verification.json | 100 +++++++++++++++++ 2 files changed, 195 insertions(+), 11 deletions(-) create mode 100644 docs/plans/agent-studio-plan-first-agent-map/retirement-verification.json diff --git a/docs/plans/agent-studio-plan-first-agent-map/authority-retirement.md b/docs/plans/agent-studio-plan-first-agent-map/authority-retirement.md index a9189fc68..1344f3085 100644 --- a/docs/plans/agent-studio-plan-first-agent-map/authority-retirement.md +++ b/docs/plans/agent-studio-plan-first-agent-map/authority-retirement.md @@ -1,4 +1,4 @@ -# Agent Map authority and retirement gate (SAP-3089) +# Agent Map authority and source retirement (SAP-3089 / SAP-3090 / SAP-3091) The current Studio server owns one durable Agent Map per project. Its state response always includes `studioProjects`, including an empty list when the @@ -8,9 +8,10 @@ to infer a project from its name or serve a second topology. ## Release boundary The server retirement in [#892](https://github.com/sapiom/sapiom-js/pull/892) -and client recovery in [#893](https://github.com/sapiom/sapiom-js/pull/893) must -ship together. Merge both before merging a Harness version PR, publishing npm -packages or tagging a desktop release. The server-only layer still has a +and client recovery in [#893](https://github.com/sapiom/sapiom-js/pull/893) are +the foundation of the cumulative SAP-3090 / SAP-3091 cleanup stack. Review and +ship all seven layers together before merging a Harness version PR, publishing +npm packages or tagging a desktop release. The server-only layer still has a bundled browser fallback that reaches the retired endpoint on catalog failure. The server layer carries `.changeset/quiet-project-map-authority.md`, marking @@ -20,7 +21,9 @@ makes `scripts/assert-release-ready.mjs` fail before versioning or publishing. The local version/release commands and the Release PR, npm Publish and Desktop Release workflows all run that check. The client layer removes the blocker together with the unavailable-map recovery. Its recovery changeset remains a -patch; the combined Harness release takes the higher minor bump. +patch; the combined Harness release takes the higher minor bump. SAP-3091 also +adds `.changeset/quiet-retired-server-graphs.md` for the observable transition +from the temporary 410 response to generic API 404. ## Authority matrix @@ -63,10 +66,31 @@ The public PackageInventory contract remains in `@sapiom/agent`. Canonical path caching, accepted discovery evidence, shared watch leases and individual-agent Canvas extraction keep their existing owners and regression coverage. -## Evidence required before browser deletion +## Source-deletion boundaries -Attach results to SAP-3089 at the reviewed PR head. Do not treat the presence of -this file as evidence that a host or recovery exercise passed. +All layers were implemented on one cumulative working branch. Separate snapshot +refs keep the PR diffs reviewable; the final ref contains the complete stack for +local Studio validation. Human review is intentionally deferred until the +complete cleanup is available, as authorized by the maintainer. + +| Ticket/layer | Revision | Change | +| --- | --- | --- | +| SAP-3090 1/2 ([#907](https://github.com/sapiom/sapiom-js/pull/907)) | `42fcaccf` | Remove browser entry points and older-server session handoff. | +| SAP-3090 2/2 ([#908](https://github.com/sapiom/sapiom-js/pull/908)) | `4c4b7190` | Delete unreachable browser topology and repoint retained viewport/styles/tests. | +| SAP-3091 1/3 ([#909](https://github.com/sapiom/sapiom-js/pull/909)) | `67337e6d` | Extract retained workspace scope/path owners and Canvas invocation type. | +| SAP-3091 2/3 ([#910](https://github.com/sapiom/sapiom-js/pull/910)) | `1a338947` | Remove server routes and graph composition; retain discovery/currentness/watch ownership. | +| SAP-3091 3/3 | `cab477b541b0485f22a4948075d2921ba1a3434c` | Delete the server engine/store/watchers/relationships/contracts and filter unsupported browser events. | + +The last row is the exact source-deletion revision. Later evidence-only edits do +not change the tested runtime. A fresh production source and clean-built `dist` +search finds no remaining imports or callers of the retired modules. Old route +and event strings remain only in negative test/smoke probes. The public +`@sapiom/agent` PackageInventory source and schema are unchanged from `main`. + +## Retained verification gates + +Record results on SAP-3090, SAP-3091 and parent SAP-3083 at the accepted stack +head. The table defines the observation scope; actual run results follow below. | Gate | Reproducible evidence | | --- | --- | @@ -81,12 +105,72 @@ The Linux packaged run is Linux evidence. The required signed/notarized macOS installer and its upgrade journey remain release validation, not an inference from a Linux result. Record that platform's evidence in SAP-3086 before shipping. -## Candidate evidence — 2026-09-09 +## Final cleanup evidence — 2026-09-09 + +Runtime revision: `cab477b541b0485f22a4948075d2921ba1a3434c`. The +[machine-readable verification record](./retirement-verification.json) includes +package/bundle hashes, counts, skips and initial failures. Evidence-only commits +after this revision do not alter the runtime. + +- A clean Harness build followed by the root build, typecheck and lint passed. + Terminology, provider-copy, PR-template/security checks and all 178 root script + tests passed. The Node 24 VM's root test command still fails the unchanged + `agent-core` unreadable-directory assertion; this is not a green root run. +- All **3,840 retained Harness unit/integration cases** passed (two explicit + skips), and all **10 isolated performance cases** passed. Remaining packages + passed separately: MCP 179 (three skips), CLI 73, desktop 205. +- The browser run passed **625/627**; two Chrome targets crashed in the template + preference file. That entire file then passed **23/23**, without code changes. + All **627** unique cases passed across the full run and scoped rerun. All + **15 Canvas browser cases** passed. The current authority tests include + omitted-catalog recovery, exact session tabs and negative legacy request/event + probes; retained map layout, navigation, history, focus and mobile checks pass. +- Fresh Linux x64 packaging uses Harness **0.16.0**, desktop **0.4.6**, Electron + **33.4.11**. The unpacked app passed **16** smoke checks (one Windows-only skip). + The actual AppImage extract-and-run wrapper also passed **16** checks on its + isolated run, using the identical artifact and unchanged smoke coverage. + Both runs recorded old graph read/refresh/navigation counts **0/0/0**, direct + removed-route responses **404/404/404**, and unchanged saved map/history. +- All **195** built Harness runtime/assets match the packaged files byte-for-byte + (the builder intentionally excludes TypeScript declarations and source maps). + The clean built and packaged trees contain no retired graph modules. Desktop + packaging used copied dependencies; shared workspace native binaries retain + their original hashes. + +AppImage: `sapiom-0.4.6-x86_64.AppImage` + +SHA-256: `e63fb39419b54edc828814a7195faca6814edfe99b1f7f6c675c89752a3293ad`. + +### Preexisting session-scope race observed during validation + +The first AppImage run passed the map and other checks but failed its initial +session creation with `409 PROJECT_SESSION_SCOPE_UNAVAILABLE`. Its catalog +shows a newly enrolled root becoming `missing` during the handoff from +`pendingProjectCwds` to `SessionManager.pendingCreates`. Concurrent scope +reconciliation can omit the root while bootstrap scheduling/claim is awaiting. +The admission guard then correctly refuses the stale identity. The source +paths and scope derivation are unchanged by server cleanup; removed graph +scopes supplied no protective lease. The race predates this work in +[`873dad63`](https://github.com/sapiom/sapiom-js/commit/873dad63928c287b35c37c5c401042d7ffa05149) +and the scheduling handoff in +[`21684912`](https://github.com/sapiom/sapiom-js/commit/21684912c20feaf1d86a84e5ab8199dc205f32cc). + +The isolated AppImage rerun passed without changing the artifact or test. That +result does not fix the race. SAP-3091 records it as a separate functional +follow-up: retain scope continuously through enrollment, scheduling, claim and +transfer to pending creation, without allowing duplicate bootstrap sessions or +weakening final admission. A deterministic regression can hold the second +outbox `beforeSchedule` callback, complete a concurrent `/api/workflows` read, +then require one successful session with the same active identity. This seam +has been identified but not implemented or run in the cleanup. + +## Historical SAP-3089 authority evidence — 2026-09-09 The server fence is commit `d3c91355`, based on main `65219660`. Browser code, screenshots, and this record are reviewed together in the next stack layer. -This records implementation evidence; the SAP-3090 deletion decision still -requires review of that final head and its CI. +This is the original authority-fence evidence, before the source-deletion +revisions above. Its temporary 410 responses and original test counts are not +the final cleanup result. - Root build, typecheck and lint passed, including the final Harness browser rebuild. Terminology and provider-copy checks passed. diff --git a/docs/plans/agent-studio-plan-first-agent-map/retirement-verification.json b/docs/plans/agent-studio-plan-first-agent-map/retirement-verification.json new file mode 100644 index 000000000..6edb6e842 --- /dev/null +++ b/docs/plans/agent-studio-plan-first-agent-map/retirement-verification.json @@ -0,0 +1,100 @@ +{ + "revision": "cab477b541b0485f22a4948075d2921ba1a3434c", + "harnessVersion": "0.16.0", + "desktopVersion": "0.4.6", + "electronVersion": "33.4.11", + "platform": "linux-x64", + "appImage": "sapiom-0.4.6-x86_64.AppImage", + "appImageSha256": "e63fb39419b54edc828814a7195faca6814edfe99b1f7f6c675c89752a3293ad", + "checks": [ + { + "file": "dist/server/index.js", + "sha256": "de6c34771a6fb703f96e1a03c19983b7e5f192398232fbc7f23f3d92334d872d" + }, + { + "file": "dist/web/index.html", + "sha256": "c4da1b63ffaddaf29781f6857d1a0c865c7565523898edfd40a13028fce07d8f" + }, + { + "file": "dist/web/assets/index-BZtXtN0s.js", + "sha256": "304ecd5579eebacac3db002ac524c27fd4f06bc981e9b42a1b16a7edbeab8719" + } + ], + "retiredGraphFilesInPackagedDist": 0, + "byteMatchedRuntimeFiles": 195, + "nativeWorkspaceBinariesUnchanged": true, + "date": "2026-09-09", + "validation": { + "build": "passed after cleaning Harness dist", + "typecheck": "passed", + "lint": "passed with existing unrelated warnings", + "rootTest": { + "result": "failed", + "test": "agent-core/src/bundle-error.spec.ts: unreadable project directory", + "baseline": "same failure on unchanged prior code in the Node 24 VM" + }, + "harnessUnit": { + "passed": 3840, + "skipped": 2, + "filesPassed": 239, + "filesSkipped": 1 + }, + "harnessPerformance": { + "passed": 10 + }, + "browser": { + "uniqueCases": 627, + "fullRunPassed": 625, + "fullRunCrashed": 2, + "focusedFilePassed": 23, + "focusedFile": "web/e2e/template-harness.spec.ts", + "note": "Two Chrome target crashes; the full affected file passed unchanged with two workers." + }, + "canvas": { + "passed": 15 + }, + "remainingPackages": { + "mcpPassed": 179, + "mcpSkipped": 3, + "cliPassed": 73, + "desktopPassed": 205 + }, + "rootScriptTests": { + "passed": 178 + }, + "terminology": "passed", + "providerCopy": "passed", + "prTemplateAndSecurityChecks": "passed", + "linuxUnpackedSmoke": { + "passed": 16, + "skipped": 1, + "skippedCheck": "Windows-only agent-shim" + }, + "appImageSmoke": { + "initialPassed": 15, + "initialFailed": 1, + "initialSkipped": 1, + "initialFailure": "session-create: HTTP 409 PROJECT_SESSION_SCOPE_UNAVAILABLE", + "isolatedPassed": 16, + "isolatedSkipped": 1, + "artifactChanged": false, + "smokeCoverageChanged": false + }, + "agentMapSmoke": { + "legacyReadRequests": 0, + "legacyRefreshRequests": 0, + "legacyNavigationRequests": 0, + "directRetiredRouteStatuses": [ + 404, + 404, + 404 + ], + "savedMapAndHistoryUnchanged": true + } + }, + "limitations": [ + "Initial AppImage run exposed a preexisting session-scope retention gap between pendingProjectCwds and pendingCreates. It predates this cleanup; no admission checks or smoke coverage were weakened. A clean rerun does not fix the race.", + "Node 24 VM root test failure is recorded separately from successful retained package tests.", + "Linux evidence does not validate a signed/notarized macOS installer or installed-version upgrade. SAP-3086 retains those release gates." + ] +} From a0a88a44d0e8589f178896fa381b5a345a329336 Mon Sep 17 00:00:00 2001 From: Yash Date: Thu, 10 Sep 2026 07:34:03 +0000 Subject: [PATCH 3/6] fix(harness): preserve project map viewports across navigation Restore the browser contracts called out in review: remember manual pan and zoom per project for the current auth lifetime, retain automatic fitting, and cover sibling-agent project tabs. Refs: SAP-3090 --- .changeset/tall-maps-stay-durable.md | 4 +- .../harness/web/e2e/agent-map-recovery.html | 3 + .../web/e2e/agent-map-viewport.spec.ts | 106 ++++++++++++++++++ .../harness/web/e2e/project-altitude.spec.ts | 54 +++++++++ packages/harness/web/src/App.tsx | 9 ++ .../web/src/components/AgentMapCanvas.tsx | 87 ++++++++++---- .../web/src/components/AgentMapPane.tsx | 7 ++ .../harness/web/src/lib/graph-viewport.ts | 4 + 8 files changed, 252 insertions(+), 22 deletions(-) create mode 100644 packages/harness/web/e2e/agent-map-viewport.spec.ts diff --git a/.changeset/tall-maps-stay-durable.md b/.changeset/tall-maps-stay-durable.md index 4140edd6f..0bcb45458 100644 --- a/.changeset/tall-maps-stay-durable.md +++ b/.changeset/tall-maps-stay-durable.md @@ -2,4 +2,6 @@ "@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. +Remove unreachable legacy project graph browser code from Studio's bundled client and server. This internal cleanup preserves durable Agent Map navigation, project-wide conversation tabs, and ordinary sessions' independent Canvas and Steps views. + +Restore each project's map pan and zoom when returning from another project or an agent Canvas. If the saved view would leave every node offscreen, fit the map into view. diff --git a/packages/harness/web/e2e/agent-map-recovery.html b/packages/harness/web/e2e/agent-map-recovery.html index 64014f6cb..23cce85f0 100644 --- a/packages/harness/web/e2e/agent-map-recovery.html +++ b/packages/harness/web/e2e/agent-map-recovery.html @@ -6,10 +6,12 @@ import { createElement as h, useState } from "react"; import { createRoot } from "react-dom/client"; import { AgentMapCanvas } from "../src/components/AgentMapCanvas.tsx"; + import { createGraphViewportStore } from "../src/lib/graph-viewport.ts"; import { agentMapPackingFixture } from "./agent-map-packing-fixture.ts"; import "../src/styles.css"; function Fixture() { const [broken, setBroken] = useState(true); + const [viewportStore] = useState(createGraphViewportStore); const proposal = agentMapPackingFixture(); // Direct component props exercise recovery beyond the API's codec guard. if (broken) proposal.nodes.push(proposal.nodes[0]); @@ -25,6 +27,7 @@ "div", { id: "map", style: { width: 600, height: 900, display: "flex" } }, h(AgentMapCanvas, { + viewportStore, proposal, deployments: new Map(), selectedNodeId: null, diff --git a/packages/harness/web/e2e/agent-map-viewport.spec.ts b/packages/harness/web/e2e/agent-map-viewport.spec.ts new file mode 100644 index 000000000..34dd26a2e --- /dev/null +++ b/packages/harness/web/e2e/agent-map-viewport.spec.ts @@ -0,0 +1,106 @@ +import { expect, test, type Page } from "@playwright/test"; + +async function openProject(page: Page, project: string) { + await page.getByTestId(`project-select-${project}`).click(); + await expect(page.getByTestId("agent-map-canvas")).toHaveAttribute( + "data-layout-state", + "ready", + ); +} + +const transform = (page: Page) => + page.getByTestId("agent-map-subject").evaluate((el) => el.style.transform); + +test.beforeEach(async ({ page }) => { + await page.goto( + "/?seed=0&mockFixtures=deep&mockStudioProjects=present&mockAgentMapGolden=1", + ); + await expect(page.getByTestId("session-context")).toBeVisible(); + await openProject(page, "acme-app"); +}); + +test("each project's pan and zoom survive another project and an agent Canvas", async ({ + page, +}) => { + const initial = await transform(page); + await page.getByRole("button", { name: "Zoom in", exact: true }).click(); + await page.getByTestId("agent-map-viewport").focus(); + await page.keyboard.press("ArrowRight"); + const acmeView = await transform(page); + expect(acmeView).not.toBe(initial); + + await openProject(page, "polsia"); + expect(await transform(page)).not.toBe(acmeView); + await page.getByRole("button", { name: "Zoom in", exact: true }).click(); + await page.getByTestId("agent-map-viewport").focus(); + await page.keyboard.press("ArrowDown"); + const polsiaView = await transform(page); + expect(polsiaView).not.toBe(acmeView); + + await openProject(page, "acme-app"); + await expect.poll(() => transform(page)).toBe(acmeView); + await page + .getByTestId("workflow-leasing") + .locator(".workflow-item-trigger") + .click(); + await expect(page.getByTestId("agent-map-frame")).toHaveCount(0); + await expect(page.getByTestId("right-panel-board")).toBeVisible(); + await openProject(page, "acme-app"); + await expect.poll(() => transform(page)).toBe(acmeView); + await openProject(page, "polsia"); + await expect.poll(() => transform(page)).toBe(polsiaView); +}); + +test("returning to a map with every node offscreen fits it back into view", async ({ + page, +}) => { + const fitted = await transform(page); + // Pan well beyond the map using the actual viewport controls. + await page.getByTestId("agent-map-viewport").focus(); + for (let i = 0; i < 50; i += 1) await page.keyboard.press("ArrowRight"); + expect(await transform(page)).not.toBe(fitted); + await openProject(page, "polsia"); + await openProject(page, "acme-app"); + await expect.poll(() => transform(page)).toBe(fitted); +}); + +test("Fit clears the saved manual view and keeps following pane size after returning", async ({ + page, +}) => { + await page.getByRole("button", { name: "Zoom in", exact: true }).click(); + await page.getByRole("button", { name: "Fit Agent Map to view" }).click(); + await openProject(page, "polsia"); + await openProject(page, "acme-app"); + const normal = await transform(page); + await page.getByTestId("canvas-expand").click(); + await expect.poll(() => transform(page)).not.toBe(normal); + await expect(page.getByTestId("agent-map-canvas")).toHaveAttribute( + "data-layout-state", + "ready", + ); + const automatic = await transform(page); + await page.getByRole("button", { name: "Fit Agent Map to view" }).click(); + expect(await transform(page)).toBe(automatic); +}); + +test("an auth change discards the previous signed-in viewport", async ({ + page, +}) => { + const initial = await transform(page); + await page.getByRole("button", { name: "Zoom in", exact: true }).click(); + await page.getByTestId("agent-map-viewport").focus(); + await page.keyboard.press("ArrowRight"); + expect(await transform(page)).not.toBe(initial); + await page.evaluate(() => { + ( + window as unknown as { + __HARNESS_TEST__: { publish: (message: unknown) => void }; + } + ).__HARNESS_TEST__.publish({ + type: "auth.changed", + authenticated: true, + organizationName: "Another account", + }); + }); + await expect.poll(() => transform(page)).toBe(initial); +}); diff --git a/packages/harness/web/e2e/project-altitude.spec.ts b/packages/harness/web/e2e/project-altitude.spec.ts index 0afac17cc..0297e3d55 100644 --- a/packages/harness/web/e2e/project-altitude.spec.ts +++ b/packages/harness/web/e2e/project-altitude.spec.ts @@ -115,6 +115,60 @@ test("E3.4 — selecting a sibling agent moves the right pane and NOTHING else", ).toEqual(tabsBefore); }); +test("E3.3 — sessions bound to different agents stay in the project strip on sibling Canvas navigation", async ({ page }) => { + await page.goto( + "/?seed=0&mockFixtures=deep&mockNoLiveSessions=1&mockStudioProjects=present&mockAgentMapGolden=1", + ); + await expect(page.getByTestId("project-select-polsia")).toBeVisible(); + await page.getByTestId("project-select-polsia").click(); + const map = page.getByTestId("agent-map-live"); + await expect(map).toBeVisible(); + const projectId = await map.getAttribute("data-project-id"); + expect(projectId).toBeTruthy(); + await page.evaluate((projectId) => { + const { publish } = (window as unknown as { + __HARNESS_TEST__: { publish: (message: unknown) => void }; + }).__HARNESS_TEST__; + for (const [index, agent] of ["mailer", "rollup"].entries()) { + const id = `sess-polsia-${agent}`; + publish({ + type: "session.status", + session: { + id, + agentSessionId: null, + harness: "claude-code", + cwd: "/Users/demo/polsia", + status: "running", + ready: true, + title: agent, + createdAt: `2026-08-01T1${index}:00:00.000Z`, + lastActiveAt: `2026-08-01T1${index}:00:00.000Z`, + boundWorkflowPath: agent === "mailer" + ? "/Users/demo/polsia/packages/harness/web/src/components/mailer" + : "/Users/demo/polsia/scripts/tools/rollup", + agentMapIdentity: { projectId, userId: "user_mock", sessionId: id }, + }, + }); + } + }, projectId!); + const tabs = page.getByRole("tablist", { name: "Sessions" }).getByRole("tab"); + await expect(tabs).toHaveCount(2); + await expect(tabs.nth(0)).toHaveAttribute("data-testid", "session-tab-main-sess-polsia-mailer"); + await expect(tabs.nth(1)).toHaveAttribute("data-testid", "session-tab-main-sess-polsia-rollup"); + await tabs.nth(0).click(); + await expect(page.getByTestId("session-context")).toHaveAttribute("data-session-id", "sess-polsia-mailer"); + await page.getByTestId("project-select-polsia").click(); + await expect(map).toBeVisible(); + const before = await tabs.allTextContents(); + await page.getByTestId("workflow-rollup").locator(".workflow-item-trigger").click(); + await expect(page.getByTestId("workflow-rollup")).toHaveClass(/is-focused/); + await expect(map).toHaveCount(0); + await expect(page.getByTestId("right-panel-board")).toBeVisible(); + await expect(page.getByTestId("session-context")).toHaveAttribute("data-session-id", "sess-polsia-mailer"); + await expect(tabs).toHaveCount(2); + expect(await tabs.allTextContents()).toEqual(before); +}); + test("E3.9/E3.10 — Steps says why it cannot answer for a project; Code is gone", async ({ page, }) => { diff --git a/packages/harness/web/src/App.tsx b/packages/harness/web/src/App.tsx index 29ff8a60f..ac142bda1 100644 --- a/packages/harness/web/src/App.tsx +++ b/packages/harness/web/src/App.tsx @@ -44,6 +44,7 @@ import { useCallback, useEffect, useLayoutEffect, + useMemo, useRef, useState, } from "react"; @@ -67,6 +68,7 @@ import type { import { CanvasPane } from "./components/CanvasPane"; import { AgentMapPane } from "./components/AgentMapPane"; +import { createGraphViewportStore } from "./lib/graph-viewport"; import { CommandPalette } from "./components/CommandPalette"; import { ConnectivityBanner, @@ -287,6 +289,12 @@ const shellApi = createApi(); export const App = (): JSX.Element => { const harness = useHarnessState(); + // A project map remounts when browsing another project or agent. Keep its + // viewport for this signed-in UI lifetime, without persisting map data. + const agentMapViewportStore = useMemo( + createGraphViewportStore, + [harness.authRevision], + ); const [selectedHarness, setSelectedHarness] = useState( () => loadUiPrefs().preferredHarness ?? DEFAULT_HARNESS, ); @@ -3676,6 +3684,7 @@ export const App = (): JSX.Element => { ) : studioView?.altitude === "map" ? ( { - followsUpdates.current = true; + const commitView = useCallback( + (next: GraphView | ((current: GraphView) => GraphView)) => { + setView((current) => { + const resolved = typeof next === "function" ? next(current) : next; + // Only manual views need restoring. Auto-fit must keep following new + // layouts and pane sizes after navigating away and back. + if (followsUpdates.current) viewportStore.delete(proposal.projectId); + else viewportStore.set(proposal.projectId, resolved); + return resolved; + }); + }, + [proposal.projectId, viewportStore], + ); + + const measureFit = useCallback(() => { const viewport = viewportRef.current; - if (!viewport || !layout) return; + if (!viewport || !layout) return null; const rect = viewport.getBoundingClientRect(); + if (rect.width <= 0 || rect.height <= 0) return null; const root = Number.parseFloat( getComputedStyle(document.documentElement).fontSize, ); - const next = fitGraphView( + return fitGraphView( layout.bounds, { width: rect.width, height: rect.height }, Number.isFinite(root) ? root : 16, AGENT_MAP_MIN_ZOOM, ); - setMinZoom(next.minZoom); - setView({ zoom: Math.min(1, next.zoom), x: 0, y: 0 }); }, [layout]); + const fit = useCallback((): void => { + followsUpdates.current = true; + const next = measureFit(); + if (!next) return; + setMinZoom(next.minZoom); + commitView({ zoom: Math.min(1, next.zoom), x: 0, y: 0 }); + }, [commitView, measureFit]); + useLayoutEffect(() => { const viewport = viewportRef.current; if (!viewport || !layout) return; - if (fittedProjectRef.current !== proposal.projectId) - followsUpdates.current = true; const measure = (): void => { - const visible = viewport.getBoundingClientRect().width > 0; - if (!followsUpdates.current || !visible) return; - fittedProjectRef.current = proposal.projectId; - fit(); + const next = measureFit(); + if (!next) return; + setMinZoom(next.minZoom); + if (fittedProjectRef.current !== proposal.projectId) { + fittedProjectRef.current = proposal.projectId; + const saved = viewportStore.get(proposal.projectId); + const restored = saved && { + ...saved, + zoom: clampGraphZoom(saved.zoom, next.minZoom, AGENT_MAP_MIN_ZOOM), + }; + followsUpdates.current = true; + if ( + restored && + graphViewIntersectsViewport( + restored, + layout.bounds, + { width: viewport.clientWidth, height: viewport.clientHeight }, + layout.nodes, + ) + ) { + followsUpdates.current = false; + commitView(restored); + return; + } + } + if (followsUpdates.current) + commitView({ zoom: Math.min(1, next.zoom), x: 0, y: 0 }); }; measure(); if (typeof ResizeObserver === "undefined") return; const observer = new ResizeObserver(measure); observer.observe(viewport); return () => observer.disconnect(); - }, [fit, layout, proposal.projectId]); + }, [commitView, layout, measureFit, proposal.projectId, viewportStore]); useEffect(() => { const viewport = viewportRef.current; @@ -135,7 +180,7 @@ export function AgentMapCanvas({ event.preventDefault(); followsUpdates.current = false; const rect = viewport.getBoundingClientRect(); - setView((current) => + commitView((current) => wheelGraphView( current, event.deltaY, @@ -150,7 +195,7 @@ export function AgentMapCanvas({ }; viewport.addEventListener("wheel", wheel, { passive: false }); return () => viewport.removeEventListener("wheel", wheel); - }, [minZoom]); + }, [commitView, minZoom]); const startPan = (event: ReactPointerEvent): void => { if ((event.target as Element).closest("button")) return; @@ -168,7 +213,7 @@ export function AgentMapCanvas({ if (!drag || drag.pointerId !== event.pointerId) return; if (event.clientX !== drag.x || event.clientY !== drag.y) followsUpdates.current = false; - setView({ + commitView({ ...drag.origin, x: drag.origin.x + event.clientX - drag.x, y: drag.origin.y + event.clientY - drag.y, @@ -182,7 +227,7 @@ export function AgentMapCanvas({ const revealNode = (node: GraphRect): void => { const viewport = viewportRef.current; if (!viewport || !layout) return; - setView((current) => { + commitView((current) => { const next = revealGraphRect( current, layout.bounds, @@ -221,7 +266,7 @@ export function AgentMapCanvas({ return; event.preventDefault(); followsUpdates.current = false; - setView((current) => + commitView((current) => panGraphViewWithKeyboard(current, event.key as GraphArrowKey), ); }} @@ -415,7 +460,7 @@ export function AgentMapCanvas({ aria-label="Zoom out" onClick={() => { followsUpdates.current = false; - setView((current) => ({ + commitView((current) => ({ ...current, zoom: clampGraphZoom( current.zoom - GRAPH_ZOOM_STEP, @@ -433,7 +478,7 @@ export function AgentMapCanvas({ aria-label="Reset Agent Map view" onClick={() => { followsUpdates.current = false; - setView(resetGraphView()); + commitView(resetGraphView()); }} > {Math.round(view.zoom * 100)}% @@ -445,7 +490,7 @@ export function AgentMapCanvas({ disabled={view.zoom >= GRAPH_MAX_ZOOM} onClick={() => { followsUpdates.current = false; - setView((current) => ({ + commitView((current) => ({ ...current, zoom: clampGraphZoom( current.zoom + GRAPH_ZOOM_STEP, diff --git a/packages/harness/web/src/components/AgentMapPane.tsx b/packages/harness/web/src/components/AgentMapPane.tsx index 2a4d30658..1c5ba20f6 100644 --- a/packages/harness/web/src/components/AgentMapPane.tsx +++ b/packages/harness/web/src/components/AgentMapPane.tsx @@ -14,6 +14,7 @@ import type { } from "@shared/agent-map"; import type { WorkflowInfo } from "@shared/types"; import type { HarnessApi } from "../lib/api"; +import type { GraphViewportStore } from "../lib/graph-viewport"; import { agentMapDeployments, type AgentMapDeployments, @@ -33,6 +34,7 @@ import { AgentMapInspector } from "./AgentMapInspector"; import { Icon } from "./Icon"; interface AgentMapPaneProps { + viewportStore: GraphViewportStore; visible: boolean; api: Pick< HarnessApi, @@ -51,6 +53,7 @@ interface AgentMapPaneProps { } export function AgentMapPane({ + viewportStore, visible, api, workflows, @@ -280,6 +283,7 @@ export function AgentMapPane({ } else if (proposal && proposal.nodes.length > 0) { content = ( void; @@ -421,6 +427,7 @@ function PopulatedAgentMap({
Date: Thu, 10 Sep 2026 07:34:03 +0000 Subject: [PATCH 4/6] fix(harness): restore Agent Map metadata typography Preserve the muted monospace metadata role after removing the old graph styles. Cover the computed light and dark styles, attach mock-fixture before and after screenshots, and remove the stale mock failure comment. Refs: SAP-3090 --- .../SAP-3090/metadata-after-dark.png | Bin 0 -> 129860 bytes .../SAP-3090/metadata-after-light.png | Bin 0 -> 131719 bytes .../SAP-3090/metadata-before-dark.png | Bin 0 -> 132371 bytes .../SAP-3090/metadata-before-light.png | Bin 0 -> 131480 bytes .../web/e2e/agent-map-metadata.spec.ts | 60 ++++++++++++++++++ packages/harness/web/src/lib/api.ts | 7 +- packages/harness/web/src/styles.css | 7 +- 7 files changed, 65 insertions(+), 9 deletions(-) create mode 100644 .github/screenshots/SAP-3090/metadata-after-dark.png create mode 100644 .github/screenshots/SAP-3090/metadata-after-light.png create mode 100644 .github/screenshots/SAP-3090/metadata-before-dark.png create mode 100644 .github/screenshots/SAP-3090/metadata-before-light.png create mode 100644 packages/harness/web/e2e/agent-map-metadata.spec.ts diff --git a/.github/screenshots/SAP-3090/metadata-after-dark.png b/.github/screenshots/SAP-3090/metadata-after-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..15acfda2a05ce919c1d7b3676db3f599f989aabc GIT binary patch literal 129860 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 literal 0 HcmV?d00001 diff --git a/.github/screenshots/SAP-3090/metadata-after-light.png b/.github/screenshots/SAP-3090/metadata-after-light.png new file mode 100644 index 0000000000000000000000000000000000000000..ba99c794779cfb3a6e6dc1831b28492f26d3cce8 GIT binary patch literal 131719 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ⓈZc- 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%0D7R{EV2}p9prK* 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 literal 0 HcmV?d00001 diff --git a/packages/harness/web/e2e/agent-map-metadata.spec.ts b/packages/harness/web/e2e/agent-map-metadata.spec.ts new file mode 100644 index 000000000..6d8e848cf --- /dev/null +++ b/packages/harness/web/e2e/agent-map-metadata.spec.ts @@ -0,0 +1,60 @@ +import { expect, test } from "@playwright/test"; + +for (const theme of ["light", "dark"] as const) { + test(`map metadata uses the muted monospace role in ${theme} mode`, async ({ + page, + }) => { + await page.goto( + "/?seed=0&mockFixtures=deep&mockStudioProjects=present&mockAgentMapGolden=1", + ); + await expect(page.getByTestId("session-context")).toBeVisible(); + await page.getByTestId("project-select-acme-app").click(); + await expect(page.getByTestId("agent-map-canvas")).toHaveAttribute( + "data-layout-state", + "ready", + ); + await page + .getByTestId("agent-map-info-node_00000000-0000-7000-8000-000000000101") + .click(); + await expect(page.getByTestId("agent-map-inspector")).toBeVisible(); + await page.evaluate((value) => { + document.documentElement.dataset.theme = value; + }, theme); + + // Resolve the design roles in the browser, so this checks the cascade and + // rem/theme resolution at each consumer rather than matching CSS source. + const expected = await page.evaluate(() => { + const reference = document.createElement("span"); + reference.style.cssText = + "color:var(--text-faint);font-family:var(--font-mono);font-size:var(--type-meta)"; + document.body.append(reference); + const style = getComputedStyle(reference); + const result = { + color: style.color, + fontFamily: style.fontFamily, + fontSize: style.fontSize, + }; + reference.remove(); + return result; + }); + for (const selector of [ + ".agent-map-live-header .agent-map-node-meta", + ".agent-map-node .agent-map-node-meta", + ".agent-map-inspector .agent-map-node-meta", + ]) { + const metadata = page.locator(selector); + await expect(metadata.first()).toBeVisible(); + const actual = await metadata.evaluateAll((elements) => + elements.map((element) => { + const style = getComputedStyle(element); + return { + color: style.color, + fontFamily: style.fontFamily, + fontSize: style.fontSize, + }; + }), + ); + for (const style of actual) expect(style).toEqual(expected); + } + }); +} diff --git a/packages/harness/web/src/lib/api.ts b/packages/harness/web/src/lib/api.ts index 5f95844b5..0516df902 100644 --- a/packages/harness/web/src/lib/api.ts +++ b/packages/harness/web/src/lib/api.ts @@ -2991,11 +2991,8 @@ export class MockApi implements HarnessApi { async getRailState(projectRoot: string): Promise { await delay(60); - // Test-only, mock mode only, matching __MOCK_SYSTEM_GRAPH_FAIL_ONCE__: a - // read-only checkout or a 5xx on this route is the one case where "safe to - // write" and "safe to draw" have different answers, and getting that wrong - // leaves the rail naming every system while the map shows an unlabelled - // blob. Reachable only by throwing the read. + // Mock-only read failure: keep the rail usable without overwriting saved + // state that could not be loaded. if ( typeof window !== "undefined" && (window as unknown as { __MOCK_RAIL_STATE_FAIL__?: boolean }) diff --git a/packages/harness/web/src/styles.css b/packages/harness/web/src/styles.css index 09e8391af..3d8dde0a7 100644 --- a/packages/harness/web/src/styles.css +++ b/packages/harness/web/src/styles.css @@ -4138,10 +4138,9 @@ button.rail-footer-card:hover { } .agent-map-node-meta { - width: 100%; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; + color: var(--text-faint); + font-family: var(--font-mono); + font-size: var(--type-meta); } .agent-map-controls { From 5bfed981be12701e523e9096bdd0ab498aff0f20 Mon Sep 17 00:00:00 2001 From: Yash Date: Thu, 10 Sep 2026 07:34:03 +0000 Subject: [PATCH 5/6] docs(harness): reconcile graph retirement release notes Describe the final authenticated 404 contract consistently across the combined release and document JSON responses for every unknown API path. Refs: SAP-3091 --- .changeset/quiet-project-map-authority.md | 2 +- .changeset/quiet-retired-server-graphs.md | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.changeset/quiet-project-map-authority.md b/.changeset/quiet-project-map-authority.md index beb1118c9..72fade082 100644 --- a/.changeset/quiet-project-map-authority.md +++ b/.changeset/quiet-project-map-authority.md @@ -4,7 +4,7 @@ **Breaking for HTTP clients** (minor while `@sapiom/harness` is pre-1.0): retire the documented project System Graph endpoints. Authenticated requests to all -three routes now return `410` with `error: "legacy_graph_retired"`: +three routes now return the generic JSON API `404` response: - `GET /api/workspaces/:workspaceKey/system-graph` - `POST /api/workspaces/:workspaceKey/system-graph/refresh` diff --git a/.changeset/quiet-retired-server-graphs.md b/.changeset/quiet-retired-server-graphs.md index 3386372fd..3882b07c6 100644 --- a/.changeset/quiet-retired-server-graphs.md +++ b/.changeset/quiet-retired-server-graphs.md @@ -2,4 +2,6 @@ "@sapiom/harness": minor --- -Remove the retired project graph server runtime and HTTP handlers. Authenticated requests to the old graph, refresh, and navigation URLs now return the generic API 404; unauthenticated requests still return 401. Use durable project IDs and the Agent Map APIs. Shared agent discovery, ordinary sessions, and per-agent Canvas remain available. +Remove the retired project graph server runtime and HTTP handlers. Authenticated requests to the old graph, refresh, and navigation URLs return the generic JSON API 404; requests without the required boot token still return 401. The JSON 404 fallback applies to all unknown `/api` paths, preventing them from falling through to the Studio HTML shell. + +Use durable project IDs and the Agent Map APIs. Shared agent discovery, ordinary sessions, and per-agent Canvas remain available. From e1b8e23497680ee62a51640644b6f499f2ccd729 Mon Sep 17 00:00:00 2001 From: Yash Date: Thu, 10 Sep 2026 07:47:13 +0000 Subject: [PATCH 6/6] docs(harness): record E8 review fixes and fresh validation Keep original package evidence separate from current source and build results, including the initial archive test failure and unchanged passing reruns. Refs: SAP-3089, SAP-3090, SAP-3091 --- .../authority-retirement.md | 58 ++++++- .../retirement-verification.json | 147 +++++++++++++++++- 2 files changed, 196 insertions(+), 9 deletions(-) diff --git a/docs/plans/agent-studio-plan-first-agent-map/authority-retirement.md b/docs/plans/agent-studio-plan-first-agent-map/authority-retirement.md index 1344f3085..2ea3c92e0 100644 --- a/docs/plans/agent-studio-plan-first-agent-map/authority-retirement.md +++ b/docs/plans/agent-studio-plan-first-agent-map/authority-retirement.md @@ -22,8 +22,9 @@ The local version/release commands and the Release PR, npm Publish and Desktop Release workflows all run that check. The client layer removes the blocker together with the unavailable-map recovery. Its recovery changeset remains a patch; the combined Harness release takes the higher minor bump. SAP-3091 also -adds `.changeset/quiet-retired-server-graphs.md` for the observable transition -from the temporary 410 response to generic API 404. +adds `.changeset/quiet-retired-server-graphs.md`. Both retirement changesets +describe the final authenticated JSON API 404, which applies to every unknown +`/api` path. The intermediate 410 fence is not a separately published contract. ## Authority matrix @@ -81,9 +82,10 @@ complete cleanup is available, as authorized by the maintainer. | SAP-3091 2/3 ([#910](https://github.com/sapiom/sapiom-js/pull/910)) | `1a338947` | Remove server routes and graph composition; retain discovery/currentness/watch ownership. | | SAP-3091 3/3 | `cab477b541b0485f22a4948075d2921ba1a3434c` | Delete the server engine/store/watchers/relationships/contracts and filter unsupported browser events. | -The last row is the exact source-deletion revision. Later evidence-only edits do -not change the tested runtime. A fresh production source and clean-built `dist` -search finds no remaining imports or callers of the retired modules. Old route +The last row is the exact source-deletion revision. Subsequent review fixes +have their own runtime revision and verification record below. A fresh production +source and clean-built `dist` search finds no remaining imports or callers of +the retired modules. Old route and event strings remain only in negative test/smoke probes. The public `@sapiom/agent` PackageInventory source and schema are unchanged from `main`. @@ -105,12 +107,52 @@ The Linux packaged run is Linux evidence. The required signed/notarized macOS installer and its upgrade journey remain release validation, not an inference from a Linux result. Record that platform's evidence in SAP-3086 before shipping. -## Final cleanup evidence — 2026-09-09 +## Review-fix verification — 2026-09-10 + +Runtime source revision: `5bfed981be12701e523e9096bdd0ab498aff0f20`, including +`main` at `8679d7457a8c4a1f40b2137da9e677de01b62a53`. The JSON record's +`reviewFixes` entry contains fresh build hashes and per-PR typecheck results. +These updates preserve the original reviewed commits and the seven PR +boundaries; the cumulative working branch still contains every layer. + +- #892 uses main's complete partial auth mock to resolve the merge conflict. + All 263 integration checks passed; that mock's four cases also passed on + #892's own tree. Main's deliberate removal of the duplicate Claude review + workflow is carried through the stack. +- #907 restores per-project manual pan and zoom across project/agent navigation. + Saved views are scoped to the current signed-in UI lifetime; offscreen maps + recover by fitting, and Fit continues following pane/layout changes. Browser + coverage restores E3.3's project tabs across different agent bindings. Its + changeset identifies the removed compatibility branch as internal cleanup. +- #908 restores `--text-faint`, `--font-mono` and `--type-meta`, with computed + style assertions and before/after mock screenshots in light and dark themes. + The stale mock failure comment is removed. The viewport and metadata tests + failed on the original code, then passed with the fixes. +- #910 reconciles both retirement changesets to the final JSON 404 contract, + including all unknown `/api` paths. Boot-token authentication remains required. + +Harness and dependency builds, Harness typecheck/lint, terminology and +provider-copy checks passed. All **3,845 Harness unit/integration cases** passed +(two explicit skips), all **10 performance cases** passed, all **634 browser +cases** passed, and all **15 Canvas browser cases** passed. All seven isolated +PR heads passed server/browser typechecks; #907's own tree also passed all ten +viewport/project-altitude cases. The fresh build contains no retired graph files. + +The first three-worker Harness run failed one archive-wiring case with an empty +turn list. The affected file passed unchanged **8/8**, and the full two-worker +rerun passed unchanged. The initial failure remains in the JSON record; no test +or admission guard was weakened. + +The package hashes and smoke evidence below belong to the earlier deletion +revision. They are historical evidence, not a newly packaged review-fix artifact. +Signed macOS installer/upgrade validation remains the SAP-3086 release gate. + +## Original cleanup evidence — 2026-09-09 Runtime revision: `cab477b541b0485f22a4948075d2921ba1a3434c`. The [machine-readable verification record](./retirement-verification.json) includes -package/bundle hashes, counts, skips and initial failures. Evidence-only commits -after this revision do not alter the runtime. +package/bundle hashes, counts, skips and initial failures. The subsequent +review-fix revision is recorded separately above. - A clean Harness build followed by the root build, typecheck and lint passed. Terminology, provider-copy, PR-template/security checks and all 178 root script diff --git a/docs/plans/agent-studio-plan-first-agent-map/retirement-verification.json b/docs/plans/agent-studio-plan-first-agent-map/retirement-verification.json index 6edb6e842..3ac142532 100644 --- a/docs/plans/agent-studio-plan-first-agent-map/retirement-verification.json +++ b/docs/plans/agent-studio-plan-first-agent-map/retirement-verification.json @@ -96,5 +96,150 @@ "Initial AppImage run exposed a preexisting session-scope retention gap between pendingProjectCwds and pendingCreates. It predates this cleanup; no admission checks or smoke coverage were weakened. A clean rerun does not fix the race.", "Node 24 VM root test failure is recorded separately from successful retained package tests.", "Linux evidence does not validate a signed/notarized macOS installer or installed-version upgrade. SAP-3086 retains those release gates." - ] + ], + "reviewFixes": { + "date": "2026-09-10", + "sourceRevision": "5bfed981be12701e523e9096bdd0ab498aff0f20", + "builtAssets": [ + { + "file": "server/index.js", + "sha256": "158275759366835e841e023b64aa4cbfb76d6fab3d85e31de9694b0915938ab1" + }, + { + "file": "web/index.html", + "sha256": "58c37a75d1758897225daefb4dd6f343529bb8c82fc95c3154c94bb41a3c0456" + }, + { + "file": "web/assets/index-C-d3Neif.js", + "sha256": "9eebc5cf2d76dbff7e45c50514fe676f55aaac38d11038d81cf245e36c756f05" + }, + { + "file": "web/assets/index-xp2ouk6y.css", + "sha256": "917059001d832523c198c9e1cc36db5fa389db5a3abfcd4263a8c445c1f0d61b" + } + ], + "retiredGraphFilesInBuiltDist": 0, + "integratedMain": "8679d7457a8c4a1f40b2137da9e677de01b62a53", + "scope": [ + "Resolve the main auth mock conflict with the complete partial mock.", + "Restore manual project map viewports across project and agent navigation, with auth isolation, offscreen recovery and retained auto-fit.", + "Restore cross-agent project tab coverage and clarify the unreachable browser compatibility cleanup changeset.", + "Restore muted monospace Agent Map metadata, cover computed light/dark styles and record mock before/after screenshots.", + "Remove the stale mock graph failure comment.", + "Reconcile both retirement changesets to the final authenticated JSON 404 contract for every unknown API path." + ], + "validation": { + "harnessAndDependencyBuild": "passed", + "harnessTypecheck": "passed", + "harnessLint": "passed", + "terminology": "passed", + "providerCopy": "passed", + "mainIntegrationTests": { + "passed": 263 + }, + "harnessUnit": { + "passed": 3845, + "skipped": 2, + "filesPassed": 239, + "filesSkipped": 1, + "workers": 2 + }, + "initialHarnessUnitRun": { + "passed": 3844, + "failed": 1, + "skipped": 2, + "workers": 3, + "failure": "record-archive-wiring: keeps a session readable after its events are swept; turns[0] was undefined", + "unchangedFocusedFileRerun": { + "passed": 8 + }, + "note": "The subsequent complete two-worker run passed unchanged; the initial failure is retained rather than omitted." + }, + "harnessPerformance": { + "passed": 10 + }, + "browser": { + "passed": 634, + "workers": 2, + "browser": "installed Google Chrome" + }, + "canvas": { + "passed": 15 + }, + "focusedBrowser": { + "passed": 16, + "regressionsFailedBeforeFix": [ + "project viewport restoration", + "metadata computed styles in light and dark" + ] + }, + "isolatedPrHeads": [ + { + "number": 892, + "head": "c614bc3a457991348a3b754fcceba5cf15c3e295", + "checks": { + "server-typecheck": 0, + "web-typecheck": 0, + "auth-mock": 0 + } + }, + { + "number": 893, + "head": "1b8934720686cc46490b85cc17e9c69d46051547", + "checks": { + "server-typecheck": 0, + "web-typecheck": 0 + } + }, + { + "number": 907, + "head": "22452e67fb85dfd4f95af54876f65f1f3ec0efde", + "checks": { + "server-typecheck": 0, + "web-typecheck": 0, + "browser-contracts": 0 + } + }, + { + "number": 908, + "head": "62c2ffd79feca85d277e709053b17f44827b4d5b", + "checks": { + "server-typecheck": 0, + "web-typecheck": 0 + } + }, + { + "number": 909, + "head": "b43e79cb8effc33d6a0ad028e5c12f93b919586c", + "checks": { + "server-typecheck": 0, + "web-typecheck": 0 + } + }, + { + "number": 910, + "head": "5a1b979c0dede92bcd711ddd3ef65e6fb5ecdba2", + "checks": { + "server-typecheck": 0, + "web-typecheck": 0 + } + }, + { + "number": 912, + "head": "184c4e301cc9525545e4298934b310e0f990b851", + "checks": { + "server-typecheck": 0, + "web-typecheck": 0 + } + } + ] + }, + "screenshots": [ + ".github/screenshots/SAP-3090/metadata-before-light.png", + ".github/screenshots/SAP-3090/metadata-after-light.png", + ".github/screenshots/SAP-3090/metadata-before-dark.png", + ".github/screenshots/SAP-3090/metadata-after-dark.png" + ], + "packagingScope": "The AppImage hashes and packaged smoke results above belong to the original 2026-09-09 deletion revision. These review-fix results validate the current source and build; signed macOS installer/upgrade validation remains SAP-3086." + } }