# CLI Subagent Transcript Fix Runbook

Date: 2026-03-05 (UTC)
Owner: Pipo

## 1) What was broken

Symptoms observed in production:

- `subagents list` showed runs as `done` / `timeout`, but `sessions_history` returned `messages: []`.
- Some runs showed inconsistent timing metadata (including previously reported negative-style runtime anomalies).
- Manual `chat.inject` to the same `sessionKey` worked, proving transcript infra itself was functional.

## 2) Why this can break again after updates

The fix was applied to **compiled dist bundles** under:

- `/usr/lib/node_modules/openclaw/dist/*.js`

OpenClaw updates (`npm update`, package reinstall, `update.run`, etc.) can:

1. replace these files entirely,
2. change hash-based filenames,
3. regenerate code structure (so exact patch anchors move).

So: the fix is durable **until the next package rebuild/update**, then it may be overwritten.

## 3) Final applied fix (working)

### A) Transcript persistence at delivery stage (critical)

Patched `deliverAgentCommandResult()` to mirror output into the child transcript when:

- lane is `AGENT_LANE_SUBAGENT`, or
- provider is CLI and detected by `isCliProvider(...)`.

Implementation behavior:

- Derives text from `payloads` (`join("\n\n")`, trimmed).
- Uses fallback text when output is empty.
- Calls `appendAssistantMessageToSessionTranscript(...)` using `effectiveSessionKey`.
- Logs success/failure with `[cli-transcript] ...`.

### B) Runtime clamp (defensive)

Replaced:

```js
(entry.endedAt ?? now) - (entry.startedAt ?? entry.createdAt)
```

with:

```js
Math.max(0, (entry.endedAt ?? now) - (entry.startedAt ?? entry.createdAt))
```

in relevant runtime files.

## 4) Files patched

Verified marker `"[cli-transcript] mirrored output"` present in:

- `/usr/lib/node_modules/openclaw/dist/subagent-registry-CkqrXKq4.js`
- `/usr/lib/node_modules/openclaw/dist/reply-DhtejUNZ.js`
- `/usr/lib/node_modules/openclaw/dist/pi-embedded-CtM2Mrrj.js`
- `/usr/lib/node_modules/openclaw/dist/pi-embedded-DgYXShcG.js`
- `/usr/lib/node_modules/openclaw/dist/plugin-sdk/reply-DFFRlayb.js`

Runtime clamp `Math.max(0, ...)` verified in those same runtime variants.

## 5) Validation evidence (pass)

Probe run:

- `runId`: `3c81985e-da19-4f5d-bf01-ade7b5b7c183`
- `sessionKey`: `agent:gemini:subagent:9532f2a0-a1c6-408f-88a0-7f6caf1a6138`

Result:

- `sessions_history` now contains assistant text (`GEMINI_SUBAGENT_MIRROR_PROBE`)
- transcript file exists:
  - `/home/ubuntu/.openclaw/agents/gemini/sessions/1bbc4513-94d1-4d84-8f70-595e2a44f7ce.jsonl`
- runtime values now non-negative in list outputs.

## 6) Reapply script (post-update)

Script path:

- `scripts/reapply_subagent_transcript_fix.py`

Usage:

```bash
# Preview only
sudo python3 /home/ubuntu/.openclaw/workspace/scripts/reapply_subagent_transcript_fix.py --dry-run

# Apply + restart gateway user service
sudo python3 /home/ubuntu/.openclaw/workspace/scripts/reapply_subagent_transcript_fix.py --apply --restart
```

Script safety:

- Creates `*.bak.fix-<timestamp>` backup per changed file.
- Runs `node --check` on changed files.
- Auto-rolls back changed files if syntax check fails.

## 7) Operational verification checklist (after updates)

1. Gateway healthy:

```bash
systemctl --user is-active openclaw-gateway.service
openclaw gateway status
```

2. Run one minimal subagent probe (Gemini is enough).
3. Verify transcript not empty via `sessions_history` for `childSessionKey`.
4. Confirm runtime values are non-negative in `subagents list`.
5. Check file logs if needed:

- `/tmp/openclaw/openclaw-YYYY-MM-DD.log`

## 8) Notes

- This is a hotfix over bundled artifacts, not an upstream source patch.
- After official upstream fix lands, this runbook/script may be retired.
