瀏覽代碼

docs: design balanced ChatAgent event selection

Problem: ChatAgent can verbally promise supported actions without emitting the text event required to execute them.\n\nRisk: stronger selection rules must preserve negative boundaries, legacy EventPrompt cleanup, and invocation-mode isolation.
zhenyu.hu 2 周之前
父節點
當前提交
63481a9a4c
共有 2 個文件被更改,包括 227 次插入0 次删除
  1. 1 0
      docs/plans/todos.md
  2. 226 0
      docs/superpowers/specs/2026-07-15-chat-agent-event-prompt-design.md

+ 1 - 0
docs/plans/todos.md

@@ -121,3 +121,4 @@
 | 53.4 | done | `docs/plans/todo-53.4-managed-event-prompt-test-identity.md` | Make the payload-singleton regression distinguish the managed EventPrompt from a generated-signature custom impostor. | Focused `1 passed`, full WebSocket file `94 passed`; mutation check proves the test fails if the impostor survives instead of the managed item. |
 | 53.5 | done | `docs/plans/todo-53.5-event-prompt-order-independent-identity.md` | Prove EventPrompt payload selection depends on managed prompt identity rather than whether it appears before or after a generated-signature impostor. | Focused `1 passed`, full WebSocket file `94 passed`; both item orderings pass and bounded code-quality review is approved. |
 | 53.6 | done | `docs/plans/todo-53.6-browser-visual-qa.md` | Complete desktop and narrow-screen visual/interaction QA before closing Todo 53 and merging locally. | Browser QA was explicitly waived by the user on 2026-07-15 after Chrome extension communication remained unavailable; automated and HTTP verification remain the accepted closeout evidence. |
+| 54 | pending | `docs/superpowers/specs/2026-07-15-chat-agent-event-prompt-design.md` | Balance ChatAgent text-event recall and false positives with a decision-oriented EventPrompt while preserving the existing protocol and invocation-mode boundaries. | TDD prompt-contract and compatibility tests pass; focused/full suites, JS syntax, app import, and diff checks pass; live A/B evidence is recorded when a provider target is available. |

+ 226 - 0
docs/superpowers/specs/2026-07-15-chat-agent-event-prompt-design.md

@@ -0,0 +1,226 @@
+# ChatAgent Event Selection Prompt Design
+
+**Date:** 2026-07-15
+**Status:** approved for implementation planning
+
+## Context
+
+In `dual_agent` mode, ChatAgent selects EventAgent capabilities by appending
+event names inside an `<agent_events>` block after its visible reply. The
+current generated prompt explains the catalog and output format, but treats
+event selection as optional and does not define when an event is required.
+
+Recent local audit evidence shows the practical failure mode: ChatAgent says it
+will adjust volume or check weather, but emits no event. Examples include
+`声音调到90`, `调大一点音量`, and later weather requests. The model therefore
+produces a plausible conversational promise without causing the real action.
+
+The generated prompt currently exists in two equivalent construction paths:
+
+- `ToolRegistry.chat_event_system_message()` supplies the runtime fallback for
+  API clients that did not submit an EventPrompt.
+- `buildAvailableEventsPrompt()` generates the read-only EventPrompt shown and
+  submitted by the browser console.
+
+Both paths must retain the same behavioral contract. The text-event parser and
+the `<agent_events>` wire format are already stable and are not the source of
+the observed missed triggers.
+
+## Goals
+
+- Balance event recall against false positives.
+- Require an event whenever ChatAgent promises or claims a supported external
+  action.
+- Trigger low-risk, read-only, or reversible capabilities from clear natural
+  intent, even when the user does not phrase it as an imperative.
+- Ask one concise clarification before ambiguous or incomplete higher-impact
+  actions.
+- Keep ordinary conversation, hypothetical discussion, unsupported requests,
+  and capability questions event-free.
+- Preserve the existing event block protocol, parser, EventAgent argument
+  resolution, event kernel, and invocation-mode boundaries.
+- Continue recognizing old generated EventPrompts when restoring sessions or
+  workspace snapshots.
+
+## Non-goals
+
+- No separate intent-classification model call.
+- No provider-native tool schema changes.
+- No EventAgent argument protocol changes; ChatAgent still emits names only.
+- No event-kernel, handler, session, WebSocket, or active-turn behavior change.
+- No guarantee that every stochastic model follows the prompt perfectly; live
+  evaluation measures adherence but does not replace deterministic contracts.
+
+## Approaches Considered
+
+### 1. Decision-oriented prompt only
+
+Replace the weak optional wording with explicit selection rules, consistency
+invariants, and compact positive and negative examples. Keep the current
+protocol and model-call count.
+
+This is the selected approach because it directly addresses the observed
+failure, has the smallest runtime scope, and can be evaluated independently
+before introducing new architecture.
+
+### 2. Metadata-driven trigger policies
+
+Expose trigger and confirmation metadata through the event catalog and render
+event-specific policy dynamically. This scales better for a large heterogeneous
+registry, but requires domain, catalog API, frontend, and compatibility changes.
+It remains a possible follow-up if prompt-only evaluation shows that generic
+rules are insufficient.
+
+### 3. Separate event-intent classifier
+
+Run a dedicated classification step before ChatAgent response generation. This
+could improve isolation but adds latency, token cost, another failure mode, and
+coordination complexity. It is not justified before measuring the prompt-only
+approach.
+
+## Selected Prompt Contract
+
+The generated EventPrompt will identify itself as protocol version 2 and use
+imperative rules. Its dynamic catalog remains name plus description only.
+
+The prompt must communicate these rules:
+
+1. Decide whether the user's latest intent requires any available event.
+2. When a supported real-world action or fresh external-data request is clear,
+   emit the matching event.
+3. If the visible reply says or implies that ChatAgent will perform, has
+   performed, is checking, is changing, is scheduling, or is ending something,
+   the same reply must append the corresponding event. ChatAgent must never
+   promise a supported action without emitting its event.
+4. Low-risk, read-only, and reversible actions may be inferred from clear
+   natural intent. `声音太小了` can select `device.volume.adjust`, and
+   `明天天气怎么样` can select `knowledge.web.search`.
+5. For ambiguous or incomplete higher-impact actions, ask one concise
+   clarification and emit no event yet. A complete and unambiguous request does
+   not require redundant confirmation.
+6. Do not emit events for ordinary conversation, hypothetical statements,
+   discussion about a capability, unsupported behavior, or a request that does
+   not match an available event.
+7. Multiple independent clear intents may emit multiple exact event names, one
+   per line.
+8. The event block is machine-control metadata, not part of the visible reply.
+   It is allowed even when another prompt prohibits Markdown, lists, JSON, or
+   other visible formatting.
+9. When no event is selected, omit the event block entirely.
+10. Never include parameters, explanations, bullets, code fences, or invented
+    names inside the block.
+
+The generated shape will remain:
+
+```text
+Event selection protocol v2.
+Available events:
+- event.name: description
+...
+[decision rules and compact examples]
+First write the user-facing reply normally. If one or more events are selected,
+append exactly this block after the visible reply:
+<agent_events>
+event_name
+</agent_events>
+Use exact available event names only, one per line. Do not include parameters.
+```
+
+## Decision Examples
+
+The prompt will include a small, generic set of examples that match the current
+production-shaped capabilities without teaching argument extraction:
+
+| User intent | Expected selection behavior |
+| --- | --- |
+| `声音太小了` | Reply naturally and emit `device.volume.adjust`. |
+| `声音调到90` | Reply naturally and emit `device.volume.adjust`. |
+| `明天天气怎么样` | Reply naturally and emit `knowledge.web.search`. |
+| `你回复太慢了` | No event; response latency is not device volume. |
+| `你能调音量吗` | No event; this asks about capability rather than requesting action. |
+| `提醒我开会` | Ask for missing scheduling details and emit no event. |
+| `我明天下午三点要开会` | No event; this is a statement unless the user requests scheduling. |
+| A complete request to create a schedule | Emit `calendar.schedule.create`. |
+| An explicit goodbye or session-ending request | Emit `session.terminate`. |
+| Ordinary greeting or emotional conversation | No event. |
+
+Examples are selection guidance only. EventAgent remains responsible for
+arguments and validation.
+
+## Data Flow and Compatibility
+
+The browser continues to generate a read-only EventPrompt from selected tools.
+In `dual_agent`, exactly one managed EventPrompt is serialized. In
+`chat_agent_tools`, generated EventPrompt content remains excluded and provider
+tool schemas remain the only capability-selection surface.
+
+The runtime continues to inject its registry-generated prompt only when no
+event instructions are already present. The Python and JavaScript prompt
+builders will use the same version marker, rule ordering, examples, catalog
+format, and output suffix.
+
+`isGeneratedEventPromptContent()` must recognize both:
+
+- the legacy prefix `You may request EventAgent work using this text protocol.`;
+- the new `Event selection protocol v2.` prefix.
+
+Recognition remains conservative: a known prefix alone is insufficient. The
+content must also contain the event block markers and the exact-name/no-
+parameters instruction. This preserves cleanup of historical generated prompts
+without deleting ordinary custom prompts that merely mention event syntax.
+
+## Verification Design
+
+Implementation will use TDD.
+
+Deterministic tests will first fail against the current prompt and then prove:
+
+- the backend prompt contains the version marker, mandatory action/event
+  consistency rule, low-risk inference rule, higher-impact clarification rule,
+  negative boundaries, exact output block, and compact examples;
+- the frontend prompt contains the same behavioral anchors and catalog output;
+- old and new generated EventPrompt signatures are both recognized;
+- ordinary custom prompts containing partial markers remain retained;
+- payload singleton and invocation-mode filtering behavior remain unchanged;
+- runtime fallback injection still supplies exactly one catalog and no provider
+  tools in `dual_agent`;
+- parser behavior is unchanged.
+
+Focused verification commands will cover the prompt/runtime tests and frontend
+source/behavior tests, followed by JavaScript syntax, the full suite, app import,
+and diff checks.
+
+If a local live provider target and API key are available, run a fresh A/B
+evaluation with the same model and parameters. At minimum, evaluate the ten
+decision examples above across old and new prompts and record both missed
+required events and false positives. Existing historical SQLite sessions are
+evidence for the problem but must not be reused as an A/B input source because
+their accumulated context and prompt order differ.
+
+## Risks and Controls
+
+- Stronger rules may increase false positives. Negative examples and the
+  capability-question/hypothetical boundaries control this risk.
+- Generic risk language may not scale to future events. If live evaluation
+  exposes event-specific ambiguity, follow up with metadata-driven policy
+  rather than continually expanding a monolithic prompt.
+- Prompt duplication between Python and JavaScript can drift. Tests assert the
+  shared behavioral anchors and exact protocol suffix in both paths.
+- Historical snapshots may contain the old generated prompt. Dual-signature
+  detection preserves deduplication and outbound singleton guarantees.
+- Other system prompts may prohibit visible formatting. The v2 prompt explicitly
+  defines the event block as hidden machine metadata so those instructions do
+  not suppress event emission.
+
+## Success Criteria
+
+- Direct or naturally expressed volume requests and fresh-data questions cause
+  the matching event instead of an unsupported verbal promise.
+- Response-latency complaints, capability questions, ordinary chat, and
+  incomplete scheduling requests do not produce unrelated events.
+- No protocol, parser, provider-tool mode, EventAgent argument, or event-kernel
+  regression occurs.
+- Old and new EventPrompt snapshots remain safely deduplicated.
+- Deterministic verification passes, and any available live A/B evidence records
+  both recall and false-positive outcomes rather than reporting only successful
+  triggers.