Decisions
Entry
- Parent issue:
ISS-014
- Change:
single-react-design-freeze
- Scale:
complex
- Interface impact: future L4; this change freezes contracts without switching runtime behavior.
- Capability sources: sm-flow built-in clarify/context/propose,
grill-with-docs, openspec-propose, zoom-out, openspec-apply-change, openspec-archive-change.
Context Evidence
session-run-trace-isolation established Chat Session and Diagnosis Run as separate lifecycles and made runId the Trace ownership key.
verifier-evidence-reference-fidelity established that no-evidence is a scoped negative observation, not proof that a problem does not exist.
executor-composer-final-answer established deterministic safe fallback boundaries and prohibited unfiltered raw output from reaching users.
modular-rag-pipeline established that retrieval trace and context packing are audit details rather than direct facts.
- Current Spring AI Alibaba
ToolCallRequest already provides tool_call_id; Harness must validate and persist it rather than create a second identity.
- Current Spring AI
ChatModel.call(Prompt) has no cancellation token, so cancellation must be expressed as layered, observable semantics rather than an unsupported absolute guarantee.
Question Pool
| ID |
Dimension |
Question |
Mode |
Status |
| Q1 |
Terminology |
Does tool_call_id use the framework ID or a Harness-generated ID? |
user-interview |
confirmed: framework ID |
| Q2 |
Terminology |
Are invocation lifecycle and evidence outcome separate fields? |
user-interview |
confirmed: status + evidence_status |
| Q3 |
Boundary |
Is ISS-014 one umbrella Issue with independent OpenSpec changes? |
user-interview |
confirmed: one Issue, 11 changes |
| Q4 |
Boundary |
May stage 4 publish before Guards exist? |
user-interview |
confirmed: no; public cutover only in 6B |
| Q5 |
Lifecycle |
What is the durable source of truth for previous_turn and last_intent? |
user-interview |
confirmed: diagnosis_run safe published result |
| Q6 |
Contract |
How is KNOWLEDGE_QUERY citation validation represented? |
evidence-driven |
resolved: structured answer items with exact RAG bindings |
| Q7 |
Cancellation |
What cancellation guarantees are technically enforceable? |
evidence-driven |
resolved: layered cancellation, no false hard-cancel claim |
| Q8 |
Acceptance |
Are Apply, Archive and phase Git commit pre-authorized? |
user-interview |
confirmed: yes, for all phases |
Confirmed Decisions
tool_call_id is the framework Tool Call protocol ID. Harness validates non-empty, bounded, safe characters and Run-local uniqueness; duplicate/invalid/missing IDs fail closed.
- Redis
status=PROJECTING/READY/ERROR represents invocation/projector lifecycle.
evidence_status=EVIDENCE_FOUND/NO_EVIDENCE/ERROR represents result semantics.
NO_EVIDENCE may only support NEGATIVE_OBSERVATION within the exact query scope; it cannot prove absence, exclusion or health.
- Stage 4 and 6A remain internal. Stage 6B performs the only public Chat cutover after stage 5 release gates pass.
- ISS-014 remains the umbrella Issue. Eleven independent changes run serially; each must complete sm-flow, OpenSpec archive and Git commit before the next starts.
- Full live E2E is deferred to stage 7; earlier stages run focused verification proportional to their change.
- KNOWLEDGE_QUERY uses a dedicated structured draft: each answer item binds the single lookup
tool_call_id and one or more returned document_id values; Harness validates exact membership before rendering answer + references + limitations. It does not reuse the Diagnosis Analysis schema and does not enter SemanticGuard in the first version.
- Cancellation is layered: mark cancellation requested, prevent new model/Tool rounds and any final Draft release, invoke framework interruption, cancel owned Tool/JDBC work where supported, and rely on configured HTTP timeouts for an already-blocking synchronous model call. Run finalization is atomic and late results are discarded.
- Public SSE
done is not emitted after the client has disconnected; internal Run state still reaches CANCELLED.
diagnosis_run is the durable source for intent, release_outcome and published_result. Only the latest same-session DIAGNOSIS + SUCCESS record with a non-null safe published result may become previous_turn; FALLBACK/FAILED/CANCELLED remain auditable but are excluded.
published_result stores only user_query/published_conclusion/scope/limitations/source_documents; it excludes Tool Call IDs, raw evidence, full Draft and SemanticGuard audit reasons.
Evidence-Driven Findings To Report
- The framework already exposes
ToolInterceptor, structured output types, tool execution timeout, model/tool call limit hooks and ReactAgent.interrupt; later Harness stages should reuse these extension points.
- Spring AI model dependencies include retry support, while current application configuration does not explicitly freeze all retry layers; stage 0 must define a retry inventory and stage 2 must enforce it.
- Current
DiagnosisRun stores a text answer and generic status but has no explicit intent, release_outcome or structured published result; Q5 must be resolved before the previous-turn contract is executable.
- Current KNOWLEDGE_QUERY target behavior promises citation validation, but the issue only defines the Diagnosis Draft binding schema; the committed spec must add the dedicated answer-item contract described above.
- Spring AI retry auto-configuration defaults
maxAttempts to 10. The target Harness retry matrix requires underlying model/HTTP retries to be set to one attempt, with Router and SemanticGuard retries performed only by Harness.
OpenSpec Backfill
- All confirmed decisions above must appear in design/specs/tasks before
.committed is created.
- All user-interview questions are confirmed; no pending decision blocks Commit.
Architecture Audit
Current input flows from ChatController into ChatService, which owns routing, ReactAgent construction, multi-Agent orchestration and final rendering; tools persist evidence through ToolInvocationRecorder, while Hooks and ThreadLocal bridge Run and verifier state. Stage zero introduces only dependency-free contract types under harness.contract; those types must not depend on Controller, Redis, JPA, Spring Agent state or current Hook classes. Later stages move ownership in order: RunContext, invocation store, Tool-specific projection, Diagnosis Agent, Guards, application use case and finally the public SSE adapter. diagnosis_run remains durable Run ownership, Redis canonical invocation remains short-lived Harness ownership, and agent_step/tool_invocation remain durable audit detail. The principal risk is spec/runtime drift, mitigated by archiving only the stage-zero contract capability now and delaying modifications to existing runtime capabilities until their implementation changes.
Cross-Artifact Alignment
| Chain |
Status |
Evidence |
| ISS-014/brief goals, scope and non-goals → proposal |
aligned |
Proposal limits stage zero to contracts, security and baseline with no public cutover. |
| proposal commitments → design |
aligned |
Design records every ID, status, Draft, fallback, previous-turn, retry, cancellation and phase-gate commitment. |
| design decisions → specs |
aligned |
The single stage-zero capability has testable requirements for every stable contract boundary. |
| specs observable behavior → tasks |
aligned |
Tasks create reusable types/tests, remove the secret, align artifacts and verify without switching runtime behavior. |
Commit Gate Result
- Question pool covers terminology, boundary, lifecycle, contract, cancellation and acceptance.
- All user-interview items are explicitly confirmed.
- Evidence-driven conclusions were reported and written into design/spec/tasks.
- Interface impact is recorded as future L4; this change itself does not switch the public API.
- No devflow/OpenSpec conflict remains.