Operator-local presentation candidate
The bounded contract exposes presentation.catalog.show,
presentation.workspace-directory.show, presentation.project-list.show and
presentation.session-list.show.
The operator-local portfolio is wired
through SDK, Node, CLI, client-core and an authored client renderer. This does not
establish user/device authority, release qualification or full R9a acceptance.
The catalog request is exactly {}. The directory request contains the exact
catalogVersion: "maia.presentation.portfolio/v3" and the catalog's exact
catalogDigest, a protocol viewId, integer
generation from 0 through 2,147,483,647, and the existing container.list page
parameters (limit 1–100 and optional opaque cursor). These identities correlate
client delivery; they do not authenticate a user or grant resource access.
This version is the only supported component profile. The digest is SHA-256 of
the catalog response's ordered actions, authority, catalogVersion,
components, method and releaseQualified fields, serialized as compact JSON.
It identifies that static manifest, not renderer code or an authorization proof.
A component-contract change requires a version change. Missing or mismatched
version/digest is rejected, not silently downgraded.
The result separates the existing container resource page from a flat renderer
specification. WorkspaceDirectory has empty props and ordered children;
WorkspaceReference contains an exact container ID and revision, never its name,
status, authority, URL, proof or SDK method. The graph has one root, at most 100
leaf references, no orphans, cycles or duplicate references, and exact ordered
resource correspondence. The complete result is bounded to 128 KiB. Excess fields,
unknown versions/types, expressions, state, actions, visibility and repetition
fail closed. Failures do not substitute an invented empty directory.
The Node candidate requires the already authenticated operator context and rejects any Invocation attachment before identity or data access. It composes the existing container reader, not a new store. It preserves the existing Node instance ID; there is no new epoch, home Session, policy revision or principal registration. All four methods are human-only, non-receipted reads. Existing wire payloads remain unchanged; no compatibility dashboard or data migration is introduced.
The Project-list request uses the same catalog/view/generation binding and the
existing container.show page parameters, including an exact containerId.
Its result retains the full container and Project summaries. The ProjectList
root binds the container ID and revision; ordered ProjectReference leaves bind
Project IDs and revisions. Graph/resource, duplicate-ID, byte and field checks
are equally strict. membershipCursor, when present, is the input page cursor,
not resources.nextCursor; Session navigation revalidates that exact membership
cursor and both resource revisions before and after its reads. Authored Session-list
membership verification reads the bounded maximum 100-Project window from that
cursor, so selections from every legal Project page size remain valid. The target
is a current membership claim, not proof that a particular page size was viewed.
The Session-list request binds exact container and Project IDs/revisions and the
used membership cursor in target. Its distinct page uses existing
session.list parameters: Project ID, numeric afterCursor and limit, without
the states and attention filters. Node
checks that membership before and after reading Sessions. The SessionList
root binds both resource revisions; SessionReference leaves bind exact Session
IDs/revisions. Foreign Project Sessions and graph/resource mismatches fail closed.
Session detail keeps its existing membership-checked read path.
observations carries each listed Session's live runtime from the same
session.observe projection, index-aligned with resources.items: runtime
kind, health (idle, working, stalled), the running turn and its elapsed
time, activity and process usage. A Session without a live runtime carries only
its ID. The spec never carries this state; a renderer reads it from the
resources beside the exact reference.
The portfolio v3 catalog adds Session runtime observations and replaces v2, v1 and the earlier directory-only catalog without a fallback or dual compatibility path. Update Node, SDK and the native renderer as one candidate; old catalog versions fail closed.
The ordinary control dispatcher routes these operations before Invocation identity
or data access. SDK response checks capture the original validated request rather
than retaining caller-mutable correlation fields. CLI source exposes
presentation catalog show, presentation workspace-directory show --input-stdin,
presentation project-list show --input-stdin and
presentation session-list show --input-stdin through public
SDK methods; source fixtures cover strict admission and unchanged result data.
A disposable real built Node/CLI fixture covers catalog negotiation, empty and populated pages, cursor delivery, bad digest and credential rejection, and cleanup. This does not qualify the renderer or another principal/client profile.
The client-core Effect view owns bounded reads, cancellation, generation/revision fencing and disposal, shared by the three real list profiles. Each renderer admits only its two authored components, with no standard registry or generated actions. Regression tests cover revocation during loading and late render-fault callbacks from disposed mounts. Exported Chromium/WebKit journeys and a bounded agent-operated native directory journey passed for the earlier directory artifact. They do not qualify the revised portfolio catalog or Project-list candidate. Current Project-list native and independent acceptance evidence remains pending; no human or release qualification is implied.
Publication must be checked against a coherent isolated tree; dirty-worktree evidence alone is not clean-checkout acceptance. Snapshot paging is not a patch stream, a multi-user authorization contract or a performance-isolation claim.
Imported from Maia OS docs at a2175bb