Skip to content

feat(navigation): rank app searches with jev - #105577

Closed
mariusandra wants to merge 5 commits into
masterfrom
feat/jev-app-search
Closed

mariusandra wants to merge 5 commits into
masterfrom
feat/jev-app-search

Conversation

@mariusandra

@mariusandra mariusandra commented Sep 23, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

The Apps tab only matches app names, so people must know which tool fits their task before searching.
Queries such as “watch a failed checkout” miss useful apps whose descriptions and examples explain that capability.

Changes

The Jev apps search ranks available apps by relevance to the task, using their names, categories, full descriptions, and tooltip examples.

  • Results appear in descending relevance: scores of 0.5+ are prominent, 0.2–0.49 appear muted under “Other apps,” and scores below 0.2 are hidden.
  • Jev treats searches as autocomplete input and infers likely meanings from partial words and unfinished phrases.
  • Clearing the query restores the app catalog and starred apps.
  • Starred apps show the same rich descriptions and examples on hover as the app catalog.
  • Support’s tooltip includes “conversations,” which also gives Jev that search context.
  • Searches debounce while typing and discard stale responses.
  • Provider failures show an explanation and fall back to name matching.
  • Jev uses the existing decisions API with a server-side TypeSafe integration, a five-second timeout, and shared request budgets.
  • Decisions have dedicated, configurable per-user limits of 600/minute and 36,000/hour, separate from the shared AI quota.
  • TypeSafe outbound ceilings are 600/minute and 36,000/hour across the instance, with the normal 10% reserve.
  • Local development enables the demo; cloud access retains the existing US-only ml-inference-decisions flag.

The tooltip and search share the same descriptions, so future tooltip improvements also improve ranking.
The existing gateway does not route Jev; the integration uses TypeSafe's native API through the common egress transport.

Before After
Name filtering Jev ranking

Screenshots use deterministic Storybook responses and a synthetic query.

The search screenshot above shows the original cutoff. The current layout keeps plausible alternatives under “Other apps”:

Ranked results with muted alternatives

Starred apps now share the catalog tooltip:

Starred app tooltip

Before:

flowchart LR
    Query[Search] --> Filter[Match app names] --> Apps[Grouped apps]
    classDef phBlue fill:#1d4aff,stroke:#1d4aff,color:#fff;
    classDef phYellow fill:#f9bd2b,stroke:#f9bd2b,color:#000;
    class Query,Apps phYellow;
    class Filter phBlue;
Loading

After:

flowchart LR
    Query[Search] --> API[Decisions API] --> Jev[TypeSafe Jev]
    Catalog[Descriptions and examples] --> API
    Jev --> Apps[Ranked apps scoring at least 0.2]
    Apps --> Other[Scores below 0.5 appear muted]
    API -->|Unavailable| Fallback[Name matches]
    classDef phRed fill:#f54e00,stroke:#f54e00,color:#fff;
    classDef phYellow fill:#f9bd2b,stroke:#f9bd2b,color:#000;
    classDef phGray fill:#e5e7eb,stroke:#c7ccd1,color:#000;
    class Query,Apps,Other,Fallback phYellow;
    class API,Jev phRed;
    class Catalog phGray;
Loading

How did you test this code?

Local checks passed: scoped Jest and Python suites, frontend TypeScript, repository-wide mypy, scoped security Semgrep, and strict preflight.
CI results and patch coverage are pending.

The throttle update passes the database-free presentation, integration, and egress tests.
Full endpoint tests hit a pre-existing reused test database mismatch: duplicate heatmap table migration, then missing project columns without migrations.
OpenAPI regeneration completed without generated changes.

  • Search tests cover ranking, threshold boundaries, full tooltip context, batching, gating, failures, debounce, and stale responses.
  • Integration tests cover authentication, egress policy, deadlines, missing configuration, and provider errors.
  • Automated browser checks exercised clearing search, dark mode, and 256px/208px sidebar widths; screenshots above show the rendered result.
  • Hover checks confirmed identical starred and catalog tooltip content at both sidebar widths and in dark mode.
  • Updated search tests cover both cutoff boundaries, all-muted results, and no plausible results. Browser checks confirm muted links and tooltips remain usable.
  • New throttle tests cover autocomplete after the shared AI quota is exhausted, configured burst/sustained limits, user isolation, and recovery.
  • Live Jev checks used synthetic queries about checkout debugging, feature rollouts, signup drop-off, and gardening. Relevant queries returned useful apps; gardening returned none.
  • Live partial-query checks ranked Session replay first for “sess” and Feature flags first for “feat fla.”
Local validation commands (outputs retained locally)

All development commands ran through .codex/with-flox.

hogli test products/ml_inference/backend/tests/test_logic.py posthog/egress/test/test_domains.py
env DEBUG=0 hogli test frontend/src/layout/panel-layout/navbar/tabs/navAppsTabLogic.test.ts --runInBand --watchman=false
pnpm --filter=@posthog/frontend typescript:check
uv run mypy --cache-fine-grained .
hogli ci:preflight --fix

Security scan: 28 rules, five changed Python files, zero findings.
The normal pre-push hook also passed strict preflight.

👉 Stay up-to-date with PostHog coding conventions for a smoother review.

Release status

  • No feature flag controls this change
  • This change is behind a feature flag and is not available to users
  • This change makes a previously flagged feature available to everyone

Automatic notifications

  • Publish to changelog?

Docs update

Updated local development documentation with demo configuration, the threshold, and fallback behavior.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Agent: Codex, GPT-6

Tools: shell, Git, GitHub CLI, web lookup, and Playwright. No shareable session link is available.
The open-PR search found Jev integrations for other product surfaces, but no duplicate Apps search PR.
Fixtures and screenshots use repository app metadata and synthetic queries; credentials remain in ignored local configuration.
CodeRabbit CLI was signed out, so this draft has no local CodeRabbit pass.

Skills: writing-ui-components, writing-kea-logics, writing-user-facing-copy, adopting-generated-api-types, routing-outbound-api-calls, migrating-llm-gateway-callers, improving-drf-endpoints, writing-tests, writing-code-comments, setting-feature-flags-in-storybook, hogli, running-ci-preflight, writing-pr-descriptions, reviewing-with-coderabbit.

@mariusandra mariusandra self-assigned this Sep 23, 2026
@trunk-io

trunk-io Bot commented Sep 23, 2026

Copy link
Copy Markdown

Merging to master in this repository is managed by Trunk.

  • To merge this pull request, check the box to the left or comment /trunk merge below.

After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here

@github-actions

github-actions Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

🤖 CI report

⚠️ Trunk lane — backend Python lane

This PR is assigned to the backend Python lane. It runs backend Python tests and may merge in parallel with PRs in other lanes.

⚠️ Complexity (TypeScript) — 6 functions above the limit (max 33)

Cyclomatic complexity above the limit in changed typescript files (10 for production files, 15 for test files). Warn only: worth simplifying when you next touch these functions.

Function Location Complexity Limit
ProjectTree frontend/src/layout/panel-layout/ProjectTree/ProjectTree.tsx:125 33 10
NavAppRow frontend/src/layout/panel-layout/navbar/tabs/NavAppRow.tsx:29 28 10
<anonymous> frontend/src/layout/panel-layout/ProjectTree/ProjectTree.tsx:333 20 10
<anonymous> frontend/src/layout/panel-layout/ProjectTree/ProjectTree.tsx:495 19 10
NavTabApps frontend/src/layout/panel-layout/navbar/tabs/NavTabApps.tsx:16 18 10
<anonymous> frontend/src/layout/panel-layout/ProjectTree/ProjectTree.tsx:266 16 10
✅ Duplication (Python) — clean

New Python code duplication introduced by this branch. Fails at 70+ tokens in app code, or 150+ tokens when both copies live in test files. Advisory while the gate proves itself: extract a shared helper instead of copying.

✅ Duplication (TypeScript) — clean

New TypeScript code duplication introduced by this branch. Fails at 70+ tokens in app code, or 150+ tokens when both copies live in test files. Advisory while the gate proves itself: extract a shared helper instead of copying.

⚠️ Bundle size — 🔺 +19.0 KiB (+0.0%)

Uncompressed size of every built .js bundle, compared against the base branch.

Total: 68.38 MiB · 🔺 +19.0 KiB (+0.0%)

File Size Δ vs base
render-query/src/render-query/render-query.js 20.16 MiB 🔺 +4.5 KiB (+0.0%)
exporter/src/queries/schema.js 1.22 MiB 🔺 +3.9 KiB (+0.3%)
posthog-app/src/queries/schema.js 1.22 MiB 🔺 +3.9 KiB (+0.3%)
posthog-app/src/scenes/AuthenticatedShell.js 269.9 KiB 🔺 +2.8 KiB (+1.1%)
posthog-app/_parent/products/web_analytics/frontend/heatmaps/scenes/heatmaps/HeatmapsScene.js 16.3 KiB 🔺 +2.2 KiB (+15.3%)

Posted automatically by build-bundle-size-report · uncompressed bytes from dist-report

✅ Eager graph — within budget

How much code each root ships on the eager path — downloaded and parsed before the surface is interactive. Measured from the esbuild output chunks (post-tree-shake, static imports only); lazy import() / React.lazy chunks are not counted.

Root Eager (shipped) Δ vs base Budget
entry (logged-out pages, app bootstrap)
src/index.tsx
1.56 MiB · 22 files 🔺 +222 B (+0.0%) ████████░░ 85.0% of 1.84 MiB
logged-out boot: index + App + bootApp (preloaded by every page, including /login)
src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
3.57 MiB · 628 files 🔺 +292 B (+0.0%) █████████░ 88.5% of 4.03 MiB
authenticated shell (every logged-in page)
src/scenes/AuthenticatedShell.tsx
7.50 MiB · 2,432 files 🔺 +3.5 KiB (+0.0%) ████████░░ 78.8% of 9.51 MiB

🟢 node_modules/monaco-editor/ stays out of src/index.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 node_modules/monaco-editor/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/layout/navigation-3000/navigationLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/scenes/dashboard/dashboardLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/lemon-ui/LemonMarkdown/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/RichContentEditor/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/CodeSnippet/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/taxonomy/core-filter-definitions-by-group.json stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 node_modules/monaco-editor/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/session-recordings/player/sessionRecordingPlayerLogic.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx

Largest files eagerly shipped from src/index.tsx
Size File
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
24.6 KiB ../node_modules/.pnpm/buffer@6.0.3/node_modules/buffer/index.js
6.3 KiB ../node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.production.min.js
4.5 KiB ../node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/process.js
3.9 KiB ../node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/cjs/scheduler.production.min.js
1.4 KiB ../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js
1.3 KiB src/index.tsx
1.3 KiB src/RootErrorBoundary.tsx
912 B ../node_modules/.pnpm/ieee754@1.2.1/node_modules/ieee754/index.js
854 B src/scenes/ChunkLoadErrorBoundary.tsx
Largest files eagerly shipped from src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
Size File
301.8 KiB ../node_modules/.pnpm/posthog-js@1.434.11_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
267.6 KiB ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
100.4 KiB src/lib/api.ts
83.9 KiB src/products.tsx
69.1 KiB src/lib/lemon-ui/icons/icons.tsx
63.4 KiB src/lib/utils/eventUsageLogic.ts
38.7 KiB ../node_modules/.pnpm/@dnd-kit+core@6.0.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@dnd-kit/core/dist/core.esm.js
33.9 KiB ../node_modules/.pnpm/kea@4.0.0-pre.6_patch_hash=139b8d1f1304f9d9da452a9a1244c94ea679dbcb85687d8999563146879fb6f5_react@18.3.1/node_modules/kea/lib/index.cjs.js
28.5 KiB src/scenes/scenes.ts
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
Size File
301.8 KiB ../node_modules/.pnpm/posthog-js@1.434.11_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
268.0 KiB src/taxonomy/core-filter-definitions-by-group.json
267.6 KiB ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
153.7 KiB ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
100.4 KiB src/lib/api.ts
98.5 KiB ../packages/quill/packages/quill/dist/index.js
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js
90.6 KiB ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js
83.9 KiB src/products.tsx

Posted automatically by check-eager-graph · sizes are eager output bytes (shipped, post-tree-shake) from the esbuild metafile · part of #32479

✅ Toolbar bundle — eager 2.36 MiB within budget

What the toolbar ships to customer pages, measured from the esbuild output (minified, post-tree-shake). The eager set is the entry plus everything statically imported from it — fetched before any feature runs; deferred chunks load lazily. The eager guardrail is 5.72 MiB. Each output file must also stay below 10 MB, where CloudFront stops compressing it. The module boundary is enforced separately by check-toolbar-graph.

Metric Size Δ vs base Budget
Eager (shipped)
entry + static imports
2.36 MiB · 19 files 🔺 +292 B (+0.0%) ████░░░░░░ 41.3% of 5.72 MiB
Deferred (lazy) 2.09 MiB · 44 files no change n/a — loads on demand
Loader dist/toolbar.js 1.2 KiB no change █░░░░░░░░░ 6.0% of 19.5 KiB
Largest eagerly-shipped chunks
Size File
786.6 KiB dist/toolbar/toolbar-app-WPLXB2KQ.css
650.3 KiB dist/toolbar/chunk-chunk-PK2HFUUK.js
483.6 KiB dist/toolbar/chunk-chunk-EC4CHVWG.js
138.3 KiB dist/toolbar/chunk-chunk-MUASZH4M.js
131.8 KiB dist/toolbar/chunk-chunk-FDH2IBXT.js
75.2 KiB dist/toolbar/toolbar-app-TWI6G23V.js
69.0 KiB dist/toolbar/chunk-chunk-TSAL54PB.js
35.6 KiB dist/toolbar/chunk-chunk-OBXW74UA.js
21.0 KiB dist/toolbar/chunk-chunk-JALPX7MO.js
6.8 KiB dist/toolbar/chunk-chunk-DV7IWQNF.js

Posted automatically by check-toolbar-size · sizes are toolbar output bytes (shipped, post-tree-shake) from the esbuild metafile

✅ Dist folder size — 🔺 +155.9 KiB (+0.0%)

Total size of the built frontend/dist folder (all assets), compared against the base branch.

Total: 1543.47 MiB · 🔺 +155.9 KiB (+0.0%)

@greptile-apps

greptile-apps Bot commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

Retrigger

The production configuration rule must be satisfied before merging; the late-enable empty-result state is a lower-impact frontend defect.

Reviews (1) · Last reviewed commit: "feat(navigation): rank app searches with..."

Comment on lines +115 to +118
if (!search.trim() || !values.jevEnabled) {
return null
}
await breakpoint(250)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Late enablement skips ranking

The ranking loader only runs when setSearch fires. If a user types while preflight or feature flags are still loading, the loader returns null. When Jev later becomes enabled, the UI switches to Jev search without requesting rankings and incorrectly shows “No apps found” until the query is edited. Retrigger ranking when Jev becomes enabled, or keep name filtering active until rankings have been requested.

Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src/layout/panel-layout/navbar/tabs/navAppsTabLogic.ts
Line: 115-118

Comment:
**Late enablement skips ranking**

The ranking loader only runs when `setSearch` fires. If a user types while preflight or feature flags are still loading, the loader returns `null`. When Jev later becomes enabled, the UI switches to Jev search without requesting rankings and incorrectly shows “No apps found” until the query is edited. Retrigger ranking when Jev becomes enabled, or keep name filtering active until rankings have been requested.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Comment thread posthog/settings/web.py Resolved
@coderabbitai

coderabbitai Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: PostHog/posthog/.coderabbit.yaml

Review profile: QUIET

Plan: Enterprise

Run ID: 787d587d-3d29-455a-ac4f-cfdfe0b3e7d9

📥 Commits

Reviewing files that changed from the base of the PR and between 242d6d9 and 7daa1ce.

📒 Files selected for processing (7)
  • docs/published/handbook/engineering/developing-locally.md
  • posthog/egress/typesafe/README.md
  • posthog/egress/typesafe/limiter.py
  • posthog/settings/web.py
  • products/ml_inference/backend/presentation/throttles.py
  • products/ml_inference/backend/presentation/views.py
  • products/ml_inference/backend/tests/test_presentation.py

Included review availability: Your plan provides up to 12 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

The changes add TypeSafe egress settings, budgets, observability, and transport for Jev decision requests. Jev models use that transport, and the apps tab uses returned relevance scores to show ranked search results with loading and failure states. App descriptions and examples supply search inputs and tooltip content. Storybook stories and local-development guidance cover the search experience and setup.

Priority: ➖ Normal

Merge Risk: 🟡 Moderate · up to 7daa1

Slow provider responses may hold a request worker beyond five seconds, and screen-reader users may not hear when an empty search finishes. Resolve or explicitly accept these risks before merging.

🚥 Pre-merge checks | ✅ 1
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The description is complete and follows the required template. It explains the problem, user-visible changes, feature-flag release status, screenshots, documentation updates, automated tests, known te…
✨ Finishing Touches 💡 1
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Note

Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.

🟡 Other comments (1)
frontend/src/layout/panel-layout/navbar/tabs/navAppsTabLogic.ts-114-160 (1)

114-160: 🚀 Performance & Scalability | 🟡 Minor | ⚡ Quick win

Reduce TypeSafe request fan-out for app search.

Each nonblank search sends ceil(allItems.length / 32) TypeSafe requests after the 250 ms debounce. The TypeSafe limiter uses the shared typesafe:account:default bucket across all workers, with defaults of 60 requests per minute and 1,000 per hour. A few users typing with pauses can exhaust this shared budget, causing app search to fall back to text matching.

Use a longer debounce, cache rankings by search term, or allocate a separate budget for this caller.

🧹 Nitpick comments (1)
frontend/src/layout/panel-layout/navbar/tabs/NavTabApps.stories.tsx (1)

35-64: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a story that runs a Jev search. The decide mock is never called as written.

Default, Narrow, Dark, and NameFilter all render with an empty search. For an empty search, the appRankings loader returns null and sends no request. As a result, the decide/ handler is dead code. The ranked "Results", "Finding apps…", and "Jev is unavailable" states have no visual-regression coverage. Add a story that sets a search, for example watch a failed checkout. You can use a play function that types into [data-attr="nav-apps-search"], or dispatch navAppsTabLogic.actions.setSearch in a decorator. Add a failure variant with a decide handler that returns 500. The path instruction requires code with "no superfluous parts".

Also applies to: 77-86

Source: Path instructions


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: PostHog/posthog/.coderabbit.yaml

Review profile: QUIET

Plan: Enterprise

Run ID: 3a114356-8ff4-4892-920d-030b8209e5d4

📥 Commits

Reviewing files that changed from the base of the PR and between eb1b5c8 and 9ad8b87.

📒 Files selected for processing (15)
  • docs/published/handbook/engineering/developing-locally.md
  • frontend/src/layout/panel-layout/ProjectTree/ProjectTree.tsx
  • frontend/src/layout/panel-layout/navbar/tabs/NavAppTooltip.tsx
  • frontend/src/layout/panel-layout/navbar/tabs/NavTabApps.stories.tsx
  • frontend/src/layout/panel-layout/navbar/tabs/NavTabApps.tsx
  • frontend/src/layout/panel-layout/navbar/tabs/appDescriptions.ts
  • frontend/src/layout/panel-layout/navbar/tabs/navAppsTabLogic.test.ts
  • frontend/src/layout/panel-layout/navbar/tabs/navAppsTabLogic.ts
  • posthog/egress/typesafe/README.md
  • posthog/egress/typesafe/limiter.py
  • posthog/egress/typesafe/observability.py
  • posthog/egress/typesafe/transport.py
  • posthog/settings/web.py
  • products/ml_inference/backend/logic/decisions.py
  • products/ml_inference/backend/tests/test_logic.py

Included review availability: Your plan provides up to 12 included reviews per hour; 11 remain after this review.

api_key=settings.TYPESAFE_API_KEY,
body=_wire_body(request),
source="ml_inference",
timeout=min(timeout_seconds, 5.0),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Enforce an overall deadline for Jev requests.

Requests treats timeout=5.0 as a socket-inactivity limit, not a five-second limit for the complete response. If the provider continues sending bytes within each read interval, the synchronous call can occupy a worker for longer than the intended cap. Enforce a total request deadline, including response-body consumption. (requests.readthedocs.io)

@trunk-io

trunk-io Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

Static Badge   Static Badge   Static Badge

View Full Report ↗︎ ⋅ Docs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to GitHub limitations.

⚠️ Outside diff range comments (1)

🟡 Minor · Keep the empty-result live region mounted. · NavTabApps.tsx:108

frontend/src/layout/panel-layout/navbar/tabs/NavTabApps.tsx:108
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Keep the empty-result live region mounted.

When a Jev search resolves with no matches, the loading status is removed and the empty message is mounted as new content. NavTabSection keeps its panel mounted, but it does not provide a live region or move focus. Adding role="status" only to the conditional paragraph is not sufficient because a populated live region that appears later may not be announced.

Keep a status region mounted and update its contents:

Suggested fix
-                    {groupedItems.length === 0 && !(isJevSearch && appRankingsLoading) && (
-                        <p className="text-xs text-tertiary px-2 py-2">No apps found. Try a different search.</p>
-                    )}
+                    <div role="status" aria-live="polite">
+                        {groupedItems.length === 0 && !(isJevSearch && appRankingsLoading) && (
+                            <p className="text-xs text-tertiary px-2 py-2">
+                                No apps found. Try a different search.
+                            </p>
+                        )}
+                    </div>

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: PostHog/posthog/.coderabbit.yaml

Review profile: QUIET

Plan: Enterprise

Run ID: d3e3dfc6-6d0b-4701-ba63-413885671070

📥 Commits

Reviewing files that changed from the base of the PR and between 9ad8b87 and 242d6d9.

📒 Files selected for processing (8)
  • docs/published/handbook/engineering/developing-locally.md
  • frontend/src/layout/panel-layout/navbar/tabs/NavAppRow.tsx
  • frontend/src/layout/panel-layout/navbar/tabs/NavTabApps.stories.tsx
  • frontend/src/layout/panel-layout/navbar/tabs/NavTabApps.tsx
  • frontend/src/layout/panel-layout/navbar/tabs/appDescriptions.ts
  • frontend/src/layout/panel-layout/navbar/tabs/appsCatalog.ts
  • frontend/src/layout/panel-layout/navbar/tabs/navAppsTabLogic.test.ts
  • frontend/src/layout/panel-layout/navbar/tabs/navAppsTabLogic.ts

Included review availability: Your plan provides up to 12 included reviews per hour; 10 remain after this review.

@posthog

posthog Bot commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

👋 Visual changes detected for this PR.

Review and approve in PostHog Visual Review

If these changes are unexpected, they may be caused by a flaky test or a broken snapshot on master. Don't approve — rerun the job or wait for a fix.

@webjunkie

Copy link
Copy Markdown
Contributor

Agent-drafted heads-up, posted from @webjunkie's account on behalf of DevEx.

#105784 is in the merge queue and adds one shared posthog/egress/typesafe/ domain, so this PR and four others stop each shipping their own copy. Once it lands, please rebase onto it and drop your posthog/egress/typesafe/ files and TYPESAFE_* settings.

The domain README also has a usage policy for TypeSafe that every caller has to meet before merge: behind a feature flag that only PostHog staff can see, no customer data during the experiment, and before any launch that sends customer data, an explicit per-customer opt-in (approved copy TBD) plus sign-off from leadership.

Changes for this PR:

  • typesafe_request(api_key=, body=, source=, timeout=) → typesafe_request("POST", "https://api.typesafe.ai/v1/systemone", api_key=, source=, endpoint="/v1/systemone", priority=Priority.NORMAL, timeout=, json=body, allow_redirects=False). The decisions API passes arbitrary question maps, so the raw helper fits better than system_one.
  • Hourly default is 20,000 (yours was 36,000). Raise it with TYPESAFE_EGRESS_HOURLY_BUDGET if sustained typing needs it.
  • Policy: search queries are text that users type, which counts as customer data. It needs the staff-only flag, and no customer rollout until opt-in and sign-off.

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