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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 95 additions & 11 deletions docs/plans/agent-studio-plan-first-agent-map/authority-retirement.md
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand All @@ -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

Expand Down Expand Up @@ -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 |
| --- | --- |
Expand All @@ -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.
Expand Down
Original file line number Diff line number Diff line change
@@ -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."
]
}
5 changes: 2 additions & 3 deletions packages/harness/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
40 changes: 40 additions & 0 deletions packages/harness/docs/agent-map-api.md
Original file line number Diff line number Diff line change
@@ -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.
Loading
Loading