feat(harness): add chat application use case

This commit is contained in:
zhuyongxin
2026-07-22 00:57:39 +08:00
parent ee0949d464
commit f8809cb7dd
56 changed files with 2815 additions and 6 deletions
@@ -0,0 +1,115 @@
# single-react-chat-application-usecase Specification
## Purpose
TBD - created by archiving change single-react-chat-application-usecase. Update Purpose after archive.
## Requirements
### Requirement: Application-owned session and Run lifecycle
The Chat Application Use Case SHALL resolve or generate the session ID, create exactly one RunContext, persist one matching Diagnosis Run, and propagate the same session ID, run ID, original Query, cancellation, budget, and terminal outcome through routing and the selected executor.
#### Scenario: Existing session request
- **WHEN** an internal request supplies a valid session ID
- **THEN** the use case preserves it, generates one run ID, and returns/persists the same identifiers
#### Scenario: New session request
- **WHEN** an internal request omits the session ID
- **THEN** the use case generates one valid session ID and uses it for all Run operations
### Requirement: Minimal isolated Intent Router
The Router SHALL execute a direct no-Tool, no-memory, no-ReAct ChatModel call whose input contains only the unchanged Query, optional last intent, and optional last user Query. It SHALL accept only `SYSTEM_CHAT`, `KNOWLEDGE_QUERY`, or `DIAGNOSIS`.
#### Scenario: Three valid routes
- **WHEN** the model returns each supported enum in the strict output schema
- **THEN** the use case dispatches to exactly the corresponding fixed executor
#### Scenario: New topic overrides history
- **WHEN** the current Query identifies a new topic while prior routing context exists
- **THEN** the model input still preserves the original current Query and prior fields are only optional context
### Requirement: Router technical retry fails closed
The Router SHALL use `HarnessRetryPolicies.intentRouter()` and SHALL retry timeout, transport, or invalid output at most once with identical input. A second failure MUST produce `ROUTING_UNAVAILABLE` and MUST NOT dispatch Diagnosis.
#### Scenario: Invalid output then valid route
- **WHEN** the first output is not a supported enum and the second output is valid
- **THEN** exactly two attempts use the same input and the valid route is executed
#### Scenario: Two invalid outputs
- **WHEN** both permitted attempts return invalid output
- **THEN** the Run ends FAILED and no intent executor is called
### Requirement: Fixed isolated executors
The Application Use Case SHALL map SYSTEM_CHAT to one no-Tool model response, KNOWLEDGE_QUERY to exactly one lookup-knowledge invocation plus one bounded answer model call, and DIAGNOSIS to the single Diagnosis Agent followed by the release boundary. Executors MUST NOT call one another or rewrite the Query.
#### Scenario: System Chat
- **WHEN** intent is SYSTEM_CHAT
- **THEN** no evidence Tool, Diagnosis Agent, EvidenceGuard, or SemanticGuard is invoked
#### Scenario: Knowledge Query
- **WHEN** intent is KNOWLEDGE_QUERY
- **THEN** only lookup_knowledge is invoked once and query_logs/query_mysql/Diagnosis ReAct are unavailable
#### Scenario: Diagnosis
- **WHEN** intent is DIAGNOSIS
- **THEN** the original Query and bounded PreviousTurn enter DiagnosisAgentUseCase and the Draft cannot publish before DiagnosisReleaseUseCase
### Requirement: Knowledge references are physically validated
The Knowledge executor SHALL accept only a bounded READY RAG projection, SHALL validate every model answer item against the exact direct invocation ID and returned document ID set, and SHALL remove Tool Call IDs from public content.
#### Scenario: Supported knowledge answer
- **WHEN** answer items reference the exact lookup call and only returned documents
- **THEN** public content contains answer text, stable document references, and limitations without Tool Call IDs
#### Scenario: Fabricated knowledge reference
- **WHEN** the model returns another call ID or an unknown document ID
- **THEN** the executor fails closed and no knowledge answer is published
#### Scenario: No knowledge evidence
- **WHEN** lookup returns READY `NO_EVIDENCE`
- **THEN** the executor returns a fixed bounded no-evidence answer without calling the answer model
### Requirement: Safe bounded PreviousTurn
The system SHALL load PreviousTurn only from the same Session's most recent Run with `intent=DIAGNOSIS`, `release_outcome=SUCCESS`, and non-null valid `published_result`. It SHALL deterministically bound fields and source documents without model summarization.
#### Scenario: Last safe Diagnosis exists
- **WHEN** a qualifying Run contains valid PublishedResult JSON
- **THEN** the next Diagnosis receives its bounded query, conclusion, scope, limitations, and RAG document metadata
#### Scenario: Last Run is fallback failed or cancelled
- **WHEN** newer Runs are not qualifying safe Diagnosis successes
- **THEN** they cannot become PreviousTurn and the query returns the most recent qualifying record or null
#### Scenario: Published result is corrupt
- **WHEN** stored JSON is invalid or required safe fields are blank
- **THEN** PreviousTurn is null and no raw stored value reaches a model
### Requirement: Diagnosis Run persistence contract
The `diagnosis_run` schema SHALL add nullable `intent`, `release_outcome`, and JSON `published_result`, and the JPA entity/repository/store SHALL write and query them consistently. PublishedResult MUST NOT contain Tool IDs, raw evidence, full Draft, or SemanticGuard reasons.
#### Scenario: Successful Diagnosis completion
- **WHEN** a Diagnosis report with non-null conclusion is safely released
- **THEN** the Run stores intent DIAGNOSIS, release outcome SUCCESS, safe public answer, bounded PublishedResult, duration and budget usage
#### Scenario: Fallback completion
- **WHEN** release returns SafeFallback
- **THEN** the Run status is SUCCESS, release outcome is FALLBACK, and published_result is null
#### Scenario: Failure or cancellation
- **WHEN** routing/execution fails or the client cancels the Run
- **THEN** the Run stores exactly one FAILED or CANCELLED release outcome and no PublishedResult
### Requirement: Protocol-neutral progress and cancellation
The use case SHALL notify a protocol-neutral observer after the Run is persisted, expose only session/run identifiers and client-disconnect cancellation, and emit only fixed safe application status codes.
#### Scenario: Observer start and status
- **WHEN** internal execution begins
- **THEN** observer start occurs once before routing status and contains the persisted session/run identifiers
#### Scenario: Client disconnect control
- **WHEN** the observer invokes client-disconnect cancellation
- **THEN** the same RunContext is cancelled and late executor results cannot complete successfully
### Requirement: Stage-six-A public isolation
Stage 6A SHALL NOT modify or switch public Chat Controller endpoints, SSE contracts, frontend consumers, or legacy ChatService behavior.
#### Scenario: Internal-only delivery
- **WHEN** stage 6A changes are inspected
- **THEN** Controller/frontend/public endpoint behavior has zero diff and stage 6B can consume the completed use case without rewriting it