Skip to content

FE-538: Entity sidebar (read-only)#24

Merged
lunelson merged 8 commits into
mainfrom
ln/fe-538-entity-sidebar
Apr 7, 2026
Merged

FE-538: Entity sidebar (read-only)#24
lunelson merged 8 commits into
mainfrom
ln/fe-538-entity-sidebar

Conversation

@lunelson
Copy link
Copy Markdown
Contributor

@lunelson lunelson commented Apr 3, 2026

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

@linear
Copy link
Copy Markdown

linear Bot commented Apr 3, 2026

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.

Copy link
Copy Markdown
Contributor Author

lunelson commented Apr 3, 2026

This stack of pull requests is managed by Graphite. Learn more about stacking.

@lunelson lunelson changed the title feat: entity sidebar with TanStack Query (FE-538) FE-538: Entity sidebar (read-only) Apr 7, 2026
@lunelson lunelson marked this pull request as ready for review April 7, 2026 15:30
@augmentcode
Copy link
Copy Markdown

augmentcode Bot commented Apr 7, 2026

🤖 Augment PR Summary

Summary: 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:

  • Introduced EntitySidebar UI with tabbed views for Decisions and Assumptions.
  • Added TanStack Query (@tanstack/react-query) and wrapped the app in QueryClientProvider.
  • Added GET /api/projects/:id/entities to return persisted decisions/assumptions for a project.
  • Updated InterviewWorkspace layout to include the sidebar and to refresh entities/route data when chat streaming completes.
  • Added API tests covering the new entities endpoint (empty project + invalid ID).
  • Refactored observer structured-output schema generation to derive JSON schema from Zod via toJSONSchema.
  • Removed deprecated formatHistory wrapper and cleaned up SSE adapter translator/test surface area.

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 👎

Copy link
Copy Markdown

@augmentcode augmentcode Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 4 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.


export function EntitySidebar({ projectId }: { projectId: number }) {
const [activeTab, setActiveTab] = useState<Tab>('Decisions');
const { data, isLoading } = useEntities(projectId);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Comment thread src/server/app.ts

// Get entities for a project
app.get('/api/projects/:id/entities', (req: Request, res: Response) => {
const id = Number(req.params.id);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Comment thread src/server/app.ts
res.status(400).json({ error: 'Invalid project ID' });
return;
}
res.json(getEntitiesForProject(db, id));
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Comment thread src/server/observer.ts
},
required: ['decisions', 'assumptions'],
},
schema: toJSONSchema(observerOutputSchema),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Copy link
Copy Markdown
Contributor Author

lunelson commented Apr 7, 2026

Merge activity

  • Apr 7, 4:18 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Apr 7, 4:20 PM UTC: Graphite rebased this pull request as part of a merge.
  • Apr 7, 4:20 PM UTC: @lunelson merged this pull request with Graphite.

@lunelson lunelson changed the base branch from ln/fe-537-observer-agent to graphite-base/24 April 7, 2026 16:18
@lunelson lunelson changed the base branch from graphite-base/24 to main April 7, 2026 16:18
lunelson and others added 6 commits April 7, 2026 16:19
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>
lunelson and others added 2 commits April 7, 2026 16:19
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant