Image Workspace Protocol v5

September 10, 2026 · View on GitHub

Audience: embedding hosts, agent authors, protocol implementers, and reviewers.

Status: implemented bounded workspace protocol; HOSTED GREEN under the v0.4.0 release baseline. The earlier authoring-only status is superseded. This does not establish performance, unrestricted publication, or complete-programme support.

V5 adds a host-configured session and explicit live-source refresh without changing v1–v4 method lists or response bytes. Its envelope is semaprax.image-agent-result.v5, with protocol semaprax.image-agent-protocol.v5, exact image_revision, exact project_revision, and a method-specific payload. Existing non-discovery semantic payload schemas remain their owned versions. Discovery descriptions, schemas, and generated clients derive from the methods actually enabled by the fixed host policy; user payload strings are never rewritten to upgrade schemas.

Host configuration

VNextSession::open(&absolute_manifest, VNextPolicy {
    candidate_prepare: true,
    diagnostics: true,
    test_policy: None,
    build_enabled: false,
})

The absolute manifest must equal its authenticated canonical Project path. Defaults are semantic reads and explicit refresh only. Diagnostics, interpreted tests, and pathless builds additionally require candidate_prepare; tests use the host's existing fixed CandidateTestPolicy. No request changes these booleans or limits. serve_vnext(input, output, session) accepts host-provided streams and the already configured session; it discovers no paths or authority.

An embedding host can also attach an independently verified immutable package graph before requests. This selects package/summary and package/consumers without widening any execution, candidate or publication grant. They describe an independent package subject, not a relationship to the current Project. No RPC accepts package input paths or attaches/replaces a graph. See Package Semantic Graph.

The optional MCP adapter consumes that configured session and exposes its selected methods as tools. It preserves exact v5 arguments and response bytes, requires a separate MCP initialization handshake, and cannot add a grant or approve a candidate. Its larger outer response bound accounts for escaping a complete v5 response before any operation runs.

An additive open_with_frontend_cache constructor keeps the same policy and image identity while reusing source-exact compiler ASTs during authenticated live refresh. The separate embedding-host handle_read_batch API runs selected immutable image/discovery and retained semantic reads on bounded scoped workers. Neither changes the ordinary sequential NDJSON loop or grants new methods. See Live Frontend Cache and Parallel Reads and Parallel Retained Reads for their explicit host choices and detached worker inputs.

The default read-only method set also includes image/dependencies: exact-image, stable-ID declaration dependency reports delivered in bounded UTF-8 chunks. It shares the immutable image index with candidate deltas and the host parallel read path; no candidate grant or publication authority is needed or acquired. See Declaration Dependencies.

image/analysis-coverage is another default exact-image semantic read. It reports retained source facts alongside explicit uninspected deployment, generated-file, external-API, runtime and consumer boundaries. It accepts no external paths or execution authority; missing imports never prove missing external dependencies. See Analysis Coverage.

With candidate preparation, candidate/analysis-coverage applies that same closed inventory to one exact fully admitted candidate revision. The outer response remains bound to the live session image, while the payload image, Project, graph and source identities describe the candidate. It preserves all uninspected areas and creates no additional candidate or derived-image entry. See Candidate Analysis Coverage.

Agents can instead request image/dependency-summary and expand selected image/dependency-page handles. These structured read-only methods expose counts and bounded sites/callers/calls/members pages without transferring the complete report. See Dependency Navigation.

image/function-reference-export emits a compact canonical selector for one declared function and optional facet. image/function-reference-resolve accepts those exact bytes only against the same image revision, verifies the Project, Workspace, graph and source provenance, and freshly derives the current function summary and selected facet handle. Both closed-schema methods are eligible for authenticated read batches. The reference is an integrity and staleness binding, not persistent compiler state, a migration token, a secret, a capability or source/publication authority. See Function Reference v1.

With candidate preparation, candidate/dependency-summary and candidate/dependency-page expose the same compact views over one exact retained candidate revision. Their handles and cursors bind the candidate, so base-image and sibling-candidate selectors cannot be reused. The queries derive and discard an image from the already admitted candidate, create or retain no additional candidate or derived-image registry entry, and are eligible for detached authenticated read batches. See Candidate Dependency Navigation.

Candidate preparation also selects candidate/impact-summary and candidate/impact-page. These methods recompute the existing bounded reverse impact artifact for the exact candidate and expose its affected, dependency-edge and frontier inventories through artifact/query-bound handles. Page items use a self-identifying unbundled envelope whose value is the unchanged compiler row. Truncation and budget evidence remain visible; pagination adds no omitted facts, authority, execution or completeness. See Candidate Impact Navigation.

Startup-only archive handoff can preload complete historical candidates from independently replayed source-backed archives. It retains the current image and fixed policy, requires the same canonical manifest, and grants no approvals or publication authority. No archive/store root is accepted through an RPC frame. See Workspace Archive Recovery v1.

Candidate preparation also selects hole/recovery-export and hole/recovery-restore for Typed-Hole Draft Recovery. These methods recover pending selectors over source-replayed valid history, retaining only a draft and no authority. Unresolved holes still block completion. Restore requires the current exact original base and the existing request-frame limit; it cannot silently rebase a draft after source changes. Refresh continues to clear drafts, and v1–v4 gain no recovery methods for unfinished work.

Candidate preparation also selects the read-only candidate/merge-preview query. It authenticates two retained candidate selectors, attempts ordinary semantic merge in both orders and reports directional admission plus exact resulting source comparison. Temporary merged candidates are not installed in the registry. Diagnostic excerpts require no rejected-attempt grant and cannot be used as attempt handles. See Merge Preview.

Candidate preparation also selects candidate/contract-expression-catalog and hole/open-contract-expression. These expose existing pre/postcondition subtrees and open Contract Expression Holes over exact candidate/draft revisions. Existing fill, query, completion and recovery routes handle these drafts; unresolved contract holes block completion alongside body holes. Older body-expression methods remain body-only.

Semantic conformance reads and target-admission projections are available independently of diagnostic permission. Candidate preparation adds current candidate, expression-hole, interface-discovery, and semantic-delta operations. Rejected-attempt operations require diagnostics. Runtime test execution and artifact projection have separate host selections. A build projects compiler artifacts into bounded reports; it does not publish files or execute a native or Wasm target. Source publication requires a separately attached Git host.

Candidate preparation also grants candidate/interface-delta, a read-only, whole-candidate comparison of static interface declarations and their bound functions. Diagnostic selection grants candidate/symbol-diagnostics, which associates retained rejected attempts only with their exact predecessor and intention target. It never attributes a rejected-source span to verified HIR. Both use bounded report chunks under current image and candidate expectations; diagnostic continuations additionally require the exact report revision because the retained attempt inventory can change. Parallel retained reads select an immutable snapshot of that inventory inside source authentication. Neither method grants repair application, execution, or publication. Their report contracts are Interface Delta and Symbol Diagnostics.

Candidate preparation also grants candidate/contract-delta, the additive Contract Delta read. It compares all contract-bearing functions against the candidate's original base, including static helper dependencies behind unchanged predicates. It takes no target selector and returns immutable bounded UTF-8 chunks under exact image/candidate expectations. It performs no target projection or execution, grants no additional authority. The parallel retained-read extension admits the same pure handler.

candidate/ownership-delta uses the same candidate-preparation grant and bounded chunk parameters for Ownership Delta. It compares checked signatures, structural inventories and complete ordered loan/cleanup plans across the candidate. It takes no target and gains no target execution, plan mutation or physical ownership authority.

The existing build grant also enables candidate/artifact-delta, which compares actual base/candidate Web or npm carriers through Artifact Delta. It replays the candidate before either build, compares file/export/source bindings, and returns chunks. The request cannot change the fixed build limit or gain artifact filesystem materialization. Candidate preparation alone does not enable this method.

The same grant additively selects candidate/analysis-artifact-evidence. It composes exact candidate analysis coverage with one freshly replayed Web, npm, OpenAPI or C artifact delta and returns the heterogeneous report in bounded UTF-8 chunks. The closed chunk binds the candidate and kind and includes plain SHA256 of the exact full report bytes for consistent reassembly. The route is a build-class operation, is absent without candidate_build, and is excluded from parallel reads and workspace/read-batch. Only generated_artifacts becomes partial for the selected pathless carrier; no materialization, deployment, native compilation, target execution or external-consumer evidence is inferred.

All available method names, closed request parameters, payload schema references, capabilities, and generated clients come from the selected catalogue. Optional parameters are omitted; null is accepted only where the declared schema permits it. The schema bundle explicitly lists payload schemas that remain opaque and links bundled constructor schemas. Generated clients only construct/validate messages; they have no filesystem, network, process, approval, or session-policy authority.

With candidate preparation selected, workspace/retained-subjects returns the bounded compact Retained Subjects v1 inventory for this session. It lists live candidate, draft and rejected-attempt handles in deterministic order, including registry-local association/orphan flags and the owning detail/discard methods. Membership grants no validity, source freshness, execution or publication authority. Because the inventory observes mutable session state, it is excluded from workspace/read-batch.

Candidate preparation also selects candidate/function-summary and candidate/function-facet, the compact Candidate Function Facets v1 projection. Nine handles bind the exact final candidate, ephemeral derived image, target and facet. Pages preserve existing HIR item order; page cursors fix handle, offset and page size while allowing the existing byte limit to vary. Both pure reads are eligible for detached authenticated parallel batches and grant no execution, retention, source or publication authority.

Explicit refresh and stale state

After a manual edit, call workspace/refresh-preview with the current image digest. It independently reads the same fixed manifest and returns observed Project/image revisions without replacing the current image or snapshot, clearing registries, or reviving an invalidated session. Its v5 envelope remains bound to the old session image; the semaprax.image-workspace-refresh-preview.v1 payload explicitly labels observed_project_revision and observed_image_revision. The payload also records old_image_revision, the observed Workspace revision, manifest_changed:false, current_state_replaced:false, requires_explicit_refresh:true, and source_authority:false.

Use that observed Project revision in the explicit refresh request below. If sources change again between preview and refresh, the exact expectation fails; preview is an observation, not permission to accept a different source subject.

{"jsonrpc":"2.0","id":"refresh","method":"workspace/refresh","params":{"image_revision":"sha256:<current-image-hex>","expected_new_project_revision":"sha256:<independently-observed-project-hex>"}}

Refresh has no path, source, manifest, policy, or force parameter. The caller supplies the current image digest and the independently observed new Project revision. The session loads the one host-bound manifest afresh, requires its canonical configuration to match the current session, checks the caller's new revision expectation, and independently derives the image. A manifest/profile, source-inventory, entry, or export-configuration change requires a new session.

Ordinary requests still authenticate the held current snapshot before preparing their result and afterward before retaining any mutation. Observed drift is absorbing for that snapshot; restoring old file text does not implicitly revive it. Refresh deliberately does not authenticate or revive that old snapshot: it creates and authenticates a new one. It fully prepares a bounded response and rechecks the fresh snapshot before replacing current session state. A rejected refresh leaves the old image, registries, and old snapshot's drift state intact. Malformed requests, unknown parameters, invalid IDs, notifications, and stale current-image expectations cannot trigger refresh.

Successful refresh retains complete immutable candidates and their exact historical bases. No intent is implicitly replayed onto the new source state. Call candidate/open after refresh to retain the current base, then explicitly candidate/rebase a historical candidate onto that new base. Historical candidate reports remain independently bound to their own subjects; the current image token is still required on requests. Source commit additionally requires a candidate based on the current held Project revision.

Every successful explicit refresh clears drafts and rejected attempts, including an unchanged-image refresh. It never silently remaps expression selections or repairs rejected intentions. The report lists retained candidate handles and exact cleared counts. An identical freshly derived image retains the old image Arc after byte equality checking, but the source snapshot is still replaced. The default constructor performs a complete cold Project load. The opt-in frontend constructor instead stages source-exact AST reuse through the same filesystem authentication and full semantic/link/profile rebuild. It adds an optional frontend_work report to preview/refresh only; failed preparation and preview do not install it. Neither route claims incremental semantic checking or warm cross-process compilation.

The payload schema semaprax.image-workspace-refresh.v1 contains old/new image and Project revisions, the new Workspace revision, image_arc_reused, sorted retained_candidates, cleared_drafts, cleared_attempts, manifest_changed:false, source_authority:false, and recovery:"explicit_fresh_snapshot", plus explicit nonclaims. Old image, facet, draft, and attempt handles cannot be mistaken for current ones.

Preparation, bounds, and publication

V5 reuses existing typed candidate preparers and the bounded registry: at most 16 complete candidates, 16 drafts, 16 attempts, and 256 MiB of accounted retained report bytes. Historical candidates occupy the same registry; refresh does not create an unbounded history. Hosts can explicitly discard historical candidates to make room for a new base. Registry accounting is not a complete HIR/RSS bound.

Ordinary handlers prepare payloads and mutations without modifying the registry, admit capacity, render the complete response, and perform final source authentication before committing a mutation. Response overflow discards the prepared mutation. The transport accepts at most 64 KiB per frame and produces at most 1 MiB per response, using the existing strict NDJSON framing/JSON-RPC codec. Oversized input ends the stream; notifications remain silent and do no semantic work. Query/report owners retain their own smaller limits.

with_git_commit_host attaches a fixed manifest-matching Git authority only before the first frame. approve_git_commit is a separate host API, never an RPC method. Approval also must precede the first frame; an active session cannot widen that temporal authorization boundary. The supported review workflow is to review/export a candidate first, then open a separate host-approved commit session and restore its exact source-backed capsule. Requests cannot self-approve or replace the fixed Git target, executable, repository, or commit metadata.

Commit preparation checks the current held source and candidate base before calling the dedicated Git publication authority. That authority owns independent replay, immutable objects, one expected-old ref pivot, and uncertain post-pivot diagnostics. A generic request wrapper does not reinterpret its post-publication failure as an ordinary failed preparation. Commit status and immutable receipt chunks remain inspectable after uncertain outcomes without asserting current source admission. They still require the session image expectation.

The final session boundary retains source authentication. If it fails after a terminal commit outcome, SPX-G287 explicitly preserves the host's published or publication_uncertain classification and includes the source diagnostics; it does not erase a known successful commit or advise blind retries. See the separate Git-publication and source-commit protocol specifications for authority and repository constraints.

serve_vnext retains final authentication failures as VNextSessionFailure inside io::Error. Embedding hosts can downcast error.get_ref() and copy its diagnostics() without flattening publication codes into a generic transport error. Stream read/write failures after a terminal Git outcome likewise preserve an explicit SPX-G287 published/uncertain classification. Final authentication still runs after stream failure, and its diagnostics are retained alongside the outcome and bounded I/O-kind description. An ordinary pre-publication stream failure keeps its original I/O error when final authentication succeeds.

Evidence and diagnostics

SPX-G280 rejects invalid host/session configuration; SPX-G281 covers refresh response capacity; SPX-G282 rejects stale image/new-source expectations or a wrong commit base; SPX-G283 rejects configuration changes or inconsistent unchanged image facts. Existing source, candidate, draft, diagnostic, test, target, and publication codes remain intact. Invalid JSON-RPC parameters and unavailable methods use the existing transport error codes.

tests/image_transport_v5/workspace.rs covers preview without state revival, absorbing-drift recovery, historical-candidate rebase, explicit transient invalidation, failed-refresh preservation, notification/parameter rejection, unchanged-image refresh, manifest-change refusal, selected capabilities, and v1/v2/v4 compatibility regressions. Existing v3 tests and separate v5 discovery, artifact, and commit tests own their domains. The implemented release corpus is HOSTED GREEN; the earlier skipped local authoring pass is historical.

The supported product workflow composes its own bounded review/publication sequence. Its existence does not complete every graph-operational requirement. Representative latency/memory benchmarks, exhaustive physical race coverage, cross-process warm reuse and broader workflow support remain separate goals, not pending execution of the already implemented v5 release gates.