Skip to content

feat(incidents): follow the Insights API follow-ups — server transition table, chat prompt, insight ↔ ticket/chat links - #438

Merged
oleksandr-blip merged 8 commits into
mainfrom
feat/incidents-insight-links
Sep 21, 2026
Merged

oleksandr-blip merged 8 commits into
mainfrom
feat/incidents-insight-links

Conversation

@oleksandr-blip

Copy link
Copy Markdown
Contributor

Summary

Frontend side of flamingo-stack/openframe-saas-tenant#3149 (+ flamingo-stack/openframe-oss-lib#2248, flamingo-stack/openframe-saas-lib#894).

  • Status transitions from the server. insightStatusTransitions is read through one @inline fragment on Query, spread into the list and detail operations (no extra round trip), and drives the row menu and the header button. The client mirror of the validator is deleted — it had already drifted (ACKNOWLEDGED / SNOOZED now only → RESOLVED).
  • Fix with Mingo = the server's insightChatPrompt. Fetched on click; its leading @insight: / @device: markers become labelled mentions, the ask becomes the text (fix-with-mingo-draft.ts, unit-tested). The dialog created from that draft sends insightId on POST /dialogs (launcher-store link, consumed on create, dropped on any change of conversation / new chat / close).
  • Stored insight id everywhere Mingo references an incident (picker item, mention chip, open view, dialog link) — what the real InsightContextResolver looks up; the chip re-encodes it for its own query.
  • Incident ↔ ticket through the assignments component. #2248 records a ticket filed from an incident as an assignment owned by the insight (item INSIGHT → target TICKET). The incident page shows its tickets with AssignedItemsView (itemType: INSIGHT) under "Assigned Ticket"; the ticket form shows the incident it is filed from as a read-only AssignmentsField row (INSIGHT is a client-only target: not pickable, never written through assignItem, sent as CreateTicketInput.insightId).
  • Mingo sessions on the incident page — dialogs(filter: { insightId }), each row opens the drawer on that conversation.

Depends on (must be deployed first)

saas-tenant #3149, oss-lib #2248, saas-lib #894 — the list/detail queries select insightStatusTransitions, so this fails against an API without it.

Verified on tenant-3149-53

  • Row menu / header follow the server table (NEW: Acknowledge · Snooze · Resolve; after acknowledging: only Resolve)
  • Fix with Mingo: both chips + server text prefilled; sent → Mingo resolved the insight and device; dialog linked to the insight and listed under Mingo Sessions
  • Create Ticket from the incident: "Assigned Incident" row on the form; saved → listed under Assigned Ticket on the incident
  • Cursor page 2 with filters (API) — #894 fixed it
  • tsc, lint:ci, Prettier, relay, vitest

Still backend-bound

  • Ticket table SOURCE column shows the device; the design shows the incident — needs Ticket.insightId (or the link exposed on the ticket).
  • Ticket details cannot show its incident (INSIGHT is not an AssignmentTargetType).
  • "Open Mingo Session" header variant not done — the sessions list covers reopening.

🤖 Generated with Claude Code

oleksandr-blip and others added 2 commits September 21, 2026 10:56
…on table, chat prompt, insight links

Aligns with openframe-saas-tenant#3149 (Insight ai and assigned items):

- Status transitions come from `insightStatusTransitions` (an @inline fragment on
  Query, spread in the list and detail operations) instead of a client mirror
  of the validator — the mirror had already drifted (ACKNOWLEDGED/SNOOZED now
  only → RESOLVED).
- "Fix with Mingo" fetches the server's `insightChatPrompt` and turns its
  leading `@insight:` / `@device:` markers into labelled mentions; the
  client-side prompt builder is gone. The chat created from that draft carries
  `insightId` on `POST /dialogs` (launcher store link, consumed on create,
  dropped on any change of conversation or a close).
- Every Mingo context reference to an incident (picker item, open view, chip)
  now carries the STORED insight id — what the real `InsightContextResolver`
  looks up — not the Relay global handle.
- Create Ticket from an incident sends `CreateTicketInput.insightId`; the form
  shows the "Assigned Incident" it is filed from (new prefill keys).
- Incident details lists the Mingo sessions started from it
  (`dialogs(filter: { insightId })`), each opening in the drawer.

Requires the #3149 API: the list/detail queries select the new field, so this
must not deploy ahead of it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…nent

openframe-oss-lib#2248 records a ticket filed from an incident as an assignment
owned by the insight (item INSIGHT → target TICKET, from
`CreateTicketInput.insightId`). So:

- The incident page shows its tickets through `AssignedItemsView` pointed at
  the incident (`itemType: INSIGHT`) under an "Assigned Ticket" heading — the
  ticket page's component, not a new table.
- The ticket form shows the incident it is filed from as a read-only
  `AssignmentsField` row (INSIGHT is a client-only target: not pickable, never
  written through `assignItem`; it goes out as `insightId`). The bespoke
  "Assigned Incident" block is gone.
- `AssignmentItemType` gains INSIGHT; `ASSIGNMENT_TARGET_TYPES` stays the
  server list, `ALL_ASSIGNMENT_TARGET_TYPES` adds the client-only target.
- The incident's Mingo-sessions query lives under the `mingo-dialogs` key, so
  the drawer's create invalidates it.

Verified on tenant-3149-53: transitions from the server table (ACKNOWLEDGED
offers only Resolve), Fix with Mingo from `insightChatPrompt` with both chips
resolved by the real resolver, the created dialog linked to the insight and
listed on the incident, Create Ticket → the ticket listed under Assigned Ticket.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@oleksandr-blip
oleksandr-blip requested review from a team as code owners September 21, 2026 08:19
Comment thread src/components/assignments/assignment-row.tsx
Comment thread src/app/(app)/incidents/utils/fix-with-mingo-draft.ts
Comment thread src/app/(app)/mingo/services/mingo-api-service.ts Outdated
oleksandr-blip and others added 5 commits September 21, 2026 11:44
…Open Mingo Session once a chat is linked

The sessions list under the notes is gone; the header's Mingo action reopens
the latest chat started from the incident when there is one, and starts one
otherwise.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ssigned-ticket links; no lookup spinner

- Table rows carry the "chat already started" answer (one aggregate lookup
  query keyed on the page's insight ids, fanning out through `fetchQuery` so it
  shares the per-incident cache the detail header reads) and settle into
  "Open Mingo Session" / "Fix with Mingo" in place — the row data, not the
  column closure, because `DataTableRow` is memoized on the row object.
- The detail header suspends on the lookup instead of showing a spinner, so it
  renders once with the right label.
- Assigned tickets: api-service-core hands the target a Relay global id; the
  ticket pages key on the raw one, so the link said "ticket not found".

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…lookup, one Mingo-button decision

- The dialog↔insight link no longer rides the launcher store (a side-channel
  any dialog create consumed and any conversation switch outside `selectDialog`
  kept): `sendInNewDialog` reads the incident off the first message — the
  `@insight:<id>` token, or an INSIGHT context item — and passes it to
  `createDialog(insightId)` explicitly.
- `useLatestIncidentDialog(s)`: a GraphQL error envelope answers null like a
  transport failure (the header must not fall over on an ai-agent without the
  filter); only drawer-visible statuses count; the aggregate can no longer
  reject; one shared stale time; docs on the hook.
- `mingoActionFor` is the one decision behind the header button and the table
  cell; the row carries the whole action so the memoized `DataTableRow` never
  reads a stale closure. A session row is inert while another prompt is in
  flight; the prompt fetch is guarded by a ref, not stale state.
- `rawIdOf` in `src/lib/relay-id.ts` replaces the inline idiom and the
  assignments-local copy; assigned Ticket targets decode guarded on the
  typename so a raw ObjectId can never be mangled.
- Comments that contradicted the stored-id rule (`context-types.ts`) or named
  a removed section fixed; `AssignmentItemType.INSIGHT` in the schema.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- Query Details had no skeleton and popped in under the notes; it now has the
  same heading over the report table's own loading rows (four columns, one
  row — the common shape), as the Suspense fallback and in the page skeleton.
- The notes skeleton reserved an 80px bar; the loaded section with no notes is
  the heading over the "Add Note" button, so the bar is that button's size.

Measured on a cold load vs loaded: header 96/96, summary card 260/260, notes
56/56; Query Details differs only by the record's own row count.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… the ones after it

Code-review finding: the parser stopped at the first marker of a kind this
build does not know; now it keeps that token in the text and reads on.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@oleksandr-blip

Copy link
Copy Markdown
Contributor Author

@flamingo-review

@github-actions

github-actions Bot commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

🦩 Flamingo Code Review

4 finding(s) — 0 action required · 4 recommended · 0 informational

Mode: advisory · 4 defect(s) outside any rule

Inline comments: 4 new


Need another pass? Commits pushed after this review are not reviewed automatically.

  • Review the new commits — the commits added since this review
  • Review the whole diff again — ignoring what was already reviewed

Prefer typing? Comment @flamingo-review, or @flamingo-review full. To review every push on this pull request, add the flamingo-review-always label.

React 👍/👎 on inline comments to teach the reviewer.

Started 2026-09-21 09:57 UTC · updated 2026-09-21 09:58 UTC · workflow run

Comment thread src/app/(app)/mingo/hooks/use-mingo-unified-chat-state.ts
Comment thread src/app/(app)/incidents/utils/fix-with-mingo-draft.ts
Comment thread src/app/(app)/incidents/hooks/use-fix-with-mingo.ts
Comment thread src/app/(app)/incidents/utils/incident-transform.ts
@oleksandr-blip
oleksandr-blip merged commit 33a47cc into main Sep 21, 2026
10 of 11 checks passed
@oleksandr-blip
oleksandr-blip deleted the feat/incidents-insight-links branch September 21, 2026 16:02
pavlo-flamingo added a commit that referenced this pull request Sep 21, 2026
Conflicts:
- schema.graphql: kept the branch's re-introspected SDL and ported main's
  additions into it (remote access requests from #441; insightChatPrompt,
  insightStatusTransitions and AssignmentItemType.INSIGHT from #438).
- incidents/utils/fix-with-mingo-prompt.ts: took main's deletion. The prompt
  is built server-side now, so the branch's EMPTY_VALUE edit has no target.
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.

2 participants