FE-538: Entity sidebar (read-only)#24
Conversation
FE-538 Entity sidebar (read-only)
React sidebar showing accumulated entities by type: scope items, requirements, decisions, assumptions. Updates live via data-entities SSE events. Read-only. |
🤖 Augment PR SummarySummary: This PR adds a read-only “Entity Sidebar” to the interview workspace, backed by a new entities API and TanStack Query for client-side state. Changes:
Technical Notes: Entity updates are driven by React Query invalidation on chat status transition (streaming → ready), rather than in-band data-part syncing. 🤖 Was this summary useful? React with 👍 or 👎 |
|
|
||
| export function EntitySidebar({ projectId }: { projectId: number }) { | ||
| const [activeTab, setActiveTab] = useState<Tab>('Decisions'); | ||
| const { data, isLoading } = useEntities(projectId); |
There was a problem hiding this comment.
src/client/components/EntitySidebar.tsx:31: useEntities failures aren’t surfaced, so a network/500 error will render the “No decisions/assumptions yet” empty state and silently mask the problem. Consider rendering an explicit error state using isError/error from React Query so users can distinguish “no entities” from “failed to load”.
Severity: medium
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
|
|
||
| // Get entities for a project | ||
| app.get('/api/projects/:id/entities', (req: Request, res: Response) => { | ||
| const id = Number(req.params.id); |
There was a problem hiding this comment.
src/server/app.ts:93: Number(req.params.id) will accept values like "1.5" and "-1" (not NaN), which can lead to confusing behavior when treated as a DB identifier. Consider validating that the project ID is a positive integer before querying.
Severity: low
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
| res.status(400).json({ error: 'Invalid project ID' }); | ||
| return; | ||
| } | ||
| res.json(getEntitiesForProject(db, id)); |
There was a problem hiding this comment.
src/server/app.ts:98: /api/projects/:id/entities returns {decisions: [], assumptions: []} even when the project doesn’t exist, whereas /api/projects/:id returns 404 for unknown projects. This can cause the UI to cache an “empty” entities response for a typo’d ID and hide a real not-found condition.
Severity: medium
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
| }, | ||
| required: ['decisions', 'assumptions'], | ||
| }, | ||
| schema: toJSONSchema(observerOutputSchema), |
There was a problem hiding this comment.
src/server/observer.ts:85: toJSONSchema(observerOutputSchema) may emit JSON Schema features (e.g., $ref/$defs or non-OpenAI/Anthropic-compatible keywords) depending on Zod’s generator defaults. Since this only fails at runtime when calling query, consider ensuring the generated schema is accepted by the Claude structured-output implementation (and ideally covered by a test/assertion).
Severity: medium
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
Read-only sidebar shows observer-extracted decisions and assumptions in categorized tabs. TanStack Query manages entity state; cache invalidated on chat stream completion (status transition). Entities API endpoint at GET /api/projects/:id/entities. 149 tests (2 new), all pass. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Eliminates 30 lines of hand-written JSON schema that duplicated the Zod observerOutputSchema. Single source of truth. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…nterviewerContext Eliminates core.ts → context.ts import. Tests now directly assert buildInterviewerContext output instead of comparing against a wrapper. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SDK stream → DomainEvent translation now lives in sdk.ts (createStreamTranslator). The sse-adapter only handles DomainEvent → AIEvent via createDomainAdapter. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Without this, the ask_question tool persists options to DB but the route loader data is stale — TurnCard never appears. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
c52f35c to
b5d22c2
Compare

feat: entity sidebar with TanStack Query (FE-538)
Read-only sidebar shows observer-extracted decisions and assumptions
in categorized tabs. TanStack Query manages entity state; cache
invalidated on chat stream completion (status transition). Entities
API endpoint at GET /api/projects/:id/entities.
149 tests (2 new), all pass.
Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
traceability: slice 6 done — I23 established, A21 partially validated
Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
refactor: derive observer JSON schema from Zod via toJSONSchema
Eliminates 30 lines of hand-written JSON schema that duplicated
the Zod observerOutputSchema. Single source of truth.
Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
refactor: remove deprecated formatHistory, update tests to use buildInterviewerContext
Eliminates core.ts → context.ts import. Tests now directly assert
buildInterviewerContext output instead of comparing against a wrapper.
Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
refactor: remove unused queryClient export from main.tsx
Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
refactor: remove createTranslator from sse-adapter
SDK stream → DomainEvent translation now lives in sdk.ts
(createStreamTranslator). The sse-adapter only handles
DomainEvent → AIEvent via createDomainAdapter.
Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
chore: update test coverage table after refactor
Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
fix: invalidate router after stream to show TurnCard
Without this, the ask_question tool persists options to DB but the
route loader data is stale — TurnCard never appears.
Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com