diff --git a/docs/architecture/chain-map-session-recovery.md b/docs/architecture/chain-map-session-recovery.md index c0d236c2..7faca044 100644 --- a/docs/architecture/chain-map-session-recovery.md +++ b/docs/architecture/chain-map-session-recovery.md @@ -86,6 +86,21 @@ App side: └─ TaskThread lifecycleStatus → ready ``` +### S4a: Agent fails before producing output + +``` +OpenClaw agent_end(success=false, runId, error) + └─ openclaw-multi-session-plugins persists xworkmate.taskRuns[runId] + └─ App polls xworkmate.tasks.get + └─ Native detached-task record absent + └─ Plugin returns durable status=failed + sanitized error + └─ Bridge preserves terminal failure (no artifact wait) + └─ App clears pending and shows the model/provider error + +expectedArtifactDirs remain scan hints. An empty reports/ or artifacts/ +directory cannot convert this terminal failure back to running. +``` + ### S5: App resend on OpenClaw lane busy ``` @@ -165,7 +180,7 @@ No persistence: | Method | Params | Returns | |--------|--------|---------| -| `xworkmate.tasks.get` | appThreadKey, openclawSessionKey, runId/taskId | Native task-registry snapshot or structured lookup error | +| `xworkmate.tasks.get` | appThreadKey, openclawSessionKey, runId/taskId | Native task snapshot, durable agent_end run snapshot, or structured lookup error | | `xworkmate.tasks.cancel` | appThreadKey, openclawSessionKey, runId/taskId | Cancel confirmation | | Removed: Bridge task reassociation | artifactScope/runId-derived taskHandle | No longer supported; route through native task registry | @@ -207,4 +222,4 @@ resolveGatewayThreadConnectionState(thread) 4. **R4: Polling parameters**: Hardcoded poll interval/retry values in `ExternalCodeAgentAcpDesktopTransport` need to align with bridge's task deadlines (10/30/60 min). If polling stops before deadline, app marks failed while task is still running. -5. **R5: OpenClaw handle expiration**: The bridge's `OpenClawTaskRecord` has no persistent storage. If the app stores a runId and later queries it after bridge restart, the lookup fails silently. +5. **R5: OpenClaw handle expiration**: The bridge's in-memory `OpenClawTaskRecord` is not authoritative after restart. The plugin's SessionEntry-backed agent_end record preserves known terminal states; runs that ended before this record was written still fall back to the bounded deadline path. diff --git a/docs/architecture/chain-map-task-execution.md b/docs/architecture/chain-map-task-execution.md index 8a9e6949..bfb9a101 100644 --- a/docs/architecture/chain-map-task-execution.md +++ b/docs/architecture/chain-map-task-execution.md @@ -135,6 +135,11 @@ openclaw-multi-session-plugins │ └─ ["openclaw-multi-session-plugins"]["xworkmate.sessionMapping"] └─ Fail closed on appThreadKey/openclawSessionKey conflicts + Durable run terminal state + ├─ session.prepare records xworkmate.taskRuns[runId] = running + ├─ agent_end records completed/failed + sanitized error in SessionEntry.pluginExtensions + └─ xworkmate.tasks.get uses this record when chat.send has no native detached-task record + prepareXWorkmateArtifacts() ├─ resolveWorkspaceDir() → workspace root ├─ safeScopeSegment(openclawSessionKey) → sanitize @@ -201,9 +206,13 @@ now copied into tasks///artifacts/ before export. Bridge forwards typed lookup to the plugin/native task-registry. The request uses the persisted association: {appThreadKey, openclawSessionKey, runId/taskId} - Terminal state comes from native task records only. Missing native records - return structured errors such as no_native_task_record instead of inferring - success from artifacts or reconstructing a Bridge task dictionary. + Terminal state comes from native task records first, then from the plugin's + durable agent_end run record. Missing both returns structured errors such as + no_native_task_record instead of inferring success from artifacts. + + expectedArtifactDirs only drive workspace-root discovery. They never keep a + terminal run in syncing-artifacts. Only explicit export flags or + requiredArtifactExtensions are blocking delivery contracts. Back to xworkmate-app: ExternalCodeAgentAcpDesktopTransport @@ -264,3 +273,4 @@ etc.), not by extending the task execution lifecycle. 5. **F5: Bridge restart** — In-memory sessions lost → app must detect and recover 6. **F6: Artifact ref key rotation** — Secret change invalidates all signed refs 7. **F7: SSE stream interruption** — Recovery polling must align with bridge task deadlines and must apply terminal snapshots immediately +8. **F8: chat.send is not a detached task** — agent_end state must remain queryable by runId even when the native task registry has no record