Skip to main content

Wework Stand-in

After connecting to an enterprise Backend, first-use primary setup and personal/cloud-project role creation default to an available cloud or remote device, preferring its default flag, or to the local device when neither is usable. The form allows explicitly selecting local or another device; changes reuse the unsaved-edit confirmation. Existing configured local profiles remain selected on first open; an unsaved placeholder role does not count as configuration. Explicit cloud-device choices are remembered per enterprise Backend and account without moving existing profiles when a device goes offline. Inventory changes never silently move an editor already opened. Saving and conversations use the selected Executor’s existing Runtime channels. Standalone usage and local projects retain their execution flow. No plugin, provider configuration or host provisioning is added.

My stand-in retains access to profiles created locally before enterprise connection and offers to view them after connecting. A selected local role can be explicitly migrated to a cloud device. Confirmation transfers its name, instructions, model settings, tags, role memories and shared memories into a separate cloud role without overwriting existing target profiles. Conversations, active work, local directories and credentials stay local. Project/data-source grants and schedules require configuration on the target, which starts paused. Local intake pauses only after copying succeeds and its profile version remains unchanged. Local configuration, memories and history remain available; retries deduplicate matching imported memories. A primary profile migrates as a separate role rather than overwriting the target primary profile.

Role creation and Stand-in settings share the header, save actions, intake switch and connection entry, without a separate nested settings card. The primary profile has one Stand-in instructions field for responsibilities, background and preferences shared with scenario roles. Existing two-field content is consolidated without loss on save. Connections initially shows connected objects with their scope and handling summary; Add connection opens project, DingTalk or Calendar selection. Scope, exclusions, tags and handling policies live in the connection editor. Device, working directory and model remain visible in Execution environment. Switching devices loads that Executor’s independent profile and is blocked while edits are unsaved. Directory and model defaults apply to new work; existing conversations retain their environment. The Issue composer has no separate stand-in toggle; receive scopes are managed in My stand-in.

My stand-in is available as Beta without the experimental preference. The Tasks sidebar and collaboration project buttons carry a Beta badge; direct navigation and project indicators also remain available. Project coordinator conversations retain their experimental gate. The primary identity opens persistent chat; scenario roles retain work/chat navigation. The work list aggregates personal work, with optional role filtering. Work cards open original Runtime conversations, where questions and native approvals remain. There is no separate decision inbox. Settings preserve intake enablement, instructions, connections, device, model, workspace and independent role instructions. Connection timing lives inside Settings.

The project toolbar opens Project stand-in. It selects an already connected stand-in first, otherwise the first eligible personal stand-in. Existing instructions and automatic-handling status are shown read-only. For an enabled project, the primary action is exclusively Disable for this project. Saving disconnects every matching stand-in from this project, using exclusions for all-project sources. Global enablement, other projects and existing executions remain unchanged. For a disabled project, the primary action is exclusively Enable and use for this project, enabling the selected stand-in and connecting the project. The UI explains that enablement also applies to its other connected projects and only new assignments after enablement are handled. Role responsibilities and instructions remain unchanged. A separate link explicitly opens personal settings and explains their cross-project effect. Personal settings open in Tasks and preserve an explicitly saved execution device. A first connection enables only the current project rather than all projects.

Create a stand-in for this project creates a personally owned stand-in with the project name and a single-project connection, also visible in personal settings. Instructions are expanded; execution settings are collapsed. Secondary views stay scoped to the selected stand-in. A stand-in is an independent special agent: creation and editing do not select personal or project agents or request their catalogs. It uses its own instructions, model, device and connections without inheriting another agent’s prompt, skills, plugins or execution policy.

Instructions reuse the normal composer, skills, plugins and Goal mode. Device, model and code workspace live under More settings. Saving does not depend on cloud catalogs, project device bindings or model readiness; dispatch validates the current actor, Issue permission and the stand-in's device and model configuration.

Every edit, including the automatic handling toggle, takes effect only after Save. Prompt and execution changes merge into the current role through functional updates, so delayed composer callbacks cannot overwrite newer toggle, device or workspace values. Failed saves retain the draft; version conflicts cannot overwrite another editor. Clicking the drawer backdrop, closing, or pressing Escape requests dismissal. Unsaved changes open a centered confirmation dialog; Keep editing preserves the draft and drawer, while Discard closes it. Back from a secondary page discards that page's edits. Disabling stops new assignments while existing Runtime tasks continue.

A role can cover all participating collaboration projects, including future projects, with individual exclusions, or a selected project list. Optional tags narrow its scope. Settings are account-scoped in the selected Executor's SQLite database; devices remain independent. Settings belong to the Executor that stores them. After a desktop device identity change, reads and scheduling bind the document and its stand-ins to the current Executor, preserving instructions, scopes, versions and assignment cutoffs. Saves still reject settings addressed to another device. The frontend passes the selected Executor explicitly as the request target, without deriving routing from stored device fields, duplicating local-device or project-access validation, or rewriting device ownership in responses. The Executor validates ownership and permissions. Local projects are displayed only on their owning device.

One personal document owns stand-in configurations and versions. Legacy project configurations migrate transactionally into roles. Old personal and project agent references are removed. Before removing a project reference, migration intersects its former project boundary with the selected project scope and preserves exclusions, retaining effective grants, identity, versions and assignment cutoffs. Explicit models and source connections remain intact; an unspecified model follows the independent stand-in default. Project-addressed RPCs are projections over this document, with no duplicate project persistence.

Automatic project intake uses each project's connection time rather than the stand-in's activation time in other projects. Both personal and project settings transactions maintain Executor-owned projectBoundaries, keyed by project ID and storage type. Project projections expose that boundary as enabledAfter for local polling, cloud assignments and durable intake validation. Continuously connected projects retain their boundaries; new connections, reconnections, removed exclusions and re-enabled identities reset the affected scope. Ordinary settings edits preserve it. Reassigning an old Issue to the user after connection remains eligible. The existing CI stand-in checkpoint adds a user story covering historical assignments, new assignments, disconnected-period assignments, reassignment and duplicate prevention across later polling. Desktop, storage and Executor remain real; only model services are replaced.

Email E2E uses hash-pinned GreenMail 2.1.15 with Java 11+ (OpenJDK 21 in existing Linux CI), preserving exact IMAP APPEND timestamp assertions. Version 1.6.15 parsed noon protocol timestamps as midnight, shifting them by 12 hours. Upstream #1086 fixes that defect; do not work around it by changing business time filters or weakening assertions.

Connection timing and background coordination​

Projects, calendar and message sources share a header and a Processing section at the end of configuration. Process directly makes the programmatic Router create concrete work without background semantic assessment. Otherwise events enter background intake. New role connections default to direct processing; new primary connections default to background assessment. Saved policies remain unchanged. Project defaults apply to newly connected projects. Legacy global mode migrates only to connections lacking explicit timing, then is removed. Existing automatic and askBeforeAct policies remain intact; manual connections require an explicit Enable automatic handling action. Direct delegation remains immediate.

Events persist in the selected Executor’s SQLite without creating work or invoking a model. The bundled @wegent/dsh-coordination-runtime plugin interprets connection timing and runs the programmatic Router: each source and role has a fixed five-minute window from its first pending input. User delegation becomes eligible immediately; project assignments, messages and calendar events follow their saved processing policy. Urgent wording cannot override it. Verified replies return to their original work, preserving pending user questions and approvals. Only semantic decisions invoke the persistent primary Codex conversation. Empty intake does not invoke a model. Recovery combines accumulated events instead of replaying missed ticks.

Settings writes and dispatch serialize per user. Configuration changes cancel undispatched intents and invalidate stale batches; accepted assessment commands retain their original receipt and cannot be automatically replayed under another ID. Batch admission and dispatch revalidate current source, enablement cutoff, assignment, role scope and permission. Temporary cloud failures retain intake; explicit revocation cancels it. User questions and approvals remain in their original conversations and are never answered automatically. Failed or cancelled assessments require an explicit Check now action to reassess unfinished events. Unconfirmed execution links to the original task and blocks automatic replay. Status retains runtime.stand_in.processing.status, without global timing controls. The personal Router adds no Backend API.

Plugin and host transaction boundary​

Executor advertises runtime.coordination-v1. The plugin calls runtime.coordination.contexts, snapshot, commit, wake and status through the existing executor-runtime client. Host snapshots bind the current user, device, configuration, wake revision and event revisions. A plugin decision can select only snapshot facts.

The batch snapshot.works inventory contains metadata validated against current owner, role and source authority; it never eagerly loads conversations. Temporary history-read saturation cannot remove an existing responsibility. read_work supplies batch work metadata and original source messages, not proof that its conversation has been read. The coordinator uses the general bounded read_task API on demand for the matching original request and results, following page/content cursors and reading only work IDs in the current batch. Temporary busy errors remain recoverable reads, not missing work or justification for duplicate tasks. Continuation preserves the original task ID, read grants, approvals and result-return binding. One existing SQLite transaction commits all intents, state and the immutable receipt. Invalid or multiply consumed events, stale snapshots, changed configuration and another device are rejected. Replaying the same snapshot and plan returns its original receipt without another dispatch.

One upstream event ID may have multiple immutable versions. To read a selected version, pass its recordId from the read_work summary as messageId, then follow payloadOffset / nextOffset through the original event. An exact recordId takes precedence within the current work. An upstream id is accepted only when it identifies one record; shared IDs return an explicit ambiguity error rather than silently selecting an older version. Other works and revoked source connections remain unreadable. reply and send_email use the same exact record selection and retain current work-owner, role and source-authority checks before execution. External reply targets and idempotency keys continue to use the selected original record’s upstream ID.

Plugin CLI actions use one exact installed and enabled plugin from the native inventory. The Executor obtains its declared connectorSlug from the unique matching localAuth.tool.id; the plugin name cannot replace connector identity. Inventory errors, duplicate plugin names, missing or ambiguous tools reject execution without choosing an older cache, a different identity, or running extra login or health checks.

When native MCP approvals omit a tool name, the host correlates one unfinished native call in the same task, thread and turn using the exact server and complete JSON arguments. Only a unique match supplies tool and call identity for the preview. Missing or ambiguous matches remain unidentified; question text, titles and recency never establish identity. Live approvals and recovered conversations share the result without changing native approval, authorization or sending policy.

The Router has no separate database, model runner or permission system. Assessment instructions and routing rules belong to the plugin; Rust retains source eligibility, batch allowlists, role permissions, current-account checks and execution. Snapshot and commit both revalidate the background conversation lifecycle and cannot rotate an active or waiting batch. The old native business poller and immediate connection dispatch branches are removed; Automation scheduling and connection providers remain.

After automatic continuation is accepted, the native encrypted queue and stable command receipt own its complete input. The standInAutomatic marker rechecks human participation at dequeue, force-start, restart recovery and actual launch. Waiting requests retain their identity, while explicit user answers remain eligible. Native acceptance establishes reliable delivery, not model consumption or business completion. Interrupted recovery confirms acceptance only through the current batch's stable command receipt or exact message record; an older active execution does not prove acceptance of a new batch. A batch without acceptance evidence becomes failed and manually retryable, without automatic replay.

When MCP batch authority changes, Executor waits for the active execution to finish, releases the old subscription and confirms Native thread/closed before resuming the same conversation and recording its new authority. Unload, resume and configuration registration share the thread lifecycle lock so concurrent resumes cannot mix batches. The host owns idle retention; Native unload delay is zero to avoid a second stale MCP pool after subscription release. Batch validation remains mandatory. Unconfirmed unload stops recovery and exposes the original execution entry.

Scheduled work​

Settings → Connections → Add connection → Calendar is the single entry for arranging work; scheduled work is no longer a peer tab of the work list. Calendar records an event and its trigger time, reusing the existing Automation store, scheduler and execution history. The identity’s calendar.policy controls the whole calendar connection; taskRequest.standInCalendar identifies calendar entries. Entries inherit the connection policy. Due entries first produce durable personal intake; background mode does not automatically create an execution task. The calendar editor no longer exposes per-event processing overrides, goals, existing-task targets or independent execution settings. Work → Scheduled independently opens /automations, preserving task scheduling, execution environment, goals and continuation settings. Calendar is entered through stand-in connections. The taskRequest.standInCalendar marker separates their lists and editing without implicit conversion. Calendar saves independently and reuses the arrangement editor’s draft guard for returning and closing. Execution history links to the original work. taskRequest.standInOwner binds ownership. The current identity model and workspace resolve when due rather than copying credentials at creation. Older schedules remain in Scheduled; calendar lists contain only the current identity’s calendar events.

The primary chat can also list, record and cancel calendar events through the same connection policy, without selecting an execution conversation. Assessment and execution retain current-user, role and source boundaries, never automatically messaging coordinator or identity conversations. Pausing/deleting an identity or modifying/cancelling an arrangement invalidates prepared requests. Existing questions and confirmations remain intact. Busy work or unavailable capacity produces Needs attention rather than entering a stale delayed queue. Version checks distinguish the system claiming a one-time job from a later user cancellation. Unsaved arrangements inside settings also require discard confirmation.

Project coordinator conversations​

Private chat, automatic handling and Issue execution belong to the existing collaboration group leader. There is no separate coordinator identity. Read-only assessment follows that leader’s model and device policies while excluding private prompts, skills, plugins and memories. Queued starts recheck the leader configuration fingerprint; an unavailable fixed model fails instead of using a default.

The conversation entry exists on the project page. Collaboration groups supply leaders and members; a bare group has no independent project chat. Multiple groups are selected inside the project. Human-led groups direct users back to the project Issue.

Conversations retain existing member-private ownership and are explicitly labelled accordingly. Their key includes user, storage, project and group; devices persist independently. Every send and actual launch rechecks project access, the current leader and agent model/device policies. Project content is untrusted task data, never additional authority. Personal identities and project leaders reuse Runtime chat, execution preparation, memory panels and native approvals. Concrete work and follow-up questions remain in the original Issue.

Project memories use a fixed project_coordinator scope bound to project and storage, isolated by user. They never load personal preferences, personal memories or other projects’ memories. Work list returns to the current project board; Settings opens project group configuration.

Publish to project writes only the instruction or conclusion entered by the user to an existing comment on the selected Issue in the current project. It never copies private chat, memory or unsent drafts automatically. Publication refreshes the project and Issue to check current comment permission, project membership and archive state, while the existing comment API retains its write authorization. The panel preserves the original private conversation and draft, confirms navigation with unsent content and blocks duplicate pending submissions. Published content follows the original Issue's access policy; the private conversation remains separate.

The registered stand-in-profile CI group covers connection timing, durable intake, MCP dispatch, same-conversation follow-up, arrangements and project conversation/memory isolation. Only model services are replaced. Screenshots, logs and temporary verification files remain outside commits.

Connection and schedule regression stories​

Verification uses isolated Electron with real local Executor, SQLite, plugin registration and RPC; only model services are replaced. DingTalk external data uses protocol integration tests and test doubles without real accounts. This does not establish real DingTalk compatibility.

User storyPreconditions and actionsRequired result and recoveryCoverage
Opt into stand-insDisable experiments, then enable and open stand-insEntry visibility follows the preference; all roles are visible and selectable at the topapplication-menu, stand-in-identities
Install and connect sourcesOpen a source with missing dependencies, missing authorization and ready dependenciesInstall, authorization and selection stages are exclusive; declared tool and account identities are exact; failures retain recoverystand-in-plugin-bridge, connection protocol tests
Select batches or continuous allStart with all, filter and select multiple resources, save and reopenWildcard scope remains account- and kind-bound and includes newly accessible resources; batches preserve other accountsstand-in-plugin-bridge, stand_in_identity_contract
Configure connections consistentlyOpen projects, calendar and message sources; edit and returnShared headers and processing controls; one top-level back action; drafts retain leave protectionstand-in-profile-settings, stand-in-connections, component tests
Route direct processingUse role defaults, then disable and enable direct processingDirect processing bypasses semantic assessment while revalidating ownership and sources; background intake batches; user input and approvals remain protectedcoordination-runtime, coordination-arrangements, native protocol tests
Record timed calendar eventsSave connection policy, then create, edit and trigger an eventDue events enter durable intake using current owning identity settings; no per-event execution environment or processing overridestand-in-profile-settings, stand-in-plugin-bridge, native timer tests
Retain independent schedulesEnter Scheduled from sidebar or system menu, then reopen CalendarOriginal task scheduling controls remain; lists, editing and cancellation tools are isolated; older schedules are not implicitly convertedapplication-menu, stand-in-plugin-bridge

Each isolated case restores original profiles, removes its events and test plugins, and stops the app. Failure logs and screenshots remain available for root-cause analysis and are not committed.

Connection plugin sources​

Connections are supplied by DSH plugins. See the connection extension point for the shared host, Provider contract and default event handling.

Connection dependencies declare exact marketplace and plugin IDs through source and optional alternateSources. Resolution reuses an installed source first, choosing declaration order when several sources are installed. Disabled or incompatible installations still require explicit action; they are never enabled, upgraded, or replaced automatically. Tool calls carry the selected source's actual ID and version, and the Executor verifies that the connection plugin declared that source.

DingTalk supports both dingtalk@wegent and dingtalk@wework, preserving existing installations and account configuration without migration or reinstallation. Undeclared marketplaces do not participate in resolution.

Model catalog and execution references​

Stand-ins and ordinary tasks share the model picker, classification, sorting, and option rules. Cloud models use their original UnifiedModel catalog objects directly, without a round trip through execution models or changes to catalog names, labels, or config.ui. Native Executor catalogs require only one display adaptation and reuse the common Codex catalog helpers for provider metadata.

Display models and RunnerModelIdentity are stored separately. Display models serve the UI; execution references contain only the actual runtime, provider, model ID, and the cloud resource name, type, namespace, and owner. Saving submits only the execution reference, not model configurations or credentials. The public resource type means a public resource, not a public-network endpoint. Intranet, public-network, and overseas labels come from the original catalog; unmarked models are not automatically labeled public-network.

The native host's ModelConfigurationStore owns custom interfaces in model.yml. After Executor starts and before Core starts, and after reading, saving, or binding the configuration file, the host serially rebuilds the Executor's in-memory interface catalog. Stand-ins select a device-owned provider and local-model:<id> reference. Public catalogs and stand-in settings contain no endpoints, API keys, or complete execution configurations. Dispatch resolves the current configuration by full device model identity; disabling or deleting an interface rejects new executions instead of switching to a Codex subscription. Ordinary tasks and stand-ins share protocol conversion, and concrete work inherits the saved model reference. Persisted tasks contain no credentials; each actual turn, including restored, queued, and continued work, resolves the original task’s stable model identity against the current device configuration. Missing references and disabled models reject execution before an unauthenticated request is sent.

Desktop and mobile use the same complete model identity comparison, distinguishing same-name providers, namespaces, and owners. Option identifiers are independent of display names and preserve existing identifiers. Changing the device or runtime invalidates old catalog requests; unavailable saved models retain the recovery entry.

The existing CI stand-in-profile checkpoint group includes the original stand-in-profile-settings scenario and the new stand-in-model-catalog scenario. The latter compares ordinary and stand-in labels for real Backend intranet, public-network, and unmarked models sharing an upstream model ID, then validates persisted execution references. The runner and CI catalog validator share checkpoint-group expansion so registered scenarios cannot be left outside CI.

The same stand-in-model-catalog checkpoint loads the stand-in-model-interface extension while retaining the original scenario, Backend, and desktop lifecycle. It checks native model.yml interface selection, credential-free saved settings, and authenticated calls to the same model service from both the primary stand-in and its concrete work. It also restarts the app and continues the original work, verifying the same conversation and authenticated model calls. Existing model-service scenarios and assertions remain unchanged.

Multiple stand-ins handling work​

When a local collaboration manager assigns an Issue to a human through submit_workflow_plan, persist the Issue assignment history and its receipt in the same SQLite transaction, reusing the ordinary assignment path’s sync_assignment_receipt. The receipt uses the owning Issue assignment event ID, not the collaboration round member-work ID. Stand-in reception and human reads update separate timestamps that survive reopening the store. Reception does not complete the work or settle human delivery. A subsequent round assigned to the same human also creates a new assignment event and unacknowledged receipt; resubmitting the same round remains idempotent. This synchronization applies to new assignments; it does not fabricate missing historical receipts.

Sources, tags, handling policy and enable-time cutoffs determine eligible roles. Project assignments first pass native assignment validation, then follow the saved connection policy: direct processing dispatches natively, while other assignments enter background intake. Each connected matching role handles an assignment once, sharing the active-assignment check. Manual role delegation retains its existing entry. The coordination plugin collects ordinary source events, resolves ownership and reuses existing work.

Existing Runtime executions and bindings retain assignment, account, project and role provenance, including failed or archived work. Naming changes and repeated notifications never replay handled work. Assignments already bound before the upgrade are not dispatched again. A new assignment uses either native direct dispatch or background intake according to its connection policy, with assignment-and-role deduplication across both paths. Previously persisted assignment intake remains protected by assignment-and-role binding deduplication. With direct processing enabled, remote Executor devices can handle explicit assignments without a desktop DSH host; background intake still requires its plugin host to be online.

DingTalk collection runs on a 15-second interval. Connections to the same group or contact on the same account share one source query, then each enabled connected stand-in receives the messages. Distinct sources are queried sequentially with independent pagination, at most 100 messages per request; remaining pages are read on later rounds. Collection time can increase actual latency. Deduplication includes the account, stand-in, and source, so repeated messages do not replay and another stand-in's records do not suppress intake. Private chat sources support individual contacts or a continuous all-contacts scope, including contacts added later on the selected account. Automatic messages first become role-scoped source events; collection never creates work or invokes a model. The coordination Router later associates existing work or requests semantic decisions. Manual message organization retains its existing grouping and error-confirmation flow.

Cloud projects reuse assignment notifications already received by Wework instead of scanning projects or polling assignments every five seconds. The desktop notification entry uses the loaded inbox and online device list, deduplicates by account, device and notification, and calls the existing Runtime RPC on each relevant device. Each device checks enabled personal settings, the current user, project, assignment identity and tags before validating assignment status and the enable-time cutoff. Each dispatch reads assignments only once. Local projects retain scheduling against local storage without cloud project or assignment requests. Historical, unrelated, unassigned and already-bound work is excluded before ordinary task creation, binding, sessions and result views are reused. Reloading the desktop reprocesses the loaded inbox while existing Runtime tasks are reused without another assignments request or execution. Automatic handling requires receipt of an assignment notification; failures are logged instead of retrying on every inbox refresh. Before task creation, the original notification still offers Delegate for explicit manual recovery; an existing failed task retains Retry. Explicit settings saves reconsider loaded notifications for the updated device. Manual delegation works with automatic handling disabled, using the explicitly chosen stand-in or the first stand-in connected to the project when none is specified; no available connection returns an explicit error. Execution provenance records the owning stand-in. Cloud execution retains current Issue permission checks; local work remains functional offline. No new backend queue or distributed lock is introduced.

Rust automation commits assignment events and their current-assignment index under the same Issue lock and database transaction, sharing event reduction. Reassignment revokes every uncancelled previous root event so an older event for the same member cannot resurface. Reading a legacy v1 index rebuilds it once as v2 from authoritative events without changing assignment, notification, or Runtime identities. This prevents stale indexes from rejecting an active assignment as already handled or inactive. Database regressions exercise the real Rust writer, transaction rollback, and three schema variants. The desktop stand-in-assignment-notifications checkpoint restores a stale index and verifies manual delegation, automatic handling after reload, and execution deduplication.

Feedback in collaboration notifications​

Stand-in handling has no Issue board-status or completion-time restriction. Manual Delegate and automatic handling support in-review, completed, and other statuses. Manual delegation can first assign an unassigned Issue to the current user. Execution still validates the current user, project, active assignment, and execution permission, and reuses the existing task for the same assignment. Automatic handling retains project, tag, and enable-time filters.

Automatic notifications, local polling, and manual delegation share the handled-task decision and execution entry. Automatic events preserve existing executions without waking failed or archived tasks. Explicit delegation reuses the normal retry flow for failures; archived tasks first use normal task restoration and then execute another turn in the original session, preserving the assignment binding. Restoration or execution failures must return errors. After successful delegation, the notification reads the Runtime task and uses the execution list's shared state projection. Returning an existing task does not prove that a new turn is running, and completed tasks must not be optimistically labeled as running.

The immediate post-delegation snapshot is retained only until the notification source version changes. Versions reuse the existing turn and status identity rather than comparing start and completion timestamps that may have different precision. Inline follow-up waiting and result loading use the same version identity so a new turn completing within the same second can settle correctly. Source updates discard the immediate snapshot so completed work cannot remain displayed as running.

Deleting an execution preserves the original assignment's deduplication relationship, so automatic notifications and polling do not recreate the same assignment task. Once a deletion marker exists, the conversation must not be restored or reported as running, even while background cleanup is pending. Reassigning the Issue creates a new assignment and is treated as new work.

Collaboration notifications match stand-in tasks by project, Issue, and assignment identity. In addition to the current Runtime list, the read-only runtime.stand_in.assignment_tasks RPC batches exact notification assignment identities for the current account against each executor’s local records, including archived executions that have not been deleted. Handled notifications retain their real state after archival or reload instead of offering Delegate again. Reassignment creates a distinct identity; deleted records are excluded. Delegation stays hidden until lookup finishes; lookup failures display an error and recover when the inbox is refreshed. Online executors are read independently, so remote failures do not discard confirmed local results. Lookup neither restores conversations nor executes models, and does not depend on successful cloud receipt writes. The stand-in icon defaults to 28px, with a 16px project-sidebar variant. The primary person and double reuse identical outlines, with a slightly smaller primary person. When disabled, the double tucks into a thick shadow along the person’s right side. Enabling unfolds it toward the upper right over about 560ms. The double has no violet coloring, hatching or facial features. Disabling reverses the movement into the thick right-hand shadow. A project-sidebar icon appears only while the current user has at least one enabled stand-in for that project. Projects without an enabled stand-in have no icon; disabling every matching stand-in removes it without affecting other projects. Reduced-motion mode displays the final state immediately. Cropped lower bodies emphasize the two heads and shadow identity. Colors invert with the theme on dark backgrounds. The original assignment notification shows the stand-in icon and working, waiting, finished, or failed state. Local and manually started stand-ins without an assignment notification also appear here. Clicking the task title opens the existing execution conversation without dispatching another task.

Notifications show the source, event and time, task content, and lightweight actions without an extra “New task” heading. New notifications snapshot the actual assigning user or manager agent name at creation; inbox reads do not query related records. Entries without a name omit assigner information and show the task title and time directly, without placeholder copy. Stand-in handling updates the identity and state in the same entry.

The inline handling area accepts follow-up instructions, answers real Runtime questions, and retries failed stand-in tasks. Ordinary follow-up input expands after clicking Reply; pending questions appear directly. Replies continue the same conversation. A rejected send keeps the draft and displays the error. Question options and request identifiers come from the conversation, never from interpreting result text.

Completion, failure, and pending input make the entry unread again and update its position. Desktop alerts respect collaboration notification preferences and are suppressed while that execution is visible. The desktop frontend owns this projection, using the read-only Executor RPC above for archived execution identities; no Backend API is added.

Stand-in read markers and desktop delivery receipts are account-scoped on the current device and do not sync between devices. Original assignment notifications retain the existing read API. Each auxiliary collection retains at most 1000 entries for 90 days and is pruned on reads and writes. Cleanup never deletes real notifications, tasks, or execution history.

Completion events use the Runtime turn ID when available; tasks without a turn ID retain their existing status-and-timestamp identity. With a turn ID, receiving a turn settlement and its task summary separately does not repeat an alert or make an already-read result unread. Existing timestamp markers are upgraded when they match the current state. Restored settlements from before account monitoring began establish a delivery baseline and retain their inbox entries and unread state without replaying historical desktop alerts. Tasks that finish after monitoring starts still notify, including tasks that finish before their first summary is discovered.

Focused tests cover durable versioned settings, independent tag rules, assignment age, existing binding filtering, device switching, and sidebar configuration merging and updates. The stand-in-assignment-notifications checkpoint verifies that two eligible stand-ins bind separate tasks for one real cloud assignment, share assignment validation, and remain independently deduplicated after inbox refresh. The stand-in checkpoint covers local fan-out, renaming, memory scope names, and outside-click drawer confirmation. These checkpoints and stand-in-workspace, stand-in-cloud, stand-in-connections, and stand-in-notifications run in existing CI. Only model responses are replaced; storage, task execution, cloud APIs, and device connections use real implementations.

Verification​

Use isolated Electron, project and Executor fixtures; cloud checkpoints use real backend APIs and connections. Only model responses are substituted. Keep screenshot evidence outside the repository and record actual results in the PR.

The stand-in-project-enable desktop checkpoint creates two local projects, verifies both sidebar icons are absent, enables a stand-in connected to both projects, then disables it for one project. Both icons must appear after enablement; only the disconnected project's icon must disappear after disabling.

Cover the status/history overview and secondary settings, default selection of an existing stand-in, personally owned project creation, explicit global settings navigation and return, draft retention across plugin navigation, draft cancellation, save conflicts and recovery, all-project connection with exclusions and future projects, adding roles, independent executions for every eligible stand-in, per-stand-in deduplication, centered unsaved-change confirmation on drawer dismissal, assignment filtering, deduplication and legacy migration without expanding authority.

Persistent conversations and long-term memory​

The primary stand-in keeps a persistent chat entry while individual work items retain separate Runtime tasks. Local Codex reuses thread resume and automatic compaction without timed thread rotation. The composer keeps model selection and hides execution controls such as context compaction, permissions, and planning.

Each primary turn refreshes its orchestration contract: discover task tools, inspect existing work, create or continue an independent task with the complete requirements, sources, deliverables and authorization limits, then read actual results before reporting. This also applies to direct turns on loaded threads; concrete tasks and scenario roles do not receive this primary-only restriction. Configuration proposals remain in the identity conversation. propose_profile declares required settings fields, project reference objects, and independent automatic-processing, action-confirmation and timing policies. New roles preserve existing roles, and proposals are saved only after native confirmation. The identity conversation also creates or cancels schedules directly; concrete workers prepare reports and perform each execution without receiving identity configuration tools.

When configuration blocks a current explicit business request, a proposal may set continueCurrentRequest. The host binds the actual identity conversation and an independent owner-request identifier, rather than accepting model-supplied actor ownership. The returned willContinueCurrentRequest reports whether that binding was established. Acceptance atomically saves settings and a pending continuation, then idempotently wakes the original conversation through the existing durable queue. Background results do not replace the owner request. A new owner message or cancellation invalidates the old continuation, including while queued. Ordinary settings edits do not generate business reminders. Continuations reread current settings, never elevate existing worker permissions, and preserve external-operation approvals.

Independent stand_in_memory records live in the selected Executor's SQLite database, scoped to the person, a role, a collaboration project, or a DingTalk connection. They are separate from Codex threads, responsibilities, and connection permissions. Records retain their source task, timestamps, and version; edits and deletion require the current version. Devices keep independent memories.

Before every execution, including follow-ups, queued turns, and restored executions, the Executor reloads current responsibilities, preferences, and applicable memories through one additionalContext source. Injection is limited to 20 records and 12KB; identity-bound search_memories provides further retrieval. Identity chats receive personal and their own role memories. External work receives only memories for its exact source, without private preferences or personal/role memories. The primary stand-in can query all records when managing memory. Stand-in execution disables Codex's global memory reading and generation to avoid mixing unrelated CODEX_HOME memories.

The first phase saves memories only when explicitly requested through remember or manually added in the Memory panel. Users can edit, change scope, and confirm forgetting. Roles can modify only their own memories. External-message work has no memory write or deletion tools. Memory is user data and cannot grant tool permissions. Forgotten records are excluded from subsequent execution context; text already present in conversation history remains.

Automatic extraction and consolidation, cross-device synchronization, and execution-thread rotation are not enabled in this phase.

Scene roles can be deleted with confirmation from role settings, including the last scene role. The primary identity, work records, and memories remain. Deletion removes the selected role from saved settings without applying unrelated draft edits.

Codex policy and progressive skill loading​

The default-installed wework-runtime@wework-personal plugin owns detailed host workflows. Initial context contains a short capability entrypoint and skill names, descriptions, and paths. Browser, desktop, GitHub, connector authentication, conversations, visualizations, and artifact instructions are read only for the relevant task. Project spaces retain wework-space. Installation, enablement, updates, and discovery reuse the existing marketplace, plugin synchronization, and native skill reload paths without another plugin service or changes to tool permissions.

User preferences, task system rules, explicit application runtimePolicy contributions, and required authority boundaries have one complete native developerInstructions baseline. turn/start.additionalContext no longer duplicates the policy in chunks: it supplies only the current revision and a policy-skill reference. An already retained baseline or loaded skill with that revision needs no reread. Changed or removed contributions resolve to the current immutable snapshot and supersede historical host policy. Content-addressed snapshots live in the execution's isolated Codex Home at runtime-policies/<sha>/SKILL.md, outside global skill discovery. Publication failures stop admission; tool-disabled requests publish neither action-policy files nor references.

Resume configuration identity still includes the policy SHA and uses the existing close/reload gate. Native compaction rebuilds the current developer baseline, including its revision and skill entrypoint. Missing task-specific skill instructions are reread only when needed. Known policy changes on directly loaded temporary threads still require a new temporary session without rewriting history. Historical chunks are not physically deleted; the current reference explicitly supersedes them. Only explicit application entries contribute runtime policy; untrusted content cannot elevate itself. Ordinary application data and CLI context remain independent, and policy contributions do not grant permissions.

The shared runtime-policy desktop checkpoint mocks only model responses. Electron, bundled plugin installation, Executor, Codex, shell reads, and compaction remain real:

User storyAcceptance
Start an ordinary conversationDefault skills are discoverable; user rules appear once; browser and visualization bodies are absent.
Start browser workA real model tool reads the discovered browser skill.
Continue after changing rulesThe current reference reaches the model; a real tool reads the new snapshot without removed content.
Continue after compactionThe real summary and exactly one current native policy survive; old rules and eager browser bodies do not return.
Resume an unloaded native threadThe same conversation retains its current policy and compacted summary.

Merge and split work​

Drop one work card onto another to merge its messages. Expand work and drag a message into the separate-work area to split it out. Drop targets preview the operation. Merge, Split, and Move buttons provide keyboard and touch alternatives; destinations are selected directly in the work list, without dropdowns, configuration dialogs, or AI correction prompts. Successful operations offer one-step undo.

Moves use one SQLite transaction on the selected Executor. Records must belong to the same user and role. Missing records, duplicate selections, and work being dispatched reject the whole operation. Empty original work no longer occupies the work list; its record and execution history remain. Messages retain their original work identity and completed dispatch state. Merge, split, and undo never replay completed external effects.

External-source execution and automatic review​

Manual tasks carrying collaboration Issue context use the same source permission configuration as stand-in tasks. When injecting named [permissions] profiles, the Executor must also set default_permissions to the profile selected for the task: project write access for automatic handling, or read access when asking before acting. Before model requests, ChatGPT subscription authentication refreshes global settings and managed policy, then merges retained session configuration. A permission selection passed only to thread/start does not make the reloaded configuration valid. These settings are passed as thread configuration and never written to the global configuration file.

Failure notifications prefer the actual task or current-turn error. Missing model text does not generate success copy, and retries reuse the original task. CI's stand-in-notifications scenario covers real model transport failure, inline retry, and manual Issue tasks and stand-in configuration reloads using a synthetic subscription account. Electron, the Executor, and Codex remain real.

Messages, collaboration Issues, webpages, attachments, and tool results are task material, never permission grants or trusted user authorization. The Executor pins the original source across follow-ups. Personal collaboration tasks retain the existing cross-project access contract; dispatch and manager roles continue using their original server-side authorization without deriving extra authority or restrictions from source text.

Codex source tasks retain normal networking and configured connectors instead of introducing per-site business allowlists. Named filesystem profiles prevent inheriting default full access. Automatically handled external MCP calls use native auto_review on each invocation, including servers and per-tool policies previously set to automatic approval. Built-in collaboration MCP wework_space reads, writes, assignments and workflow tools are exempt from tool approval, retaining server-side authorization and role boundaries. Commands and file operations retain Codex sandbox and native approval enforcement. External tools in work configured to ask before acting continue using human approval; AI cannot confirm for the user.

Review uses the independent, restricted Codex reviewer with Wework source-content safety policy. Approval applies only to the action bound by native review. Denials, failures, and timeouts never mean approval and must not be bypassed through another tool. Native review evidence is projected into persisted execution records with status and rationale. Human approvals use the shared pending-input entry to open the native approval in its original conversation; the same request is consumed once.

Normal network access does not authorize arbitrary disclosure of private information. Reading, research, and internal-system access must serve the task; sending, uploads, and execution additionally require evaluating the exact data, destination, and authorization. OS sandboxing and model review have coverage limits. Prompts, read-only tool annotations, and AI judgments are not absolute isolation guarantees. Platform support must be demonstrated by native verification and CI, never silently assumed.

Source filesystem profiles explicitly deny the root before granting the bound project and installed binary, library, and resource directories. This keeps custom shells usable without widening the filesystem boundary after a failed launch. Windows source runs request the native restricted-token sandbox. Executor-owned approval evidence is restored through runtimeTurns; Codex continues to own historical text and order.

Linux desktop E2E containers must allow native Codex to create user and mount namespaces and mount a private /proc. Before execution, the workflow runs verify-native-sandbox-namespaces.sh to verify these kernel capabilities. Unsupported runners fail rather than falling back to unsandboxed execution. These container options apply only to disposable CI runners; product root-deny rules and source-permission assertions remain unchanged.

Runtime command receipts​

Executors advertising runtime.command-receipts-v1 accept an explicit commandId on runtime.tasks.create and runtime.tasks.send. Repeating the same command and input within a task returns its original acceptance receipt. Reusing the ID with different input or execution identity returns command_conflict. Receipt queries and replays both check ownership and, when connected to the backend, the current account. Legacy calls without commandId do not receive this idempotency guarantee.

Query runtime.tasks.commands.get with { taskId, commandId, userId }. accepted means the Runtime durably received the input; it does not mean the model read it or the business work finished. States distinguish queued, dispatching, started, settled, awaiting_user, failed, cancelled, and recovery_required. awaiting_user records that this command stopped for the user's answer or approval; a later answer is a separate command and never rewrites the original receipt as successful.

Pending requests, command identity, and queue changes share the existing encrypted Runtime queue commit. Transcript visibility is not an acceptance ledger. Business events, assessment snapshots, and business actions retain their existing stand-in storage and are distinct from Runtime delivery receipts. Confirmed terminal commands discard launch credentials and the complete request, retaining receipt identity and native associations.

After restart, recovery checks the exact native thread and turn for a real timeline completion boundary. thread/turns/list can synthesize interrupted; that status alone cannot prove cancellation. Unconfirmed execution returns recovery_required, retains the request for inspection in the original work, and never resends automatically. Autonomous Goal recovery does not resubmit its original user command. Actual execution outcomes and generation checks determine settlement; late callbacks cannot settle a later command.

When a native outcome remains unknown and no runner is active, the device owner can explicitly review and abandon that uncertain execution. Read runtime.tasks.commands.get for the current commandFingerprint, exact native tuple and acceptance time, then call runtime.tasks.commands.resolve with { taskId, commandId, userId, expectedFingerprint, expectedNative, decision: "abandon", requestId }. userId is only a selector. The same controlled device-write transport as stopping a task applies, together with fresh connected-account and original command/current task owner/device checks. Missing device ownership, an active execution or a changed fingerprint/native binding fails closed. An explicit native notLoaded status proves no loaded runner, never historical turn completion. Only this owner-disposition flow uses that fact, with no local active, queued or preparing work, active Goal or known pending transition. Unknown native status remains unavailable; stop and historical completion predicates retain their original semantics.

The stored native command state remains recovery_required; the owner disposition is persisted separately and projected as abandoned in public receipts. Older readers ignore the optional disposition and still reject replay of the uncertain command. An abandoned receipt retains nativeOutcome: "unknown", the original command/thread/turn and the owner's decision. It never claims completion, native cancellation or successful external delivery. The same requestId reads the original decision idempotently; the original commandId can never replay. The decision is persisted atomically with the encrypted command queue. The coordinator consumes only that durable receipt, marks the exact old assessment as owner-abandoned and clears its recovery gate in one transaction. Existing actions and receipts remain intact; pending events enter subsequent batches. If the UI's following processing check is interrupted, restart consumes the durable receipt without resolving again or resending the old command.

New coordination callers must check the capability and must not fall back to sending without command IDs. Acceptance receipts never replace source, role, project authorization, or native operation confirmation, and cannot answer or approve requests for the user.

Durable arrangements​

Stand-in-owned arrangements retain the existing Automation store as the schedule and run source of truth. Due runs freeze their owner, role, configuration version and target task. The bundled coordination plugin discovers them through an arrangements:<user> context and routes typed schedule_due events directly, independently of a busy semantic coordinator. Callers require runtime.coordination-arrangements-v1 in addition to coordination and receipt capabilities.

The existing SQLite transaction records a routing intent and immutable routing receipt; the encrypted Executor command journal records acceptance of arrangement-run:<run-id>. Recovery always checks that exact command before preparing another input. A crash after writing a due run, routing intent, or accepted command can therefore resume without duplicating execution. Pending or running runs survive history pruning. Owned recurring arrangements catch up one missed occurrence, then resume their normal schedule.

Changed, paused or cancelled arrangements cannot start a new command. Queued commands recheck their current identity, arrangement version and original work's native questions and approvals before launch. An accepted command's original receipt remains authoritative even if the arrangement is later edited or deleted. Waiting or uncertain commands require attention in the original work and are never resent automatically. Legacy owned runs without a durable receipt require review instead of automatic replay. Unowned legacy automations retain their existing runner.

Calendar due runs use the existing per-automation history budget of 100 as their active queue limit. At capacity, existing pending/running runs and the next due time remain intact; collection resumes when a slot is released. A failed calendar enqueue marks only that run as needing attention and does not block other calendars.

First-use feature choices and recurring reviews​

runtime.stand_in.onboarding.get/complete reads and submits feature choices for the current account on the selected Executor. Reads require no model, cloud catalog or execution preparation. The two-step introduction reuses StandInConnectionSettings for app authorization and scope editing. Continue remains available without connections. Final confirmation saves personal settings and enables the primary identity before recording completion. Failed saves retain drafts; retrying completion does not resubmit already saved settings. Closing protects unsaved connection drafts. No arrangement is created. The question-mark examples retain their equivalent buttons without inline scheduling. Weekly reviews are scheduled through the conversation after scope and time confirmation, preserving paused identities and calendar policy.

Onboarding and the calendar share the Executor's weekly_review template, defaulting to Monday 09:00 in Asia/Shanghai. Deleting an arrangement retains the completion record, preventing recreation on repeat submissions. Users may explicitly add it again through the primary calendar template.

The question-mark examples modal offers daily briefings, meeting preparation, project follow-up, DingTalk mention replies and weekly work reviews. Choosing an example selects the primary conversation and appends the business request to its editable draft without sending, replacing existing notes or creating schedules. A single-person icon distinguishes the primary identity from scenario roles; the selected identity has an inverse-neutral background and checkmark. Conversation surfaces use the light theme's white background, and processing notices use a bounded bar.

The host injects source discovery instructions into system prompts, including continuations of existing identity conversations, rather than user drafts. The AI inspects the profile and provider catalog, then attempts discovery using connect_source, or list_projects for projects. The tool returns actual provider status, declared authorization identity or secure account setup requirements. It never collects passwords, expands scope or claims message access merely because a provider is available. Subscription changes require propose_profile confirmation; sign-in uses native authorization. Missing inputs block aggregation until connected and confirmed, rather than producing fabricated summaries or unusable tasks.

Identity conversations restored with an earlier desktop device identifier are rebound to the current host only after their persisted task ID, owner and role match. Owner and role stay unchanged. Ordinary tasks, external work and background batches retain their existing boundaries and task tools retain all permission checks.

Review executions reuse the general read-only list_tasks and read_task tools instead of a review-specific batch reader. The existing run binding verifies account, local device, actor task, current arrangement version and run state, fixing the scope to the seven days before that run. Explicit out-of-window time bounds are rejected. Every task page, message page and content chunk revalidates access. Follow nextCursor, beforeCursor, afterCursor and messageContentCursor for the required evidence. Complete message content does not imply complete history; sourceContentMayBeIncomplete denotes actual source incompleteness. Prior reports use ordinary conversation reads and are not independent evidence. This identity cannot continue other tasks, create delegates, configure settings, write memories or send externally. Native permissions and approvals remain unchanged, and history grants no authority. Results return to the original primary conversation, with material evidence gaps explained in business terms.

Personal stand-ins and scenario roles use the general list_tasks and read_task tools to read permitted conversations belonging to the current account, including identity conversations and ordinary tasks. Lists and native transcripts support pagination and optional time bounds. List entries distinguish kind and canContinue: reading identity evidence does not authorize dispatching work to it. Direct primary-delegated workers inherit these two read-only tools by default. Explicit readSources selected at creation additionally grants only the chosen concrete source catalog and reads, without configuration, orchestration, scheduling, memory writes or external actions. Every read revalidates the persisted owner, device, existing role and delegation source. Pausing new-work intake does not revoke reads of existing conversations. Source tasks can read only associated conversations in the same role and exact currently connected scope; removing the connection denies subsequent reads. Other accounts, unknown owners, deleted or ephemeral tasks and private coordinators are excluded. Project coordinators receive no personal history. History never grants execution authority.

User stories and acceptance coverage​

User storyAcceptance behaviorAutomated coverage
Connect apps on first useContinue with or without apps; confirm before saving connections and enabling the primary identity; create no scheduleComponent tests and the existing stand-in-profile-settings desktop checkpoint
Protect connection draftsClosing saves nothing; returning preserves selected scope; discarding is explicitDesktop draft checks and component navigation tests
Recover from concurrent editsA real version conflict keeps setup incomplete; reload and confirm without overwriting the other editSame desktop checkpoint and component failure tests
Connect apps laterEnable the stand-in without apps, then add a connection through existing settingsSame desktop checkpoint
Adjust the scheduleSave a custom Monday time and inspect the calendar entryCalendar template editor tests
Stop reviewsPause or delete without restoration on repeated completion or restartDesktop operations, Automation reload and concurrency tests
Restart reviews and read resultsAdd the calendar template and open the report in its original work conversationThe same desktop checkpoint with real Executor, native MCP and transcripts; only model responses are simulated
Trust evidence boundariesPaginate over 100 tasks and 50 messages, fix the seven-day window, reject other accounts, roles and forged runsExecutor native protocol pagination and permission tests, plus desktop history reads
Use different themes and window sizesNo horizontal overflow; legible light/dark states; keyboard selection; no duplicate pending submissionsDesktop captures/geometry checks and component pending/failure recovery tests

Review coverage composes with the existing profile checkpoint, retaining every original assertion and sharing its build, startup and model protocol fixtures. No separate CI job is added. Screenshots and logs stay in test artifacts rather than repository commits.