Skip to content

Harden CAD integration: fix facts write-back & crashes, align types with desktop API, add tests#4

Open
Henrik Cullen (hccullen) wants to merge 8 commits into
masterfrom
feat/grouped-fvc-custom-properties
Open

Harden CAD integration: fix facts write-back & crashes, align types with desktop API, add tests#4
Henrik Cullen (hccullen) wants to merge 8 commits into
masterfrom
feat/grouped-fvc-custom-properties

Conversation

@hccullen

@hccullen Henrik Cullen (hccullen) commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Summary

Started as a gap analysis of the README vs the code and grew into a broader hardening pass. Fixes real bugs (including ones that crashed the process against the live desktop app), aligns the TypeScript types 1:1 with the desktop app API, simplifies configuration, and adds a real test suite. Verified end-to-end against the live desktop app (api.try.motocorti.io).

Fixes & hardening

  • Facts write-back was broken. The openCortiSession path sent the desktop app's setFactValues the wrong shape (raw { factValues }, no sessionID). Now forwarded correctly as { sessionID, facts } on all session paths (new session + active re-entry + DB re-entry).
  • Process crashes. openSession blew up the whole process when /realtime/activeSessions returned an unexpected shape (seen live when the desktop app was mid-shell.quit). Now defaults defensively and both session handlers try/catch → return 502 instead of dying.
  • action-block-triggered was silent. The handler only logged inside the customProperties loop and assumed the field always exists — a block with no/empty custom properties produced nothing (and could throw, swallowed by the controller). Now always logs the trigger (label falls back namecontentid), tolerates missing customProperties, and only patches facts when present.
  • /health liveness probe implemented; app.ts split from index.ts so the app can be mounted in tests without binding a port.
  • leaveSession forwards the documented sessionID param when provided.

Types (1:1 with DESKTOP_APP_API.md)

  • Added src/types/shared.ts mirroring the shared types (Session, CustomProperty, Fact, UserTypeSerialized).
  • Fixed collectedFactValues to Fact[] (was { factID, value }); CurrentUserResponse = UserTypeSerialized.
  • Added DESKTOP_APP_API.md as the reference catalog.

Config

  • Replaced the per-host API_KEY_<ENV> derivation with a single API_KEY (one integration instance serves one environment).
  • Removed the unused node-fetch dependency.

Tests

  • Unit + integration tests on the Node test runner. Integration boots the real app against a stub desktop app and asserts the setFactValues shape plus a regression for the malformed-activeSessions crash. 15/15 passing.
  • Added test:unit / test:integration / test:grouped-fvc / test:e2e scripts and a live e2e script.
  • Fixed test-manual-flow.js to actually stay alive until Ctrl+C.

Docs

  • Rewrote the README to match the code: environments model (<env>.corti.app frontend vs api.<env>.motocorti.io API, per-customer, no shared prod/dev), response codes, /health, single API_KEY, updated project structure, and types pointing at DESKTOP_APP_API.md.

Verification

  • npm test → 15/15.
  • Live e2e against the desktop app: open → write-facts → leave, and action-block-triggered now logs on real triggers.

🤖 Generated with Claude Code

Bug fixes:
- eventsController: add missing break after handleSessionCaseIDChanged,
  preventing silent fallthrough into session-opened/closed cases
- eventsController: log session-opened, session-closed, app.login/logout
  and unknown events (previously all silently swallowed)
- sessionController: leaveSession was calling /realtime/enterSession
  instead of /realtime/leaveSession
- utils: /app/unhideAllAndFocus -> /window/unhideAllAndFocus (wrong
  callMethod prefix; window endpoints live under /window/)
- cortiServices: replace manual REST fetch in updateCaseCustomProperties
  with /backendproxy/cases/ensureCaseCustomProperties callMethod, removing
  direct API key handling
- handleGroupedFlowValueCollectorBlocksUpdated: log blocks with empty
  displayValues instead of silently skipping them
- handleSessionCaseIDChanged: log case ID changes (was fire-and-forget
  with no observable output)

Add test-manual-flow.js: lightweight script that opens a session via
/openCortiSession (simulating a CAD dispatch) and prints a step-by-step
checklist for manual event verification against the live desktop app.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 30, 2026 16:02

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes several integration event-handling issues (switch fallthrough, wrong callMethod routes) and improves observability by logging key session events and surfacing grouped Flow Value Collector (FVC) custom properties, plus adds a lightweight manual verification script.

Changes:

  • Fixes incorrect callMethod routes for window focus and leaving sessions; routes case custom property updates through backendproxy callMethod.
  • Improves event handling/logging (adds missing break, logs session-open/close, logs case-id-changed, logs empty FVC blocks, logs collector custom properties).
  • Adds test-manual-flow.js to simulate CAD dispatch behavior and provide a manual verification checklist.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
test-manual-flow.js Adds a manual flow script to open/leave sessions and guide verification of emitted events/logs.
src/utils/utils.ts Updates window focus callMethod to /window/unhideAllAndFocus.
src/services/cortiServices.ts Switches case custom property updates to backendproxy callMethod.
src/eventHandlers/handleSessionCaseIDChanged.ts Adds logging when a session’s case ID changes.
src/eventHandlers/handleGroupedFlowValueCollectorBlocksUpdated.ts Logs empty collector blocks and surfaces/dedupes collector custom properties for logging.
src/controllers/sessionController.ts Fixes leaveSession to call /realtime/leaveSession.
src/controllers/eventsController.ts Fixes switch fallthrough and adds logging for session/app events and unhandled events.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/services/cortiServices.ts Outdated
Comment thread src/controllers/eventsController.ts Outdated
Henrik Cullen (hccullen) and others added 6 commits June 30, 2026 18:05
Keep test-grouped-flow-value-collector-blocks-updated.js — tests the FVC
handler with synthetic payloads, no live Corti session needed. Deleted
test-session-flow.js and its copy, which were superseded by
test-manual-flow.js in the previous commit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces the sparse original with:
- Architecture diagram showing the two-port model (45002 integration,
  45001 desktop app callMethod RPC)
- Full callMethod endpoint reference table
- Documented request/response shapes for /openCortiSession and /events
- Per-event-handler explanation with example log output and customisation hints
- Configuration, running, and testing instructions covering both test scripts
- Extension guide for adding new event handlers and CAD endpoints

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Restructures the docs around the developer journey for a CAD vendor
building an integration to Corti Triage:
- Opens with what you are building and why, not what the code does
- Two clear integration points: /openCortiSession when a call comes in,
  /events to receive updates back
- Per-handler "what you receive / what to do instead" pattern showing
  exactly which console.log to replace and with what
- Explains the customProperties field-mapping pattern for FVC blocks
- Moves callMethod reference and project structure to the bottom as
  supporting material rather than the main narrative

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Title: 'Sample CAD Integration' -> 'CAD Integration' (it's an example, not a sample)
- Diagram: remove separate CAD box (implied by the endpoints); show only
  this integration <-> Corti Desktop App
- Make session creation order explicit: startSession (creates) comes
  before enterSession (opens in UI), with annotations on each step

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Restructures the doc to mirror the test-manual-flow.js sequence:
dispatch → session opens → events arrive → call ends. Adds a new
section explaining the session-open logic (active/DB/new), shows
actual terminal log output for each event handler alongside the
TODO replacement examples, and corrects the architecture diagram
to accurately reflect when setFactValues is called.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fixes and hardening
- Fix facts write-back: forward CAD `factValues` to setFactValues as
  `{ sessionID, facts }` on all session paths (new + re-entry); previously
  the openSession path sent the wrong shape with no sessionID.
- Guard openSession against malformed `activeSessions` responses and wrap
  both session handlers in try/catch (return 502 instead of crashing).
- action-block handler: always log the trigger (falling back name -> content
  -> id), tolerate missing customProperties, only patch facts when present.
- Implement GET /health liveness probe; split app.ts from index.ts so the
  app can be mounted in tests without binding a port.
- leaveSession forwards the documented `sessionID` param when provided.

Types
- Add src/types/shared.ts mirroring the desktop API shared types
  (Session, CustomProperty, Fact, UserTypeSerialized) 1:1.
- Fix collectedFactValues to Fact[]; CurrentUserResponse = UserTypeSerialized.

Config
- Replace per-host API_KEY_<ENV> derivation with a single API_KEY.
- Drop unused node-fetch dependency.

Tests
- Add unit + integration tests (Node test runner); integration boots the app
  against a stub desktop app and asserts the setFactValues shape and the
  malformed-activeSessions regression. Add test:* npm scripts and a live
  e2e script. Fix the manual-flow script to stay alive until Ctrl+C.

Docs
- Add DESKTOP_APP_API.md reference; rewrite README to match (environments
  model, response codes, /health, single API_KEY, project structure, types).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@hccullen Henrik Cullen (hccullen) changed the title Fix event handling bugs and surface grouped FVC custom properties Harden CAD integration: fix facts write-back & crashes, align types with desktop API, add tests Jun 30, 2026
- updateCaseCustomProperties now returns the cortiCallMethod promise so
  callers can await completion and observe failures; guard the caller in
  handleSessionCaseIDChanged with try/catch to avoid unhandled rejections.
- Default event handler no longer logs the full event data (potential PII) —
  logs only the event name and session/external IDs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 21 out of 22 changed files in this pull request and generated 4 comments.

Comment thread src/utils/utils.ts
Comment on lines 23 to +26
cortiCallMethod("/realtime/enterSession", {
sessionID,
}).then(() => {
cortiCallMethod("/app/unhideAllAndFocus");
if (facts) {
cortiCallMethod("/realtime/session/setFactValues", facts);
cortiCallMethod("/window/unhideAllAndFocus");
Comment thread src/services/cortiServices.ts Outdated
Comment on lines +38 to +41
cortiCallMethod("/backendproxy/cases/ensureCaseCustomProperties", {
caseID: caseId,
customProperties: customPropertiesBody,
});
Comment on lines +47 to +53
// Patch session with new facts (only when the block carried any).
if (factUpdateBody.length) {
cortiCallMethod('/realtime/session/setFactValues', {
sessionID: session.id,
facts: factUpdateBody,
});
}
Comment on lines 32 to 34
default:
// console.log(data);
console.log(`Unhandled event: ${event.name}`, data);
break;
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