12 KiB
Event debug full QA and release verification — 2026-09-05
Scope and inventory
This follow-up investigates repeated welcome actions, verifies the debug surface with standalone Box/Plugin Runtime, and checks the changes before committing/pushing Core, SDK, and LocalAgent. Real messaging-platform effects must remain isolated from debug runs.
| Area | Required checks | Evidence |
|---|---|---|
| Root cause | Follow-up messages/tool IDs preserved; direct model replay before/after mock guidance; original welcome prompt | Sanitized local traces, browser tool count |
| Events | All 15 built-in event types plus custom; nested/Unicode data and identity/target mapping | Browser results and parameterized service tests |
| Platform actions | Every catalog tool; frozen and explicit targets; permission/event/API intersection | Parameterized host boundary tests, browser reply/query/moderation/request cases |
| Mock scenarios | Success, error, query fixture, unsupported API; malformed options rejected | Browser and service tests |
| Input | Empty message/name, invalid/non-object JSON, unsupported event, actor/subject validation | Browser and request tests |
| Trace | Thinking/text/tool ordering, final snapshot deduplication, status/error correctness, no-call summary | Browser and reducer tests |
| Lifecycle | Cancel retains partial record; rerun; tabs/Agent switching; provider failure/fallback; reconnect | Browser and transport/runner tests |
| Native tools | Exec/file operations, nonzero exit, timeout and path escape | Browser and native-tool tests |
| Layout | Long output/parameters, automatic bottom scroll, narrow view, KB card spacing | DOM geometry and screenshots |
| Release | Python/SDK suites, frontend build/lint, whitespace checks, change review, commit and push | Commands, counts and remote SHAs |
Investigation
The real follow-up request contained the assistant tool call and successful tool result with matching IDs. No loss occurred at the LocalAgent → SDK → Host model boundary. Direct replay to the configured provider, bypassing the runner, reproduced event_reply after success. Adding explicit mock completion semantics stopped further calls in two direct replays. The previous LocalAgent system context omitted the debug/mock semantics although the tool result said no real platform operation occurred.
The configured upstream claude-opus-4-8 also returned an unsolicited CLI identity statement in direct replay. This originates in the provider response, not the debug renderer. It is separate from preserving tool results; it must not be presented as normal LangBot-generated status.
Final results
Browser event matrix
Executed through the real Edge WebUI, against Core :5300, Vite :3000, standalone Plugin Runtime :5400/:5401, and Docker-backed standalone Box :5410. The unbound E2E Debug 0905 Agent uses deepseek-v4-flash; the user's original Agent and welcome prompt remain unchanged and use claude-opus-4-8.
| Event | Observed result in this pass |
|---|---|
bot.invited_to_group |
Actor/group queries and event_respond_group_invite(approve=true) succeeded; request ID frozen to debug-group-request. |
bot.muted, bot.removed_from_group |
One event_get_group call each, correct group target. |
bot.unmuted |
One actor query; correct user target. |
feedback.received |
One mock reply, FEEDBACK_MOCK_OK, person target. |
friend.added |
One mock reply, FRIEND_ADDED_OK, person target. |
friend.request_received |
Acceptance and separate explicit rejection exercised; rejection preserved approve=false, Unicode remark and frozen request ID. |
group.member_banned |
One member lookup, SDK-compatible nested user and group_id. |
group.member_left |
One group lookup, SDK-compatible id/name. |
group.member_joined |
Welcome reply, configured failure, query fixture, unsupported API, and mute/unmute/kick scenarios. Original-model repeat caveat below. |
message.deleted |
One actor lookup, SDK-compatible id/nickname. |
message.edited |
One simulated deletion; frozen group, chat and message IDs. |
message.reaction |
One reply, REACTION_OK, and correct 👍 event data. |
message.received |
Real six-tool file/exec chain, plain-text recovery, cancellation, draft retention, nonzero exit and timeout. |
platform.specific |
Preserved nested arrays, booleans, null and 测试🙂; no tools called. |
custom.event, custom.e2e |
Empty object and named custom event with CUSTOM_中文🙂; no tools called. |
The first invitation/default friend-request runs submitted the preset text; they are recorded as default-behavior cases, not as explicit one-call/rejection tests. The rejection was separately rerun with the actual submitted instruction verified. Browser automation reads the controlled input after filling before treating a scenario as submitted.
Mock and execution behavior
- Platform Mock runs the actual model/tool selection, authorization, parameter validation and frozen-target resolution; only the adapter boundary is simulated. Tests assert that mock execution never accesses the real bot manager. Native tools retain real Box behavior.
- The platform catalog contains 24 tools. Parameterized tests exercise success and configured failure for all 24, plus permission/event/API filtering, explicit/frozen targets, SDK fixture shapes and invalid options. This is full catalog contract coverage, not 24 separate browser clicks or proof of live adapter support.
errors.event_reply = "E2E permission denied"produced one failed call and the 模拟执行失败 · Mock status. The model reported the actual error without retrying in this scenario.results.event_get_actorreturned the configuredfixture-user-77/测试用户🙂; the model used these values instead of the original event identity. Default query results now serialize SDK platform models; default lists contain one synthetic entry and can be overridden with[].- Disabling
send_messageremovedevent_replyfrom the model's available tools. It returnedREPLY_UNAVAILABLE, with the explicit no-tool-call summary. Clearing Mock options restored action availability; the three moderation calls succeeded with the correct group/member IDs. - Mock
[], unknown tool names, whitespace-only message/custom name, malformed event JSON and event JSON[]were rejected. Browser transcript counts did not increase for client-side validation failures. Backend tests additionally cover falsey/non-object actor, subject and data values, conflicting outcomes and invalid API names. - Thinking returned by the provider, intermediate text, tool parameters, results and final text remain distinct and ordered. Missing thinking is not fabricated. Cumulative final snapshots and prior tool-turn prefixes are deduplicated without hiding actual repeated tool calls.
Lifecycle, native tools and layout
- A browser cancellation regression exposed a stuck 停止调试 button: the
finallyblock skipped resetting state for aborted requests. It now clears the matching controller and resets running state even after user cancellation. Retest retained partial thinking/tool arguments, marked the unfinished call 未返回结果, showed the cancellation notice and restored 运行测试. - Two subsequent recovery requests encountered the bounded-stream error below. A later request in the same tab/session returned
42successfully; further real tool runs also completed. Cancellation and recovery are therefore verified, but immediate model success after cancellation is not guaranteed. - Editing
NEXT_DRAFT_FINAL_0905while asleep 5run was still awaiting its final response preserved the draft after completion. - Real
write → read → edit → glob → grep → execsucceeded.final.txtchanged fromFINAL_WRITEtoFINAL_EDIT; grep withoutincludefound one match; exec returnedFINAL_EXECwith exit code 0. Writes stayed under/workspace/e2e-debug-0905. printf E2E_ERROR >&2; exit 7preserved stderr and exit code 7 and displayed failure.sleep 3withtimeout_sec=1returnedtimed_outin 1025 ms and displayed failure. Neither was retried.- Separate tabs retained separate transcripts during concurrent runs. Agent switching reset the debug surface. File workspace sharing remains intentional; transcript isolation does not mean separate Box filesystems.
- The final transcript measured 674 px high with 16,630 px scroll height, distance from bottom 0, and equal client/scroll widths of 468 px. Visual inspection confirmed contained parameters/results and accessible input controls. The earlier pass also verified 1280 × 800; the final attempted viewport override did not change this tab, so that attempt is not counted as an additional narrow-screen result. Temporary overrides were reset.
- Knowledge-base card geometry: retrieval card bottom 1413 px, danger card top 1437 px, giving the expected 24 px gap. Both adjacent card gaps measured 24 px.
- Core health check returned
ok; Plugin Runtime was connected and all development service ports remained listening. Previous restart/reconnect evidence is in the earlier report.
Automated checks
| Suite | Result |
|---|---|
| Core agent unit directory plus debug service/controller, native/skill tools and model conversion | 659 passed, 24 Windows-only skips |
| Final changed platform/debug service/controller checks | 133 passed |
| Linux Docker: native tools, skill tools and all platform tools | 150 passed, 0 skipped; includes the 24 POSIX cases skipped on Windows |
| SDK API suite plus runtime I/O handler | 411 passed |
LocalAgent full suite (PYTHONUTF8=1) |
187 passed |
| Frontend unit suite | 69 passed |
| Skills CLI suite | 122 passed |
| Frontend TypeScript/Vite build and changed-file ESLint | Passed; existing large-bundle advisory remains |
| Changed Python Ruff; Git whitespace checks | Passed |
| Skills index generation, validate and index consistency | Passed |
Counts overlap where a final focused/Linux run repeats an earlier suite; do not add them as unique tests. Existing Pydantic deprecation warnings remain. This is the relevant subsystem regression set, not the entire repository/integration matrix. Provider fallback has deterministic LocalAgent tests; live fallback after a partially emitted response is deliberately unsupported and was not claimed as a successful browser fallback.
The full regression also found Windows portability problems in the skills tooling: LF-only frontmatter parsing, /cases/ detection and native path separators in generated references. These are fixed and covered by the CLI suite. Two frontend source-contract expectations were stale after the existing three-tab workbench/layout changes; they were updated to the actual product structure.
Remaining limits and reproduction
- Original provider is still nondeterministic. With the latest LocalAgent guidance, one rerun made exactly one successful
event_reply; another made repeated successful replies before stopping. The trace faithfully records each call. Earlier invalid_callarguments were rejected. Direct provider replay proved that repeated calls can originate upstream even with a valid matching tool result. Prompt guidance reduces ambiguity but does not establish exactly-once actions. No silent deduplication or fabricated success was added. - Bounded stream pressure can fail long responses. Two recovery runs emitted thinking and then
Streaming action consumer is too slow; response buffer full; later recovery and six-tool runs succeeded. The error originates in the SDK's existing 128-frame response queue and is preserved in the UI. It is not a missing-tool-result or 30-second HTTP timeout. Full end-to-end flow control under sustained overload remains open; queue limits were not removed to conceal the failure. - Mock results verify debug behavior, not real platform credentials, permissions, delivery, or every adapter/event Cartesian combination. Already launched external tool termination timing was not independently measured. A development-branch push does not mean these remaining production release gates passed.
For reproduction, use the retained test Agent, the Mock examples in AGENT_RUNNER_QA_GUIDE.md, and the original welcome Agent. Local diagnostic traces and fixture artifacts are excluded from Git; they contain model responses and local runtime state. This report contains outcomes rather than raw provider reasoning or secrets.