Skip to content

Dev to main#35

Closed
djanogly wants to merge 99 commits intomainfrom
dev
Closed

Dev to main#35
djanogly wants to merge 99 commits intomainfrom
dev

Conversation

@djanogly
Copy link
Copy Markdown
Contributor

No description provided.

djanogly and others added 25 commits March 11, 2026 13:13
Broader fix for calling makeFunctionReference inside components
* complete proposal reduce convex ref escape hatches

* Stop makeFunctionReference being defined inside components (#17)

Broader fix for calling makeFunctionReference inside components

* complete proposal reduce convex ref escape hatches

* harden types
* complete proposal for expanding widget convex wrapper hooks

* include generic typed calls to makeFunctionReference
Move and update docs
…ing-ref-factories

sdk-core string ref replacements
…al-convex-wrapper-hooks

introduce-mobile-local-convex-wrapper-hooks
* Manual edits to email capture widget (+ CI summary labels text)

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Djanogly <45178753+djanogly@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…TBC) (#24)

* Add file uploads - UI needs work

* improve styling, remove Snippets button

* Update unit tests

* skip dismiss email collection test

* fallback and tweaks

* Limit filetypes

Partially completed - the upload spoofing hardening is improved, but not all the way to magic-byte sniffing. We now require an allowlisted extension from the normalized filename on both the client and backend in supportAttachments.ts (line 70) and supportAttachments.ts (line 57), and added regression coverage in supportAttachments.test.ts (line 151) and supportAttachments.test.ts (line 8). I did not add signature checks, because the current finalizeUpload boundary is a Convex mutation and ctx.storage.get() is only available in actions. Doing true magic-byte validation would need a larger refactor of that finalize flow.
* Proper AI knowledge handling with Mastra

* feat: replace legacy AI agent knowledge retrieval with Convex Vector Search

* docs: update spec to mention convex instead of mastra

* docs: archive use-convex-vector-search and update main specs

* fix: use existing Vercel AI Gateway client for embedding generation

* fix: retrieve full embedding document in aiAgentActionsKnowledge to access contentType and contentId

* working AI agent and suggestions

* Fixes for Typing gaps, unused ref, invalid vector filter chaining

Unused ref warning in packages/convex/convex/embeddings.ts
Invalid vector filter chaining in packages/convex/convex/suggestions.ts

* harden types

* update AGENTS.md
* Add embedding refresh button

* Tighten permissions
…#29)

* insert links to knowledge base from admin chat, and use vector search

* Encourage checks in AGENTS, update dependency allowlist
* Use any model for AI Agent

* restrict embedding model choice to vectors with 1536 dimensions, not 3072.

* fix tests

* Address type issues etc

* Address typing issues etc. add docs, tests and display the models in UI

* make error in fetching models explicit

* update deps

* Fix playwright tests
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 16, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
opencom-landing Ready Ready Preview, Comment Apr 16, 2026 10:18pm
opencom-web Ready Ready Preview, Comment Apr 16, 2026 10:18pm

@qodo-code-review
Copy link
Copy Markdown

Review Summary by Qodo

Modularize codebase, fix campaign deletion bug, and enhance settings/survey utilities

✨ Enhancement 🐞 Bug fix 🧪 Tests

Grey Divider

Walkthroughs

Description
• Fixed infinite loop in email campaign deletion by adding explicit batch size tracking in
  emailCampaigns.ts
• Refactored large monolithic files into modular, domain-specific submodules:
  - testData.ts reduced from 3356 to 24 lines by extracting mutations into separate files
  - series.ts split into three focused submodules (authoring, runtime, telemetry)
  - testing/helpers.ts reorganized into domain-specific helper modules
  - workspaces.ts extracted hosted onboarding logic into dedicated files
• Introduced authMutation wrapper to simplify authentication and permission checks in mutation
  handlers
• Added new settings page Convex data fetching hook (useSettingsPageConvex.ts) centralizing
  workspace settings queries and mutations
• Added survey answer validation utility functions (surveyOverlay/answers.ts) for type checking
  and normalization
• Added landing page demo data seeding mutations with comprehensive knowledge base articles and
  messenger configuration
• Simplified E2E test setup by removing conditional workspace policy manipulation
• Maintained backward compatibility across all refactored modules by preserving public API exports
Diagram
flowchart LR
  A["Monolithic Files<br/>testData, series, helpers,<br/>workspaces"] -->|"Extract & Modularize"| B["Domain-Specific<br/>Submodules"]
  C["Campaign Deletion<br/>Infinite Loop"] -->|"Fix Batch Tracking"| D["Corrected Loop Logic"]
  E["Settings & Survey<br/>Requirements"] -->|"Add New Utilities"| F["useSettingsPageConvex<br/>Survey Validators"]
  B --> G["Improved Maintainability<br/>& Code Organization"]
  D --> G
  F --> G
Loading

Grey Divider

File Changes

1. packages/convex/convex/testData.ts Refactoring +22/-3354

Refactor test data mutations into modular subfiles

• Refactored monolithic test data file by extracting mutation implementations into separate modular
 files (seeds, cleanup, demoWorkspace, landing)
• Converted file to a re-export hub that imports and exposes mutations from organized submodules
• Reduced file from 3356 lines to 24 lines, improving maintainability and code organization
• Maintains backward compatibility by preserving all public mutation exports

packages/convex/convex/testData.ts


2. apps/web/src/app/settings/hooks/useSettingsPageConvex.ts ✨ Enhancement +170/-0

Add settings page Convex data fetching hook

• New custom hook that centralizes workspace settings data fetching and mutations
• Defines TypeScript types for workspace settings, email config, AI settings, automation settings,
 and security access records
• Implements useWebQuery and useWebMutation hooks for 8 different queries and 4 mutations
 related to workspace configuration
• Provides single interface for accessing workspace members, pending invitations, email
 configuration, AI/automation settings, and security access

apps/web/src/app/settings/hooks/useSettingsPageConvex.ts


3. packages/convex/convex/testing/helpers.ts Refactoring +100/-2618

Refactor testing helpers into modular domain-specific files

• Refactored monolithic 2600+ line file into modular helper imports from separate files
• Exports now re-export functions from dedicated helper modules (series, workspace, conversations,
 notifications, content, email, tickets, ai, cleanup, supportAttachments)
• Maintains backward compatibility by preserving all public API exports with same signatures
• Reduces file complexity while organizing test helpers by domain

packages/convex/convex/testing/helpers.ts


View more (107)
4. packages/convex/convex/workspaces.ts Refactoring +118/-475

Extract hosted onboarding logic and simplify auth patterns

• Extracted hosted onboarding logic into separate workspaceHostedOnboardingMutations.ts and
 workspaceHostedOnboardingQueries.ts files
• Introduced authMutation wrapper to simplify authentication and permission checks in mutation
 handlers
• Refactored getPublicWorkspaceContext query to support filtering by workspaceId or
 articleSlug with public content validation
• Simplified mutation handlers by removing repetitive auth/permission boilerplate using
 authMutation helper

packages/convex/convex/workspaces.ts


5. apps/web/e2e/public-pages.spec.ts 🧪 Tests +4/-33

Simplify public pages E2E test setup

• Removed conditional test setup that updated help center access policy based on admin secret
• Removed imports for getPublicWorkspaceContext and updateHelpCenterAccessPolicy test helpers
• Added comment explaining that /help route resolves default public workspace and multi-workspace
 policy boundaries are covered by backend tests
• Simplified test initialization by removing workspace policy manipulation

apps/web/e2e/public-pages.spec.ts


6. apps/widget/src/surveyOverlay/answers.ts ✨ Enhancement +37/-0

Add survey answer validation utility functions

• New file with utility functions for survey answer validation and normalization
• Exports isSurveyAnswerPrimitive to check for primitive types (null, string, number, boolean)
• Exports isStringOrNumberArray to validate arrays of strings or numbers
• Exports normalizeSurveyAnswerValue to coerce unknown values to valid SurveyAnswerValue type

apps/widget/src/surveyOverlay/answers.ts


7. packages/convex/convex/series.ts Refactoring +28/-2429

Refactor series module into three focused submodules

• Refactored large monolithic file into modular exports from three separate submodules
 (series/authoring, series/runtime, series/telemetry)
• Removed ~2400 lines of implementation code (validators, helpers, core logic functions)
• Kept only re-export statements that delegate to the new modular structure
• Maintains backward compatibility by preserving all public API exports

packages/convex/convex/series.ts


8. packages/convex/convex/testData/landing.ts 🧪 Tests +1079/-0

Add landing page demo data seeding mutations

• Added new test data seeding module with cleanupLandingDemo and seedLandingDemo mutations
• Implements idempotent landing page demo content generation including tours, checklists, articles,
 collections, outbound messages, surveys, and tooltips
• Includes comprehensive knowledge base articles with links to canonical documentation
• Configures messenger settings with branding and welcome message for demo workspace

packages/convex/convex/testData/landing.ts


9. packages/convex/convex/emailCampaigns.ts 🐞 Bug fix +3/-5

Fix infinite loop in email campaign deletion

• Fixed infinite loop in campaign deletion by adding explicit batch size tracking
• Changed loop condition from while (true) to `while (recipientsCount ===
 RECIPIENT_DELETE_BATCH_SIZE)`
• Added recipientsCount variable to track actual number of recipients fetched in each iteration

packages/convex/convex/emailCampaigns.ts


10. .agents/skills/convex-create-component/SKILL.md Additional files +288/-0

...

.agents/skills/convex-create-component/SKILL.md


11. .agents/skills/convex-create-component/agents/openai.yaml Additional files +10/-0

...

.agents/skills/convex-create-component/agents/openai.yaml


12. .agents/skills/convex-create-component/references/advanced-patterns.md Additional files +134/-0

...

.agents/skills/convex-create-component/references/advanced-patterns.md


13. .agents/skills/convex-create-component/references/hybrid-components.md Additional files +37/-0

...

.agents/skills/convex-create-component/references/hybrid-components.md


14. .agents/skills/convex-create-component/references/local-components.md Additional files +38/-0

...

.agents/skills/convex-create-component/references/local-components.md


15. .agents/skills/convex-create-component/references/packaged-components.md Additional files +51/-0

...

.agents/skills/convex-create-component/references/packaged-components.md


16. .agents/skills/convex-migration-helper/SKILL.md Additional files +149/-0

...

.agents/skills/convex-migration-helper/SKILL.md


17. .agents/skills/convex-migration-helper/agents/openai.yaml Additional files +10/-0

...

.agents/skills/convex-migration-helper/agents/openai.yaml


18. .agents/skills/convex-migration-helper/references/migration-patterns.md Additional files +231/-0

...

.agents/skills/convex-migration-helper/references/migration-patterns.md


19. .agents/skills/convex-migration-helper/references/migrations-component.md Additional files +169/-0

...

.agents/skills/convex-migration-helper/references/migrations-component.md


20. .agents/skills/convex-performance-audit/SKILL.md Additional files +143/-0

...

.agents/skills/convex-performance-audit/SKILL.md


21. .agents/skills/convex-performance-audit/agents/openai.yaml Additional files +10/-0

...

.agents/skills/convex-performance-audit/agents/openai.yaml


22. .agents/skills/convex-performance-audit/references/function-budget.md Additional files +232/-0

...

.agents/skills/convex-performance-audit/references/function-budget.md


23. .agents/skills/convex-performance-audit/references/hot-path-rules.md Additional files +369/-0

...

.agents/skills/convex-performance-audit/references/hot-path-rules.md


24. .agents/skills/convex-performance-audit/references/occ-conflicts.md Additional files +114/-0

...

.agents/skills/convex-performance-audit/references/occ-conflicts.md


25. .agents/skills/convex-performance-audit/references/subscription-cost.md Additional files +252/-0

...

.agents/skills/convex-performance-audit/references/subscription-cost.md


26. .agents/skills/convex-quickstart/SKILL.md Additional files +347/-0

...

.agents/skills/convex-quickstart/SKILL.md


27. .agents/skills/convex-quickstart/agents/openai.yaml Additional files +10/-0

...

.agents/skills/convex-quickstart/agents/openai.yaml


28. .agents/skills/convex-setup-auth/SKILL.md Additional files +150/-0

...

.agents/skills/convex-setup-auth/SKILL.md


29. .agents/skills/convex-setup-auth/agents/openai.yaml Additional files +10/-0

...

.agents/skills/convex-setup-auth/agents/openai.yaml


30. .agents/skills/convex-setup-auth/references/auth0.md Additional files +116/-0

...

.agents/skills/convex-setup-auth/references/auth0.md


31. .agents/skills/convex-setup-auth/references/clerk.md Additional files +113/-0

...

.agents/skills/convex-setup-auth/references/clerk.md


32. .agents/skills/convex-setup-auth/references/convex-auth.md Additional files +143/-0

...

.agents/skills/convex-setup-auth/references/convex-auth.md


33. .agents/skills/convex-setup-auth/references/workos-authkit.md Additional files +114/-0

...

.agents/skills/convex-setup-auth/references/workos-authkit.md


34. .github/workflows/ci.yml Additional files +63/-1

...

.github/workflows/ci.yml


35. AGENTS.md Additional files +574/-0

...

AGENTS.md


36. CLAUDE.md Additional files +7/-0

...

CLAUDE.md


37. CONTRIBUTING.md Additional files +11/-1

...

CONTRIBUTING.md


38. ROADMAP.md Additional files +168/-6

...

ROADMAP.md


39. apps/landing/package.json Additional files +1/-1

...

apps/landing/package.json


40. apps/mobile/app/(app)/conversation/[id].tsx Additional files +18/-36

...

apps/mobile/app/(app)/conversation/[id].tsx


41. apps/mobile/app/(app)/index.tsx Additional files +9/-34

...

apps/mobile/app/(app)/index.tsx


42. apps/mobile/app/(app)/onboarding.tsx Additional files +12/-16

...

apps/mobile/app/(app)/onboarding.tsx


43. apps/mobile/app/(app)/settings.tsx Additional files +16/-27

...

apps/mobile/app/(app)/settings.tsx


44. apps/mobile/app/_layout.tsx Additional files +2/-2

...

apps/mobile/app/_layout.tsx


45. apps/mobile/package.json Additional files +1/-1

...

apps/mobile/package.json


46. apps/mobile/src/contexts/AuthContext.tsx Additional files +13/-34

...

apps/mobile/src/contexts/AuthContext.tsx


47. apps/mobile/src/contexts/NotificationContext.tsx Additional files +14/-13

...

apps/mobile/src/contexts/NotificationContext.tsx


48. apps/mobile/src/hooks/convex/types.ts Additional files +175/-0

...

apps/mobile/src/hooks/convex/types.ts


49. apps/mobile/src/hooks/convex/useAuthConvex.ts Additional files +79/-0

...

apps/mobile/src/hooks/convex/useAuthConvex.ts


50. apps/mobile/src/hooks/convex/useConversationConvex.ts Additional files +95/-0

...

apps/mobile/src/hooks/convex/useConversationConvex.ts


51. apps/mobile/src/hooks/convex/useInboxConvex.ts Additional files +49/-0

...

apps/mobile/src/hooks/convex/useInboxConvex.ts


52. apps/mobile/src/hooks/convex/useNotificationRegistrationConvex.ts Additional files +37/-0

...

apps/mobile/src/hooks/convex/useNotificationRegistrationConvex.ts


53. apps/mobile/src/hooks/convex/useOnboardingConvex.ts Additional files +61/-0

...

apps/mobile/src/hooks/convex/useOnboardingConvex.ts


54. apps/mobile/src/hooks/convex/useSettingsConvex.ts Additional files +137/-0

...

apps/mobile/src/hooks/convex/useSettingsConvex.ts


55. apps/mobile/src/lib/convex/hooks.ts Additional files +59/-0

...

apps/mobile/src/lib/convex/hooks.ts


56. apps/mobile/src/typeHardeningGuard.test.ts Additional files +181/-0

...

apps/mobile/src/typeHardeningGuard.test.ts


57. apps/web/e2e/SKIP_REGISTRY.md Additional files +0/-2

...

apps/web/e2e/SKIP_REGISTRY.md


58. apps/web/e2e/ai-agent-settings.spec.ts Additional files +21/-18

...

apps/web/e2e/ai-agent-settings.spec.ts


59. apps/web/e2e/auth.spec.ts Additional files +5/-3

...

apps/web/e2e/auth.spec.ts


60. apps/web/e2e/carousels.spec.ts Additional files +1/-4

...

apps/web/e2e/carousels.spec.ts


61. apps/web/e2e/csat.spec.ts Additional files +19/-12

...

apps/web/e2e/csat.spec.ts


62. apps/web/e2e/fixtures.ts Additional files +12/-1

...

apps/web/e2e/fixtures.ts


63. apps/web/e2e/global-teardown.ts Additional files +1/-1

...

apps/web/e2e/global-teardown.ts


64. apps/web/e2e/helpers/auth-refresh.ts Additional files +238/-38

...

apps/web/e2e/helpers/auth-refresh.ts


65. apps/web/e2e/helpers/storage-state.ts Additional files +97/-0

...

apps/web/e2e/helpers/storage-state.ts


66. apps/web/e2e/helpers/test-data.ts Additional files +5/-1

...

apps/web/e2e/helpers/test-data.ts


67. apps/web/e2e/helpers/widget-helpers.ts Additional files +86/-13

...

apps/web/e2e/helpers/widget-helpers.ts


68. apps/web/e2e/home-settings.spec.ts Additional files +63/-97

...

apps/web/e2e/home-settings.spec.ts


69. apps/web/e2e/inbox.spec.ts Additional files +33/-6

...

apps/web/e2e/inbox.spec.ts


70. apps/web/e2e/knowledge.spec.ts Additional files +50/-320

...

apps/web/e2e/knowledge.spec.ts


71. apps/web/e2e/outbound.spec.ts Additional files +8/-6

...

apps/web/e2e/outbound.spec.ts


72. apps/web/e2e/reports.spec.ts Additional files +1/-12

...

apps/web/e2e/reports.spec.ts


73. apps/web/e2e/snippets.spec.ts Additional files +1/-3

...

apps/web/e2e/snippets.spec.ts


74. apps/web/e2e/tooltips.spec.ts Additional files +30/-4

...

apps/web/e2e/tooltips.spec.ts


75. apps/web/e2e/widget-features.spec.ts Additional files +157/-74

...

apps/web/e2e/widget-features.spec.ts


76. apps/web/e2e/widget.spec.ts Additional files +21/-9

...

apps/web/e2e/widget.spec.ts


77. apps/web/next.config.js Additional files +1/-13

...

apps/web/next.config.js


78. apps/web/package.json Additional files +4/-4

...

apps/web/package.json


79. apps/web/src/app/articles/ArticlesImportSection.tsx Additional files +355/-0

...

apps/web/src/app/articles/ArticlesImportSection.tsx


80. apps/web/src/app/articles/ArticlesListSection.tsx Additional files +265/-0

...

apps/web/src/app/articles/ArticlesListSection.tsx


81. apps/web/src/app/articles/DeleteArticleDialog.tsx Additional files +49/-0

...

apps/web/src/app/articles/DeleteArticleDialog.tsx


82. apps/web/src/app/articles/[id]/page.test.tsx Additional files +298/-0

...

apps/web/src/app/articles/[id]/page.test.tsx


83. apps/web/src/app/articles/[id]/page.tsx Additional files +138/-46

...

apps/web/src/app/articles/[id]/page.tsx


84. apps/web/src/app/articles/articlesAdminTypes.ts Additional files +113/-0

...

apps/web/src/app/articles/articlesAdminTypes.ts


85. apps/web/src/app/articles/articlesAdminUtils.test.ts Additional files +85/-0

...

apps/web/src/app/articles/articlesAdminUtils.test.ts


86. apps/web/src/app/articles/articlesAdminUtils.ts Additional files +181/-0

...

apps/web/src/app/articles/articlesAdminUtils.ts


87. apps/web/src/app/articles/collections/page.tsx Additional files +8/-14

...

apps/web/src/app/articles/collections/page.tsx


88. apps/web/src/app/articles/hooks/useArticleCollectionsConvex.ts Additional files +60/-0

...

apps/web/src/app/articles/hooks/useArticleCollectionsConvex.ts


89. apps/web/src/app/articles/hooks/useArticleEditorConvex.ts Additional files +120/-0

...

apps/web/src/app/articles/hooks/useArticleEditorConvex.ts


90. apps/web/src/app/articles/hooks/useArticlesAdminConvex.ts Additional files +170/-0

...

apps/web/src/app/articles/hooks/useArticlesAdminConvex.ts


91. apps/web/src/app/articles/page.tsx Additional files +220/-745

...

apps/web/src/app/articles/page.tsx


92. apps/web/src/app/audit-logs/page.tsx Additional files +1/-1

...

apps/web/src/app/audit-logs/page.tsx


93. apps/web/src/app/campaigns/carousels/[id]/page.tsx Additional files +15/-29

...

apps/web/src/app/campaigns/carousels/[id]/page.tsx


94. apps/web/src/app/campaigns/email/[id]/page.tsx Additional files +7/-15

...

apps/web/src/app/campaigns/email/[id]/page.tsx


95. apps/web/src/app/campaigns/hooks/useCampaignsPageConvex.ts Additional files +156/-0

...

apps/web/src/app/campaigns/hooks/useCampaignsPageConvex.ts


96. apps/web/src/app/campaigns/hooks/useCarouselEditorConvex.ts Additional files +89/-0

...

apps/web/src/app/campaigns/hooks/useCarouselEditorConvex.ts


97. apps/web/src/app/campaigns/hooks/useEmailCampaignEditorConvex.ts Additional files +85/-0

...

apps/web/src/app/campaigns/hooks/useEmailCampaignEditorConvex.ts


98. apps/web/src/app/campaigns/hooks/usePushCampaignEditorConvex.ts Additional files +77/-0

...

apps/web/src/app/campaigns/hooks/usePushCampaignEditorConvex.ts


99. apps/web/src/app/campaigns/hooks/useSeriesEditorConvex.ts Additional files +105/-0

...

apps/web/src/app/campaigns/hooks/useSeriesEditorConvex.ts


100. apps/web/src/app/campaigns/page.tsx Additional files +22/-41

...

apps/web/src/app/campaigns/page.tsx


101. apps/web/src/app/campaigns/push/[id]/page.tsx Additional files +11/-16

...

apps/web/src/app/campaigns/push/[id]/page.tsx


102. apps/web/src/app/campaigns/series/[id]/SeriesEditorCanvas.tsx Additional files +127/-0

...

apps/web/src/app/campaigns/series/[id]/SeriesEditorCanvas.tsx


103. apps/web/src/app/campaigns/series/[id]/SeriesEditorInspector.tsx Additional files +319/-0

...

apps/web/src/app/campaigns/series/[id]/SeriesEditorInspector.tsx


104. apps/web/src/app/campaigns/series/[id]/SeriesEditorSidebar.tsx Additional files +314/-0

...

apps/web/src/app/campaigns/series/[id]/SeriesEditorSidebar.tsx


105. apps/web/src/app/campaigns/series/[id]/page.tsx Additional files +109/-870

...

apps/web/src/app/campaigns/series/[id]/page.tsx


106. apps/web/src/app/campaigns/series/[id]/seriesBlockUi.tsx Additional files +67/-0

...

apps/web/src/app/campaigns/series/[id]/seriesBlockUi.tsx


107. apps/web/src/app/campaigns/series/[id]/seriesEditorTypes.ts Additional files +141/-0

...

apps/web/src/app/campaigns/series/[id]/seriesEditorTypes.ts


108. apps/web/src/app/checklists/[id]/page.tsx Additional files +8/-43

...

apps/web/src/app/checklists/[id]/page.tsx


109. apps/web/src/app/checklists/checklistTypes.ts Additional files +46/-0

...

apps/web/src/app/checklists/checklistTypes.ts


110. Additional files not shown Additional files +0/-0

...

Additional files not shown


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review Bot commented Apr 16, 2026

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (6) 📎 Requirement gaps (0)

Grey Divider


Action required

1. npm/npx commands in docs 📘 Rule violation § Compliance
Description
Changed documentation/agent-skill content introduces package-management commands using npm/npx
instead of pnpm. This violates the repo requirement to use PNPM exclusively and can lead to
inconsistent installs and lockfile drift.
Code

.agents/skills/convex-quickstart/SKILL.md[R49-103]

+```bash
+npm create convex@latest my-app -- -t owner/repo
+npm create convex@latest my-app -- -t owner/repo#branch
+```
+
+### Scaffold the project
+
+Always pass the project name and template flag to avoid interactive prompts:
+
+```bash
+npm create convex@latest my-app -- -t react-vite-shadcn
+cd my-app
+npm install
+```
+
+The scaffolding tool creates files but does not run `npm install`, so you must run it yourself.
+
+To scaffold in the current directory (if it is empty):
+
+```bash
+npm create convex@latest . -- -t react-vite-shadcn
+npm install
+```
+
+### Start the dev loop
+
+`npx convex dev` is a long-running watcher process that syncs backend code to a Convex deployment on every save. It also requires authentication on first run (browser-based OAuth). Both of these make it unsuitable for an agent to run directly.
+
+**Ask the user to run this themselves:**
+
+Tell the user to run `npx convex dev` in their terminal. On first run it will prompt them to log in or develop anonymously. Once running, it will:
+
+- Create a Convex project and dev deployment
+- Write the deployment URL to `.env.local`
+- Create the `convex/` directory with generated types
+- Watch for changes and sync continuously
+
+The user should keep `npx convex dev` running in the background while you work on code. The watcher will automatically pick up any files you create or edit in `convex/`.
+
+**Exception - cloud or headless agents:** Environments that cannot open a browser for interactive login should use Agent Mode (see below) to run anonymously without user interaction.
+
+### Start the frontend
+
+The user should also run the frontend dev server in a separate terminal:
+
+```bash
+npm run dev
+```
+
+Vite apps serve on `http://localhost:5173`, Next.js on `http://localhost:3000`.
+
+### What you get
+
+After scaffolding, the project structure looks like:
+
Evidence
PR Compliance ID 54502 requires all changed instructions/scripts to use pnpm instead of
npm/npx. The diff adds multiple npm create/npm install/npm run and npx convex ...
commands in docs and seeded help content.

Rule 54502: Use PNPM exclusively for package management commands
.agents/skills/convex-quickstart/SKILL.md[49-103]
.agents/skills/convex-migration-helper/references/migrations-component.md[7-16]
.agents/skills/convex-migration-helper/references/migrations-component.md[64-71]
.agents/skills/convex-migration-helper/references/migrations-component.md[127-129]
packages/convex/convex/testData/demoWorkspace.ts[295-305]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New/updated docs and agent-skill references use `npm`/`npx` commands, but this repo requires PNPM-only commands.

## Issue Context
Use `pnpm install`, `pnpm run <script>`, and `pnpm dlx <cli>` equivalents wherever PNPM can perform the same task.

## Fix Focus Areas
- .agents/skills/convex-quickstart/SKILL.md[49-103]
- .agents/skills/convex-migration-helper/references/migrations-component.md[7-16]
- .agents/skills/convex-migration-helper/references/migrations-component.md[64-71]
- .agents/skills/convex-migration-helper/references/migrations-component.md[127-129]
- packages/convex/convex/testData/demoWorkspace.ts[295-305]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. webQueryRef() calls makeFunctionReference 📘 Rule violation ✧ Quality
Description
apps/web/src/lib/convex/hooks.ts introduces exported ref-factory helpers that invoke
makeFunctionReference(...) inside functions. This violates the requirement that
makeFunctionReference values be created at module scope only (created once at module load).
Code

apps/web/src/lib/convex/hooks.ts[R27-53]

+export function webQueryRef<Args extends WebArgs, Result>(
+  functionName: string
+): WebQueryRef<Args, Result> {
+  return makeFunctionReference<"query", Args, Result>(functionName) as WebQueryRef<Args, Result>;
+}
+
+export function webMutationRef<Args extends WebArgs, Result>(
+  functionName: string
+): WebMutationRef<Args, Result> {
+  return makeFunctionReference<"mutation", Args, Result>(functionName) as WebMutationRef<
+    Args,
+    Result
+  >;
+}
+
+export function webActionRef<Args extends WebArgs, Result>(
+  functionName: string
+): WebActionRef<Args, Result> {
+  return makeFunctionReference<"action", Args, Result>(functionName) as WebActionRef<Args, Result>;
+}
+
+export function useWebQuery<Args extends WebArgs, Result>(
+  queryRef: WebQueryRef<Args, Result>,
+  args: Args | "skip"
+): Result | undefined {
+  return useQuery(queryRef as never, args as never) as Result | undefined;
+}
Evidence
PR Compliance ID 96846 requires makeFunctionReference(...) to be evaluated only at module scope,
not inside functions/hooks/components. The new webQueryRef/webMutationRef/webActionRef
functions each call makeFunctionReference(functionName) inside the function body.

Rule 96846: Define Convex function references at module scope
apps/web/src/lib/convex/hooks.ts[27-53]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`webQueryRef`, `webMutationRef`, and `webActionRef` call `makeFunctionReference(...)` inside function bodies, which violates the module-scope-only requirement.

## Issue Context
Even if callers invoke these helpers at top level, the `makeFunctionReference(...)` invocation itself is still inside a function body (not file top-level).

## Fix Focus Areas
- apps/web/src/lib/convex/hooks.ts[27-53]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. E2E selectors use text/classes 📘 Rule violation ▣ Testability
Description
Updated Playwright helpers locate elements using text and CSS class selectors (e.g.,
button:has-text(...), .feedback-button). This makes E2E tests brittle and violates the
requirement to use data-testid selectors for element targeting.
Code

apps/web/e2e/helpers/widget-helpers.ts[R410-427]

+export async function waitForAIHandoffButton(page: Page, timeout = 15000): Promise<Locator> {
+  const frame = getWidgetContainer(page);
+  const handoffButton = frame.locator(
+    "[data-testid='handoff-button'], button:has-text('Talk to human'), button:has-text('Talk to a human'), button:has-text('human'), button:has-text('agent')"
+  );
+
+  await expect(handoffButton.first()).toBeVisible({ timeout });
+  return handoffButton.first();
+}
+
+/**
+ * Waits for the AI feedback buttons to be visible.
+ */
+export async function waitForAIFeedbackButtons(page: Page, timeout = 15000): Promise<Locator> {
+  const frame = getWidgetContainer(page);
+  const feedbackButtons = frame.locator(
+    "[data-testid='feedback-helpful'], [data-testid='feedback-not-helpful'], .feedback-button, button[aria-label*='helpful'], button[aria-label*='not helpful']"
+  );
Evidence
PR Compliance ID 96850 requires E2E selectors to use data-testid attributes rather than CSS
classes or visible text for locating UI elements. The new helper locators include multiple
button:has-text(...) and class-based selectors alongside data-testid selectors.

Rule 96850: Use data-testid attributes for E2E test selectors
apps/web/e2e/helpers/widget-helpers.ts[172-176]
apps/web/e2e/helpers/widget-helpers.ts[338-342]
apps/web/e2e/helpers/widget-helpers.ts[410-427]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Playwright E2E helpers use text/class selectors to find elements, which is disallowed for stable selectors.

## Issue Context
Selectors should target stable `[data-testid="..."]` attributes; if the UI lacks a stable test id, add one and update the test.

## Fix Focus Areas
- apps/web/e2e/helpers/widget-helpers.ts[172-176]
- apps/web/e2e/helpers/widget-helpers.ts[338-342]
- apps/web/e2e/helpers/widget-helpers.ts[410-427]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (3)
4. v.any() used without exceptions 📘 Rule violation ⛨ Security
Description
New/modified Convex internal mutations use v.any() for args validators, but the exceptions
allowlist was cleared. This violates the requirement to use narrow validators or explicitly document
each v.any() in security/convex-v-any-arg-exceptions.json.
Code

packages/convex/convex/testData/seeds.ts[R469-547]

+const seedVisitor = internalMutation({
+  args: {
+    workspaceId: v.id("workspaces"),
+    email: v.optional(v.string()),
+    name: v.optional(v.string()),
+    externalUserId: v.optional(v.string()),
+    customAttributes: v.optional(v.any()),
+    location: v.optional(
+      v.object({
+        city: v.optional(v.string()),
+        region: v.optional(v.string()),
+        country: v.optional(v.string()),
+        countryCode: v.optional(v.string()),
+      })
+    ),
+    device: v.optional(
+      v.object({
+        browser: v.optional(v.string()),
+        os: v.optional(v.string()),
+        deviceType: v.optional(v.string()),
+      })
+    ),
+  },
+  handler: async (ctx, args) => {
+    requireTestDataEnabled();
+    const timestamp = Date.now();
+    const randomSuffix = Math.random().toString(36).substring(2, 8);
+    const sessionId = `${E2E_TEST_PREFIX}session_${timestamp}_${randomSuffix}`;
+
+    const visitorId = await ctx.db.insert("visitors", {
+      sessionId,
+      workspaceId: args.workspaceId,
+      email: args.email || `${E2E_TEST_PREFIX}visitor_${randomSuffix}@test.opencom.dev`,
+      name: args.name || `E2E Test Visitor ${randomSuffix}`,
+      externalUserId: args.externalUserId,
+      customAttributes: args.customAttributes || {
+        plan: "free",
+        signupDate: new Date().toISOString(),
+      },
+      location: args.location || {
+        city: "San Francisco",
+        region: "California",
+        country: "United States",
+        countryCode: "US",
+      },
+      device: args.device || {
+        browser: "Chrome",
+        os: "macOS",
+        deviceType: "desktop",
+      },
+      firstSeenAt: timestamp,
+      lastSeenAt: timestamp,
+      createdAt: timestamp,
+    });
+
+    await ctx.db.patch(visitorId, {
+      readableId: formatReadableVisitorId(visitorId),
+    });
+
+    return { visitorId, sessionId };
+  },
+});
+
+/**
+ * Seeds a test segment for E2E testing.
+ */
+const seedSegment = internalMutation({
+  args: {
+    workspaceId: v.id("workspaces"),
+    name: v.optional(v.string()),
+    audienceRules: v.optional(v.any()),
+  },
+  handler: async (ctx, args) => {
+    requireTestDataEnabled();
+    const timestamp = Date.now();
+    const randomSuffix = Math.random().toString(36).substring(2, 8);
+    const name = args.name || `${E2E_TEST_PREFIX}segment_${randomSuffix}`;
+
+    const defaultRules = {
Evidence
PR Compliance ID 96842 disallows v.any() in changed Convex handler args unless it is documented in
security/convex-v-any-arg-exceptions.json. The diff adds v.optional(v.any()) for args (e.g.,
customAttributes, audienceRules) while updating the exceptions file to "entries": [] (no
documented exceptions).

Rule 96842: Use narrow Convex validators for args; document any v.any() exceptions
packages/convex/convex/testData/seeds.ts[469-547]
packages/convex/convex/testing/helpers/content.ts[213-227]
security/convex-v-any-arg-exceptions.json[1-5]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Convex handlers introduce `v.any()` validators, but there are no corresponding allowlist entries.

## Issue Context
Either replace `v.any()` with a narrow validator (preferred) or add a specific, justified entry for each handler/arg in `security/convex-v-any-arg-exceptions.json`.

## Fix Focus Areas
- packages/convex/convex/testData/seeds.ts[469-547]
- packages/convex/convex/testing/helpers/content.ts[213-227]
- security/convex-v-any-arg-exceptions.json[1-5]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Dynamic makeFunctionReference(name) undocumented 📘 Rule violation ⌂ Architecture
Description
packages/convex/convex/testAdmin.ts introduces a dynamic makeFunctionReference(name) path
without an inline justification comment. This violates the requirement that dynamic function
reference creation be explicitly documented as an intentional exception.
Code

packages/convex/convex/testAdmin.ts[R30-32]

+function getInternalRef(name: string): unknown {
+  return makeFunctionReference(name);
+}
Evidence
PR Compliance ID 96849 requires dynamic makeFunctionReference(...) usage to be documented with an
inline comment explaining why dynamic dispatch is required. The new helper getInternalRef(name)
returns makeFunctionReference(name) with no such justification at the call site.

Rule 96849: Standardize Convex backend function reference boundaries ordering
packages/convex/convex/testAdmin.ts[30-32]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Dynamic `makeFunctionReference(name)` is used without an explicit comment documenting why this cannot be expressed with generated refs or a fixed constant.

## Issue Context
If this is intentionally dynamic (e.g., a secret-protected test admin gateway), it must be documented inline as an exception per the boundaries-ordering policy.

## Fix Focus Areas
- packages/convex/convex/testAdmin.ts[30-32]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Undocumented as unknown as casts 📘 Rule violation ≡ Correctness
Description
New Convex runtime code adds chained type-escape casts (as unknown as) without the required
localized justification comment. This violates the rule restricting unsafe casts in runtime paths to
narrowly scoped, documented exceptions.
Code

packages/convex/convex/aiAgentActions.ts[R131-173]

+const AUTHORIZE_CONVERSATION_ACCESS_REF = makeFunctionReference<
+  "query",
+  ConversationAccessArgs,
+  ConversationAccessResult
+>("aiAgent:authorizeConversationAccess") as unknown as ConvexRef<
+  "query",
+  "internal",
+  ConversationAccessArgs,
+  ConversationAccessResult
+>;
+
+const GET_RUNTIME_SETTINGS_FOR_WORKSPACE_REF = makeFunctionReference<
+  "query",
+  WorkspaceIdArgs,
+  RuntimeSettings
+>("aiAgent:getRuntimeSettingsForWorkspace") as unknown as ConvexRef<
+  "query",
+  "internal",
+  WorkspaceIdArgs,
+  RuntimeSettings
+>;
+
+const RECORD_RUNTIME_DIAGNOSTIC_REF = makeFunctionReference<
+  "mutation",
+  RuntimeDiagnosticArgs,
+  unknown
+>("aiAgent:recordRuntimeDiagnostic") as unknown as ConvexRef<
+  "mutation",
+  "internal",
+  RuntimeDiagnosticArgs,
+  unknown
+>;
+
+const CLEAR_RUNTIME_DIAGNOSTIC_REF = makeFunctionReference<
+  "mutation",
+  WorkspaceIdArgs,
+  Id<"aiAgentSettings"> | null
+>("aiAgent:clearRuntimeDiagnostic") as unknown as ConvexRef<
+  "mutation",
+  "internal",
+  WorkspaceIdArgs,
+  Id<"aiAgentSettings"> | null
+>;
Evidence
PR Compliance ID 72009 restricts unsafe type-escape casts like as unknown as in new runtime code
unless they are tightly scoped and documented. The added `makeFunctionReference(...) as unknown as
...` casts appear repeatedly in the file with no accompanying comment justifying the type escape or
describing removal criteria.

Rule 72009: Restrict unsafe type-escape casts in new runtime code
packages/convex/convex/aiAgentActions.ts[131-173]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Runtime Convex code uses `as unknown as` casts as a typing escape hatch without documenting why the type system cannot represent the pattern.

## Issue Context
Preferred order is generated `api`/`internal` refs; if TS2589 forces a workaround, keep it hotspot-local with the smallest cast possible and add a brief comment explaining why and how to remove it later.

## Fix Focus Areas
- packages/convex/convex/aiAgentActions.ts[131-173]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

7. Markdown assumes DOM exists 🐞 Bug ☼ Reliability
Description
@opencom/web-shared's parseMarkdown() path calls document.createElement() unconditionally,
which will throw ReferenceError: document is not defined in non-browser contexts (SSR/Node tests
without jsdom). Because this is now exported from a shared package, any accidental server-side usage
becomes a hard crash instead of a safe no-op/HTML fallback.
Code

packages/web-shared/src/markdown.ts[R92-94]

+function enforceSafeLinksAndMedia(html: string, options: ResolvedParseMarkdownOptions): string {
+  const container = document.createElement("div");
+  container.innerHTML = html;
Evidence
The shared markdown implementation uses document.createElement without checking if document
exists, and this function is exported from the package entrypoint, making it easy to be
imported/used from non-browser runtimes.

packages/web-shared/src/markdown.ts[92-94]
packages/web-shared/src/index.ts[1-6]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`packages/web-shared/src/markdown.ts` unconditionally uses DOM APIs (`document.createElement`) inside `enforceSafeLinksAndMedia`, which crashes in any runtime where `document` is undefined (SSR/Node).

### Issue Context
`parseMarkdown` is exported from `@opencom/web-shared`, so consumers can import it in environments beyond the browser. Even if current call sites are client components, this is a sharp edge that will surface as soon as a server component, Node script, or non-jsdom test imports/executes it.

### Fix Focus Areas
- Add a `typeof document === "undefined"` guard (and safe fallback behavior) around DOM-dependent logic.
- Ensure the fallback still returns safe/sanitized HTML.

- packages/web-shared/src/markdown.ts[92-149]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@djanogly djanogly closed this Apr 16, 2026
Comment on lines +49 to +103
```bash
npm create convex@latest my-app -- -t owner/repo
npm create convex@latest my-app -- -t owner/repo#branch
```

### Scaffold the project

Always pass the project name and template flag to avoid interactive prompts:

```bash
npm create convex@latest my-app -- -t react-vite-shadcn
cd my-app
npm install
```

The scaffolding tool creates files but does not run `npm install`, so you must run it yourself.

To scaffold in the current directory (if it is empty):

```bash
npm create convex@latest . -- -t react-vite-shadcn
npm install
```

### Start the dev loop

`npx convex dev` is a long-running watcher process that syncs backend code to a Convex deployment on every save. It also requires authentication on first run (browser-based OAuth). Both of these make it unsuitable for an agent to run directly.

**Ask the user to run this themselves:**

Tell the user to run `npx convex dev` in their terminal. On first run it will prompt them to log in or develop anonymously. Once running, it will:

- Create a Convex project and dev deployment
- Write the deployment URL to `.env.local`
- Create the `convex/` directory with generated types
- Watch for changes and sync continuously

The user should keep `npx convex dev` running in the background while you work on code. The watcher will automatically pick up any files you create or edit in `convex/`.

**Exception - cloud or headless agents:** Environments that cannot open a browser for interactive login should use Agent Mode (see below) to run anonymously without user interaction.

### Start the frontend

The user should also run the frontend dev server in a separate terminal:

```bash
npm run dev
```

Vite apps serve on `http://localhost:5173`, Next.js on `http://localhost:3000`.

### What you get

After scaffolding, the project structure looks like:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. npm/npx commands in docs 📘 Rule violation § Compliance

Changed documentation/agent-skill content introduces package-management commands using npm/npx
instead of pnpm. This violates the repo requirement to use PNPM exclusively and can lead to
inconsistent installs and lockfile drift.
Agent Prompt
## Issue description
New/updated docs and agent-skill references use `npm`/`npx` commands, but this repo requires PNPM-only commands.

## Issue Context
Use `pnpm install`, `pnpm run <script>`, and `pnpm dlx <cli>` equivalents wherever PNPM can perform the same task.

## Fix Focus Areas
- .agents/skills/convex-quickstart/SKILL.md[49-103]
- .agents/skills/convex-migration-helper/references/migrations-component.md[7-16]
- .agents/skills/convex-migration-helper/references/migrations-component.md[64-71]
- .agents/skills/convex-migration-helper/references/migrations-component.md[127-129]
- packages/convex/convex/testData/demoWorkspace.ts[295-305]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +27 to +53
export function webQueryRef<Args extends WebArgs, Result>(
functionName: string
): WebQueryRef<Args, Result> {
return makeFunctionReference<"query", Args, Result>(functionName) as WebQueryRef<Args, Result>;
}

export function webMutationRef<Args extends WebArgs, Result>(
functionName: string
): WebMutationRef<Args, Result> {
return makeFunctionReference<"mutation", Args, Result>(functionName) as WebMutationRef<
Args,
Result
>;
}

export function webActionRef<Args extends WebArgs, Result>(
functionName: string
): WebActionRef<Args, Result> {
return makeFunctionReference<"action", Args, Result>(functionName) as WebActionRef<Args, Result>;
}

export function useWebQuery<Args extends WebArgs, Result>(
queryRef: WebQueryRef<Args, Result>,
args: Args | "skip"
): Result | undefined {
return useQuery(queryRef as never, args as never) as Result | undefined;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

2. webqueryref() calls makefunctionreference 📘 Rule violation ✧ Quality

apps/web/src/lib/convex/hooks.ts introduces exported ref-factory helpers that invoke
makeFunctionReference(...) inside functions. This violates the requirement that
makeFunctionReference values be created at module scope only (created once at module load).
Agent Prompt
## Issue description
`webQueryRef`, `webMutationRef`, and `webActionRef` call `makeFunctionReference(...)` inside function bodies, which violates the module-scope-only requirement.

## Issue Context
Even if callers invoke these helpers at top level, the `makeFunctionReference(...)` invocation itself is still inside a function body (not file top-level).

## Fix Focus Areas
- apps/web/src/lib/convex/hooks.ts[27-53]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +410 to +427
export async function waitForAIHandoffButton(page: Page, timeout = 15000): Promise<Locator> {
const frame = getWidgetContainer(page);
const handoffButton = frame.locator(
"[data-testid='handoff-button'], button:has-text('Talk to human'), button:has-text('Talk to a human'), button:has-text('human'), button:has-text('agent')"
);

await expect(handoffButton.first()).toBeVisible({ timeout });
return handoffButton.first();
}

/**
* Waits for the AI feedback buttons to be visible.
*/
export async function waitForAIFeedbackButtons(page: Page, timeout = 15000): Promise<Locator> {
const frame = getWidgetContainer(page);
const feedbackButtons = frame.locator(
"[data-testid='feedback-helpful'], [data-testid='feedback-not-helpful'], .feedback-button, button[aria-label*='helpful'], button[aria-label*='not helpful']"
);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

3. E2e selectors use text/classes 📘 Rule violation ▣ Testability

Updated Playwright helpers locate elements using text and CSS class selectors (e.g.,
button:has-text(...), .feedback-button). This makes E2E tests brittle and violates the
requirement to use data-testid selectors for element targeting.
Agent Prompt
## Issue description
Playwright E2E helpers use text/class selectors to find elements, which is disallowed for stable selectors.

## Issue Context
Selectors should target stable `[data-testid="..."]` attributes; if the UI lacks a stable test id, add one and update the test.

## Fix Focus Areas
- apps/web/e2e/helpers/widget-helpers.ts[172-176]
- apps/web/e2e/helpers/widget-helpers.ts[338-342]
- apps/web/e2e/helpers/widget-helpers.ts[410-427]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +469 to +547
const seedVisitor = internalMutation({
args: {
workspaceId: v.id("workspaces"),
email: v.optional(v.string()),
name: v.optional(v.string()),
externalUserId: v.optional(v.string()),
customAttributes: v.optional(v.any()),
location: v.optional(
v.object({
city: v.optional(v.string()),
region: v.optional(v.string()),
country: v.optional(v.string()),
countryCode: v.optional(v.string()),
})
),
device: v.optional(
v.object({
browser: v.optional(v.string()),
os: v.optional(v.string()),
deviceType: v.optional(v.string()),
})
),
},
handler: async (ctx, args) => {
requireTestDataEnabled();
const timestamp = Date.now();
const randomSuffix = Math.random().toString(36).substring(2, 8);
const sessionId = `${E2E_TEST_PREFIX}session_${timestamp}_${randomSuffix}`;

const visitorId = await ctx.db.insert("visitors", {
sessionId,
workspaceId: args.workspaceId,
email: args.email || `${E2E_TEST_PREFIX}visitor_${randomSuffix}@test.opencom.dev`,
name: args.name || `E2E Test Visitor ${randomSuffix}`,
externalUserId: args.externalUserId,
customAttributes: args.customAttributes || {
plan: "free",
signupDate: new Date().toISOString(),
},
location: args.location || {
city: "San Francisco",
region: "California",
country: "United States",
countryCode: "US",
},
device: args.device || {
browser: "Chrome",
os: "macOS",
deviceType: "desktop",
},
firstSeenAt: timestamp,
lastSeenAt: timestamp,
createdAt: timestamp,
});

await ctx.db.patch(visitorId, {
readableId: formatReadableVisitorId(visitorId),
});

return { visitorId, sessionId };
},
});

/**
* Seeds a test segment for E2E testing.
*/
const seedSegment = internalMutation({
args: {
workspaceId: v.id("workspaces"),
name: v.optional(v.string()),
audienceRules: v.optional(v.any()),
},
handler: async (ctx, args) => {
requireTestDataEnabled();
const timestamp = Date.now();
const randomSuffix = Math.random().toString(36).substring(2, 8);
const name = args.name || `${E2E_TEST_PREFIX}segment_${randomSuffix}`;

const defaultRules = {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

4. v.any() used without exceptions 📘 Rule violation ⛨ Security

New/modified Convex internal mutations use v.any() for args validators, but the exceptions
allowlist was cleared. This violates the requirement to use narrow validators or explicitly document
each v.any() in security/convex-v-any-arg-exceptions.json.
Agent Prompt
## Issue description
Convex handlers introduce `v.any()` validators, but there are no corresponding allowlist entries.

## Issue Context
Either replace `v.any()` with a narrow validator (preferred) or add a specific, justified entry for each handler/arg in `security/convex-v-any-arg-exceptions.json`.

## Fix Focus Areas
- packages/convex/convex/testData/seeds.ts[469-547]
- packages/convex/convex/testing/helpers/content.ts[213-227]
- security/convex-v-any-arg-exceptions.json[1-5]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +30 to +32
function getInternalRef(name: string): unknown {
return makeFunctionReference(name);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

5. Dynamic makefunctionreference(name) undocumented 📘 Rule violation ⌂ Architecture

packages/convex/convex/testAdmin.ts introduces a dynamic makeFunctionReference(name) path
without an inline justification comment. This violates the requirement that dynamic function
reference creation be explicitly documented as an intentional exception.
Agent Prompt
## Issue description
Dynamic `makeFunctionReference(name)` is used without an explicit comment documenting why this cannot be expressed with generated refs or a fixed constant.

## Issue Context
If this is intentionally dynamic (e.g., a secret-protected test admin gateway), it must be documented inline as an exception per the boundaries-ordering policy.

## Fix Focus Areas
- packages/convex/convex/testAdmin.ts[30-32]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +131 to +173
const AUTHORIZE_CONVERSATION_ACCESS_REF = makeFunctionReference<
"query",
ConversationAccessArgs,
ConversationAccessResult
>("aiAgent:authorizeConversationAccess") as unknown as ConvexRef<
"query",
"internal",
ConversationAccessArgs,
ConversationAccessResult
>;

const GET_RUNTIME_SETTINGS_FOR_WORKSPACE_REF = makeFunctionReference<
"query",
WorkspaceIdArgs,
RuntimeSettings
>("aiAgent:getRuntimeSettingsForWorkspace") as unknown as ConvexRef<
"query",
"internal",
WorkspaceIdArgs,
RuntimeSettings
>;

const RECORD_RUNTIME_DIAGNOSTIC_REF = makeFunctionReference<
"mutation",
RuntimeDiagnosticArgs,
unknown
>("aiAgent:recordRuntimeDiagnostic") as unknown as ConvexRef<
"mutation",
"internal",
RuntimeDiagnosticArgs,
unknown
>;

const CLEAR_RUNTIME_DIAGNOSTIC_REF = makeFunctionReference<
"mutation",
WorkspaceIdArgs,
Id<"aiAgentSettings"> | null
>("aiAgent:clearRuntimeDiagnostic") as unknown as ConvexRef<
"mutation",
"internal",
WorkspaceIdArgs,
Id<"aiAgentSettings"> | null
>;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

6. Undocumented as unknown as casts 📘 Rule violation ≡ Correctness

New Convex runtime code adds chained type-escape casts (as unknown as) without the required
localized justification comment. This violates the rule restricting unsafe casts in runtime paths to
narrowly scoped, documented exceptions.
Agent Prompt
## Issue description
Runtime Convex code uses `as unknown as` casts as a typing escape hatch without documenting why the type system cannot represent the pattern.

## Issue Context
Preferred order is generated `api`/`internal` refs; if TS2589 forces a workaround, keep it hotspot-local with the smallest cast possible and add a brief comment explaining why and how to remove it later.

## Fix Focus Areas
- packages/convex/convex/aiAgentActions.ts[131-173]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

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