openclaw/extensions/qa-channel
Ayaan Zaidi 078ca0bc2f
fix(qa-channel): preserve final replies and clear unfinished previews (#147536)
Supersedes #144868 by @Alix-007. Issue #144851 was also reported by @Alix-007; the original commit and authorship are preserved.

## What Problem This Solves

QA final replies can be overwritten by late drafts or deleted during cleanup. A silent or empty completion can leave an unfinished preview visible.

## Why This Change Was Made

The existing preview owner decides which message is still an unfinished draft. Successful final promotion releases that draft handle and records durable delivery. Error, terminal-skip, and turn-settlement callbacks all call the same cleanup operation. The existing queue orders draft writes, promotion, and deletion.

## User Impact

Completed QA answers survive. Unfinished previews disappear before the turn is acknowledged. Distinct final chunks and attachments still arrive. This affects the repository-only QA transport.

## Evidence

- Real Gateway evidence uses identical deterministic fixtures on main `9d5fc2e49c` and candidate `72f2656c0e0b3d2381d5cb0900d4a256526fec7e`. HTTP readback after acknowledgement shows the silent draft retained on main and deleted on the candidate; the ordinary final survives on both.
- Late-partial, error-cleanup, failed-promotion, and distinct-delivery controls drive registered inbound callbacks with real HTTP bus operations. They complement the full Gateway reproduction; they do not claim every callback ordering occurred naturally in that run.
- The 55 selected tests passed on merge `5574f4821e476287b3c771b8b0b0b7c9eedb75f8`, with main parent `678f66a0b4` and candidate parent `72f2656c0e0b3d2381d5cb0900d4a256526fec7e`.
- The final correction preserves cleanup behavior with explicit awaited `try/finally`. The retained-final scenario still rejects missing answers and now verifies that the unfinished preview is deleted after acknowledgment. Its YAML success conditions are unchanged.
- All 66 owner/sibling tests passed on merge `3af49e8455a0860d99930363b2ce9f235364206b`, with main parent `e4ebb37723` and final candidate parent `597f869f9976d2707f7b0167f50f425c267372b3`.
- [CI run 34790888746](https://github.com/openclaw/openclaw/actions/runs/34790888746) is green at `597f869f9976d2707f7b0167f50f425c267372b3`, including lint and typechecks.

```sh
node scripts/run-vitest.mjs \
  extensions/qa-channel/src/inbound.test.ts \
  extensions/qa-channel/src/inbound-preview-lifecycle.test.ts \
  extensions/qa-channel/src/inbound.preview-terminal.test.ts \
  extensions/qa-channel/src/inbound.dispatch-lifecycle.test.ts \
  extensions/qa-channel/src/gateway.test.ts \
  extensions/qa-lab/src/scenario-retained-final.test.ts
```

## Consumers

QA Gateway polling waits for cleanup before acknowledging input. QA transcript and scenario readers retain completed answers and exclude deleted drafts. External production transports are unchanged.

## Invalidation

Preview handles and durable-delivery facts belong to one turn. Successful promotion releases the preview handle; terminal cleanup closes further preview updates.

## Compatibility

No config, schema, protocol, dependency, or public API changes.

Co-authored-by: Alix-007 <li.long15@xydigit.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-09-14 05:45:25 +05:30
..
assets
src fix(qa-channel): preserve final replies and clear unfinished previews (#147536) 2026-09-14 05:45:25 +05:30
api.ts
channel-plugin-api.ts
index.ts
openclaw.plugin.json
package.json
runtime-api.ts
setup-entry.test.ts
setup-entry.ts
setup-plugin-api.ts
test-api.ts
tsconfig.json