feat(advisor): Phase 1 — endpoint backward-compat (keep breakpilot-workspace working)

The advisor endpoint now serves two shapes off one orchestration:
- new FE ({question}) -> v3 JSON contract (clarity/answer/evidence/citations/...).
- legacy consumer ({message}, e.g. breakpilot-workspace which reads a text stream and
  persists raw bytes) -> plain-text stream of the L2 answer (clean prose, no [n] markup,
  no clarify gate). isLegacyRequest() discriminates; answerSystem() gains withCitations.

Prevents the v3 contract from breaking breakpilot-workspace's chat (CLAUDE.md rule #4,
keep every consumer working). No deploy. tsc clean, 13 vitest (incl. isLegacyRequest),
check-loc 0.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-07-01 13:53:17 +02:00
parent 5a513181cc
commit 3f372bcb39
3 changed files with 57 additions and 6 deletions
@@ -5,6 +5,7 @@ import {
mapFootnotes,
buildCitations,
numberedEvidenceForPrompt,
isLegacyRequest,
} from '../advisor/retrieve-mapping'
import type { EvidenceUnit } from '../advisor/contract'
@@ -68,3 +69,13 @@ describe('mapFootnotes', () => {
})
})
})
describe('isLegacyRequest', () => {
it('message-only (workspace) -> legacy stream', () => {
expect(isLegacyRequest({ message: 'Ist meine DSE ausreichend?' })).toBe(true)
})
it('question present -> contract (JSON)', () => {
expect(isLegacyRequest({ question: 'x', message: 'y' })).toBe(false)
expect(isLegacyRequest({ question: 'x' })).toBe(false)
})
})