Skip to content

feat(webapp): deterministic grounding facts and org-wide tokens for the dashboard agent - #4796

Open
kathiekiwi wants to merge 45 commits into
mainfrom
fix/dashboard-agent-test-cloud
Open

feat(webapp): deterministic grounding facts and org-wide tokens for the dashboard agent#4796
kathiekiwi wants to merge 45 commits into
mainfrom
fix/dashboard-agent-test-cloud

Conversation

@kathiekiwi

@kathiekiwi kathiekiwi commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

Grounds the dashboard agent's answers in deterministic platform facts instead of LLM inference, and widens its token to the organization.

  • get_queue now returns the actual concurrency slot holders (run ids from the run queue's Redis state, resolved against Postgres, with per-holder and snapshot consistency facts). The contract deliberately never claims the list is complete — per-key queue holders can be structurally unlistable.
  • Environment-scope concurrency (limit, current, burst factor) and the queue's concurrency override breakdown ride along, so the agent can name which limit actually binds.
  • Curated runs carry a computed queue wait (queuedAt-based, reliability-flagged); traces emit real span ids with per-turn evidence validation; error groups carry recurredSinceResolve; repo citations carry a dirty-deployment caveat; the concurrency-saturation page signal carries queue identity.
  • The dashboard-agent user-actor token is now org-scoped: valid for any project/environment in the organization the user can access (org membership enforced server-side); the current environment remains only the conversational default.
  • Chat code-renderer chunk loads retry and fall back to plain text instead of crashing to the error boundary.
  • System prompt compressed to fit the char budgets; grounding rules moved to tool descriptions.
  • Plus: Investigate button shows for failed runs without a structured error; zero-hypotheses count hidden; a local UAT seed script (scripts/seed-dashboard-agent-uat.ts).

…text

Stops the assistant chat crashing to a full-screen error when the
code-highlighting chunk fails to load. Retries twice with backoff, then
renders plain text instead of throwing.
…d errors

Extracts the lazy chunk-load factory as loadStreamdownRenderer so the
plain-text fallback path is covered by a test. The fallback still
re-raises the original error as an unhandled rejection so the
deploy-skew asset-recovery reload can pick it up.
One read-only Lua script reads the base concurrency sets, every CK variant in
ckIndex and the runningCounter together, so the run ids behind a queue's
running count come with counts from the same snapshot.
Adds slotHolders and slotHolderFacts to the retrieved queue: which runs hold the
queue's slots, their phase, and whether Redis membership matches the run's
status. Both the Redis and Postgres reads degrade instead of failing.
The holder list can never claim completeness for a CK queue, so the contract now
reports only what is provable: truncated when the cap was hit and unlistedRunning
for dequeued holders that exist but aren't listed.
Pass slotHolders/holderResolution through from the queue live row
when present, and ground the model on how to read them: name the
holder when consistent, call out scheduler/run-state mismatches
without saying leaked or stale, and never assert an executing run
from runningNow alone.
Grounding block now covers partial resolution and unresolved holders,
the none branch no longer asserts usage as fact, and the
runningNow-mismatch clause fires only when holderResolution is
complete.
Adds slotHolderFacts to withLiveState with the same independent gating
as slotHolders/holderResolution. Grounding block covers admitted-vs-
dequeued phase and prefers slotHolderFacts over comparing runningNow
manually.
…ists

slotHolders is never exhaustive by contract for per-key concurrency
queues, so no field claims completeness. slotHolderFacts gains
truncated/unlistedRunning as proof of unlisted holders, and its
consistency can be unresolved (counts then unusable). Grounding rules
and tests updated to match.
get_repo_info and read_file now surface the run-pinned deployment's
dirty flag (built from a tree with uncommitted changes), and the
source read ledger tracks it per-sha so evidence canonicalization can
caveat citations instead of asserting an exact commit match.
A dirty run-pinned deploy and the clean tracked branch can share a
sha. dirtyForSha was last-write-wins, so a later clean read of that
sha erased the dirty caveat. Fixed to OR instead of overwrite.
…oundary

The dashboard agent's delegated token now carries the organization alongside the
environment. For a token with an organization, the request may name any environment
in that org — re-authorized against the org and the user's membership — and the
token's own environment is only the default. Tokens without one stay env-pinned.
…h alert

The unsubscribe route read the environment off the token alone, so an org-wide token
could subscribe an alert in a sibling environment but not remove it. It now resolves
the environment the same way the other agent routes do, checked against the token's
organization, which resolveAgentAlertContext requires its caller to pass.
Curated runs expose a computed wait (queued vs created basis, reliability
flag) instead of raw timestamps the model had to subtract itself, mirroring
dashboardAgentWatchRunChecks' queue-wait semantics. The webapp run presenter
now selects queuedAt and derives queueWaitReliable from the raw status.

Trace spans carry their spanId, and span evidence is validated against a
per-turn span ledger (mirroring the source-read ledger) so a citation must
come from this turn's trace read. Source evidence also gets a code-stamped
dirty flag from the same ledger, fed by run-pinned/default snapshot dirtiness.

Error groups expose a computed recurredSinceResolve instead of leaving the
model to compare resolvedAt/lastSeen dates.
…akdown on get_queue

The queue can show headroom while the environment is saturated, so the
binding constraint may not be the queue itself. Add envConcurrency
(limit, current) to QueueRetrievePresenter, guarded like slotHolders,
and pass it through the dashboard agent's get_queue tool alongside the
concurrency override breakdown (base/override/overriddenBy/overriddenAt)
the route already returns but the tool was dropping.
… not the plain limit

current >= limit is not the dequeue gate; it's current >= limit * burstFactor
(burstFactor defaults to 2). Add burstFactor to EnvConcurrency and reword the
get_queue description so the model reasons from the real gate instead of
assuming current == limit means the environment is saturated.
Add optional scope/queueName/limit/current fields so the model knows
which queue or env is saturated, instead of guessing from the page.
Populated by the webapp from data already graded (no new queries),
carried through verbatim by the dashboard-agent tool.
The bare-evidence test asserted the pre-validation contract without ever
reading a trace. Now it drives get_run_trace for real before citing the
span, plus a new case for a span id no trace read returned this turn.
Dedupe get_queue grounding between the tool description and the
system prompt, and tighten verbose investigation/watch phrasing, to
bring both prompt.chars ceilings back under budget without dropping
any grounding rule.
Fabricates PG+Redis fixtures for S1-S6 and S10 of the dashboard-agent
UAT scenarios in the local References/hello-world dev environment.
@changeset-bot

changeset-bot Bot commented Aug 26, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: ebbf6b7

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai

coderabbitai Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 67de5502-a036-4ed2-a5a0-53cdd34594ed

📥 Commits

Reviewing files that changed from the base of the PR and between 62c1940 and 49601a7.

📒 Files selected for processing (18)
  • apps/webapp/app/components/code/StreamdownRenderer.test.ts
  • apps/webapp/app/components/dashboard-agent/DashboardAgentChat.tsx
  • apps/webapp/app/components/dashboard-agent/turn-deadlines.test.ts
  • apps/webapp/app/components/dashboard-agent/turn-deadlines.ts
  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.server.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.alerts.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.watches.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.ts
  • apps/webapp/app/services/dashboardAgentTokenScope.ts
  • apps/webapp/app/services/dashboardAgentWatchRunChecks.ts
  • apps/webapp/test/userActorOrgWideEnvironmentScope.test.ts
  • internal-packages/dashboard-agent/src/tool-curation.ts
  • internal-packages/dashboard-agent/src/tool-queue.test.ts
  • internal-packages/dashboard-agent/src/tool-source-ledger.test.ts
  • internal-packages/dashboard-agent/src/tool-source-ledger.ts
  • internal-packages/run-engine/src/run-queue/index.ts
  • internal-packages/run-engine/src/run-queue/tests/slotHolders.test.ts
  • scripts/seed-dashboard-agent-uat.ts
🚧 Files skipped from review as they are similar to previous changes (18)
  • apps/webapp/app/components/dashboard-agent/turn-deadlines.test.ts
  • apps/webapp/app/components/dashboard-agent/turn-deadlines.ts
  • internal-packages/dashboard-agent/src/tool-source-ledger.test.ts
  • apps/webapp/app/components/code/StreamdownRenderer.test.ts
  • apps/webapp/app/services/dashboardAgentWatchRunChecks.ts
  • apps/webapp/app/services/dashboardAgentTokenScope.ts
  • internal-packages/run-engine/src/run-queue/tests/slotHolders.test.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.alerts.ts
  • internal-packages/run-engine/src/run-queue/index.ts
  • apps/webapp/app/components/dashboard-agent/DashboardAgentChat.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.ts
  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.server.ts
  • apps/webapp/test/userActorOrgWideEnvironmentScope.test.ts
  • internal-packages/dashboard-agent/src/tool-queue.test.ts
  • internal-packages/dashboard-agent/src/tool-curation.ts
  • scripts/seed-dashboard-agent-uat.ts
  • internal-packages/dashboard-agent/src/tool-source-ledger.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.watches.ts

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

📜 Recent review details
⏰ Context from checks skipped due to timeout. (38)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (21, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (15, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (24, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (3, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (8, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (23, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (6, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (18, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (14, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (17, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (20, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (19, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (13, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (16, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (4, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (22, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (1, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (9, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (12, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (7, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (2, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (10, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (5, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (11, 24)
  • GitHub Check: e2e-webapp / 🧪 E2E Tests: Webapp (2, 2)
  • GitHub Check: packages / 🧪 Unit Tests: Packages (3, 3)
  • GitHub Check: runops-guard / runops-guard
  • GitHub Check: typecheck / typecheck
  • GitHub Check: e2e-webapp / 🧪 E2E Tests: Webapp (1, 2)
  • GitHub Check: packages / 🧪 Unit Tests: Packages (2, 3)
  • GitHub Check: fk-cascade-guard / fk-cascade-guard
  • GitHub Check: internal / 🧪 Unit Tests: Internal
  • GitHub Check: packages / 🧪 Unit Tests: Packages (1, 3)
  • GitHub Check: obsmap / 🧪 Unit Tests: Observability Map
  • GitHub Check: code-quality / code-quality
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: 🛡️ E2E Auth Tests (full)
  • GitHub Check: audit

Walkthrough

The changes add organization-wide dashboard-agent token scope with membership and organization-boundary validation. Queue APIs now expose slot holders, concurrency limits, consistency metadata, and reliable wait times. Agent evidence tracks trace reads and dirty source snapshots. API tools support cross-project reads. Dashboard-agent chat now has bounded waits, and Streamdown loading retries with a plain-text fallback. Tests cover authorization, queue diagnostics, evidence, repository state, cross-project reads, timeout handling, and renderer recovery. A UAT script creates and cleans scenario fixtures.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description gives a detailed and relevant summary of the implementation, but it omits the required issue reference, checklist, testing section, changelog section, and screenshots section from the … Update the description to follow the repository template. Add the issue reference, complete the checklist, document the testing steps and results, add a short changelog entry, and include screenshots or state that screenshots are not applic…
Docstring Coverage ⚠️ Warning Docstring coverage is 33.65% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 104 functions across 60 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the two primary changes: deterministic grounding facts and organization-wide dashboard-agent tokens. It is concise and specific.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description gives a detailed and relevant summary of the implementation, but it omits the required issue reference, checklist, testing section, changelog section, and screenshots section from the repository template.

Resolution

Update the description to follow the repository template. Add the issue reference, complete the checklist, document the testing steps and results, add a short changelog entry, and include screenshots or state that screenshots are not applicable.

✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/dashboard-agent-test-cloud

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Caution

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

⚠️ Outside diff range comments (1)
packages/plugins/src/rbac.ts (1)

302-377: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Add crumb markers for the changed authorization paths.

  • packages/plugins/src/rbac.ts#L302-L377: mark claim signing and verification.
  • apps/webapp/app/services/dashboardAgentTokenScope.ts#L22-L47: mark scope resolution.
  • apps/webapp/test/dashboardAgentTokenScope.test.ts#L4-L49: mark scope test flow.
  • apps/webapp/app/routes/api.v1.dashboard-agent.alerts.ts#L44-L142: mark token and alert-context resolution.
  • apps/webapp/app/routes/api.v1.dashboard-agent.alerts.$channelId.ts#L52-L97: mark delete-scope resolution.
  • apps/webapp/app/routes/api.v1.dashboard-agent.watches.ts#L62-L98: mark watch authorization.
  • apps/webapp/app/services/dashboardAgentAlertContext.server.ts#L18-L54: mark environment and organization validation.
  • apps/webapp/test/uatEnvironmentClaim.test.ts#L475-L507: mark organization-scope cases.
  • apps/webapp/test/userActorOrgWideEnvironmentScope.test.ts#L75-L117: mark integration authorization cases.

As per coding guidelines: “Add crumbs as you write code — not just when debugging.”

Source: Coding guidelines

🧹 Nitpick comments (4)
internal-packages/dashboard-agent/src/tool-curation.ts (1)

29-75: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add crumbs for the new code paths.

Add // @Crumbs markers or `#region `@crumbs blocks with an approved namespace. Do not create a namespace if no approved namespace applies.

  • internal-packages/dashboard-agent/src/tool-curation.ts#L29-L75: add crumbs for the run-wait calculation path.
  • internal-packages/dashboard-agent/src/tool-curation.test.ts#L139-L240: add crumbs for the new test paths.

As per coding guidelines, “Add crumbs as you write code — not just when debugging.”

Source: Coding guidelines

internal-packages/dashboard-agent/src/tool-api.ts (1)

299-304: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add crumbs for the new runtime transitions.

Add // @Crumbs markers or `// `#region` `@crumbs blocks for the new trace-ledger and live queue-state behavior.

  • internal-packages/dashboard-agent/src/tool-api.ts#L299-L304: mark the trace-span recording transition.
  • internal-packages/dashboard-agent/src/tool-api.ts#L187-L193: mark the optional live queue-field propagation.
  • internal-packages/dashboard-agent/src/tools.ts#L42-L42: mark the shared-ledger handoff to API tools.

As per coding guidelines: “Add crumbs as you write code.”

Source: Coding guidelines

apps/webapp/app/presenters/v3/QueueRetrievePresenter.server.ts (1)

168-174: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Run the three diagnostic reads concurrently.

#slotHolders and #envConcurrency each await sequentially after the existing Promise.all. Both are independent of the queue-count reads, so the endpoint pays three serial round trips. Both helpers already swallow their own failures, so Promise.all cannot reject here.

♻️ Proposed refactor
-    const results = await Promise.all([
-      engine.lengthOfQueues(environment, [queue.name]),
-      engine.currentConcurrencyOfQueues(environment, [queue.name]),
-    ]);
-
-    const { slotHolders, slotHolderFacts } = await this.#slotHolders(environment, queue.name);
-    const envConcurrency = await this.#envConcurrency(environment);
+    const [lengths, concurrencies, { slotHolders, slotHolderFacts }, envConcurrency] =
+      await Promise.all([
+        engine.lengthOfQueues(environment, [queue.name]),
+        engine.currentConcurrencyOfQueues(environment, [queue.name]),
+        this.#slotHolders(environment, queue.name),
+        this.#envConcurrency(environment),
+      ]);

Then read concurrencies?.[queue.name] and lengths?.[queue.name] in toQueueItem.

internal-packages/dashboard-agent/src/repo-tools.ts (1)

232-245: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add required crumbs for the dirty-snapshot flow.

Add // @Crumbs markers or a `#region `@crumbs block at each changed dirty-state boundary.

  • internal-packages/dashboard-agent/src/repo-tools.ts#L232-L245: mark snapshot dirty-state propagation into the loaded workspace.
  • internal-packages/dashboard-agent/src/repo-tools.test.ts#L34-L44: mark dirty-snapshot fixture setup.
  • internal-packages/dashboard-agent/src/agent-runtime.ts#L325-L333: mark client snapshot dirty-state validation.
  • internal-packages/dashboard-agent-contracts/src/evidence.ts#L5-L13: mark dirty source-evidence contract propagation.
  • internal-packages/dashboard-agent/src/tool-schemas.ts#L597-L603: mark dirty-source guidance.

As per coding guidelines: “Add crumbs as you write code — not just when debugging.”

Source: Coding guidelines


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 21637dfc-c891-41bf-bbed-ea3e306ec06f

📥 Commits

Reviewing files that changed from the base of the PR and between c7f78e4 and 10c3d2b.

⛔ Files ignored due to path filters (1)
  • internal-packages/dashboard-agent/src/__snapshots__/prompt-prefix.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (58)
  • .server-changes/agent-chat-code-renderer-fallback.md
  • .server-changes/agent-grounded-queue-answers.md
  • apps/webapp/app/components/code/StreamdownRenderer.test.ts
  • apps/webapp/app/components/code/StreamdownRenderer.tsx
  • apps/webapp/app/components/dashboard-agent/InvestigationCard.render.test.ts
  • apps/webapp/app/components/dashboard-agent/InvestigationCard.tsx
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.test.ts
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.ts
  • apps/webapp/app/presenters/v3/ApiRetrieveRunPresenter.server.ts
  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.server.ts
  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.test.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.alerts.$channelId.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.alerts.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.watches.ts
  • apps/webapp/app/routes/api.v1.projects.$projectRef.$env.jwt.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.in.$.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
  • apps/webapp/app/services/dashboardAgent.server.ts
  • apps/webapp/app/services/dashboardAgentAlertContext.server.ts
  • apps/webapp/app/services/dashboardAgentTokenScope.ts
  • apps/webapp/app/services/dashboardAgentWatchInvestigate.server.ts
  • apps/webapp/app/services/dashboardAgentWatchRunChecks.ts
  • apps/webapp/app/services/userActorEnvironment.server.ts
  • apps/webapp/test/dashboardAgentTokenScope.test.ts
  • apps/webapp/test/dashboardAgentUserActorToken.test.ts
  • apps/webapp/test/dashboardAgentWatches.lifecycle.test.ts
  • apps/webapp/test/helpers/dashboardAgentWatchesTestHelpers.ts
  • apps/webapp/test/uatEnvironmentClaim.test.ts
  • apps/webapp/test/userActorOrgWideEnvironmentScope.test.ts
  • apps/webapp/vitest.config.ts
  • internal-packages/dashboard-agent-contracts/src/contracts.test.ts
  • internal-packages/dashboard-agent-contracts/src/evidence.ts
  • internal-packages/dashboard-agent-contracts/src/page-context.ts
  • internal-packages/dashboard-agent/src/agent-runtime.ts
  • internal-packages/dashboard-agent/src/dashboard-agent.test.ts
  • internal-packages/dashboard-agent/src/repo-tools.test.ts
  • internal-packages/dashboard-agent/src/repo-tools.ts
  • internal-packages/dashboard-agent/src/tool-api-branch.test.ts
  • internal-packages/dashboard-agent/src/tool-api-paths.test.ts
  • internal-packages/dashboard-agent/src/tool-api-transport.test.ts
  • internal-packages/dashboard-agent/src/tool-api.ts
  • internal-packages/dashboard-agent/src/tool-ask-support.test.ts
  • internal-packages/dashboard-agent/src/tool-curation.test.ts
  • internal-packages/dashboard-agent/src/tool-curation.ts
  • internal-packages/dashboard-agent/src/tool-evidence.test.ts
  • internal-packages/dashboard-agent/src/tool-evidence.ts
  • internal-packages/dashboard-agent/src/tool-query-retry-cap.test.ts
  • internal-packages/dashboard-agent/src/tool-queue.test.ts
  • internal-packages/dashboard-agent/src/tool-schemas.ts
  • internal-packages/dashboard-agent/src/tool-source-ledger.test.ts
  • internal-packages/dashboard-agent/src/tool-source-ledger.ts
  • internal-packages/dashboard-agent/src/tools.ts
  • internal-packages/run-engine/src/engine/index.ts
  • internal-packages/run-engine/src/run-queue/index.ts
  • internal-packages/run-engine/src/run-queue/tests/slotHolders.test.ts
  • packages/plugins/src/rbac.ts
  • scripts/seed-dashboard-agent-uat.ts

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

📜 Review details
⏰ Context from checks skipped due to timeout. (32)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (18, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (21, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (19, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (8, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (23, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (14, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (16, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (22, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (20, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (24, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (13, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (9, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (7, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (15, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (12, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (17, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (10, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (2, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (11, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (3, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (6, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (5, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (4, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (1, 24)
  • GitHub Check: internal / 🧪 Unit Tests: Internal
  • GitHub Check: packages / 🧪 Unit Tests: Packages (1, 3)
  • GitHub Check: packages / 🧪 Unit Tests: Packages (3, 3)
  • GitHub Check: e2e-webapp / 🧪 E2E Tests: Webapp (1, 2)
  • GitHub Check: packages / 🧪 Unit Tests: Packages (2, 3)
  • GitHub Check: e2e-webapp / 🧪 E2E Tests: Webapp (2, 2)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: 🛡️ E2E Auth Tests (full)
🧰 Additional context used
📓 Path-based instructions (14)
Use Remix flat-file route conventions with dot-separated segments; for example, `api.v1.tasks.$taskId.trigger.ts` maps to `/api/v1/tasks/:taskId/trigger`.

📄 CodeRabbit inference engine (apps/webapp/CLAUDE.md)

Files:

  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.in.$.ts
  • apps/webapp/app/routes/api.v1.projects.$projectRef.$env.jwt.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.alerts.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.watches.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.alerts.$channelId.ts
Never use `request.signal` to detect client disconnects. Use `getRequestAbortSignal()` from `app/services/httpAsyncStorage.server.ts`, which is wired to Express response close events.

📄 CodeRabbit inference engine (apps/webapp/CLAUDE.md)

Files:

  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.in.$.ts
  • apps/webapp/app/components/dashboard-agent/InvestigationCard.render.test.ts
  • apps/webapp/app/services/dashboardAgentWatchInvestigate.server.ts
  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.test.ts
  • apps/webapp/app/routes/api.v1.projects.$projectRef.$env.jwt.ts
  • apps/webapp/app/services/dashboardAgent.server.ts
  • apps/webapp/app/services/dashboardAgentTokenScope.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.alerts.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.ts
  • apps/webapp/app/services/dashboardAgentWatchRunChecks.ts
  • apps/webapp/app/services/userActorEnvironment.server.ts
  • apps/webapp/app/components/code/StreamdownRenderer.test.ts
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.ts
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.test.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.watches.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.alerts.$channelId.ts
  • apps/webapp/app/presenters/v3/ApiRetrieveRunPresenter.server.ts
  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.server.ts
  • apps/webapp/app/services/dashboardAgentAlertContext.server.ts
We use vitest exclusively. **Never mock anything** - use testcontainers instead.

📄 CodeRabbit inference engine (AGENTS.md)

Files:

  • apps/webapp/app/components/dashboard-agent/InvestigationCard.render.test.ts
  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.test.ts
  • apps/webapp/test/dashboardAgentTokenScope.test.ts
  • internal-packages/dashboard-agent/src/tool-api-transport.test.ts
  • internal-packages/dashboard-agent/src/tool-evidence.test.ts
  • internal-packages/dashboard-agent/src/tool-source-ledger.test.ts
  • apps/webapp/test/userActorOrgWideEnvironmentScope.test.ts
  • internal-packages/dashboard-agent/src/tool-api-branch.test.ts
  • internal-packages/dashboard-agent/src/tool-query-retry-cap.test.ts
  • internal-packages/dashboard-agent/src/tool-api-paths.test.ts
  • apps/webapp/test/dashboardAgentUserActorToken.test.ts
  • internal-packages/dashboard-agent/src/tool-ask-support.test.ts
  • internal-packages/dashboard-agent/src/tool-curation.test.ts
  • apps/webapp/app/components/code/StreamdownRenderer.test.ts
  • internal-packages/dashboard-agent/src/tool-queue.test.ts
  • apps/webapp/test/dashboardAgentWatches.lifecycle.test.ts
  • internal-packages/run-engine/src/run-queue/tests/slotHolders.test.ts
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.test.ts
  • internal-packages/dashboard-agent/src/repo-tools.test.ts
  • apps/webapp/test/uatEnvironmentClaim.test.ts
  • internal-packages/dashboard-agent/src/dashboard-agent.test.ts
  • internal-packages/dashboard-agent-contracts/src/contracts.test.ts
Test files must not import `app/env.server.ts`; pass configuration as options instead.

📄 CodeRabbit inference engine (apps/webapp/CLAUDE.md)

Files:

  • apps/webapp/app/components/dashboard-agent/InvestigationCard.render.test.ts
  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.test.ts
  • apps/webapp/test/dashboardAgentTokenScope.test.ts
  • apps/webapp/test/userActorOrgWideEnvironmentScope.test.ts
  • apps/webapp/test/dashboardAgentUserActorToken.test.ts
  • apps/webapp/app/components/code/StreamdownRenderer.test.ts
  • apps/webapp/test/dashboardAgentWatches.lifecycle.test.ts
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.test.ts
  • apps/webapp/test/uatEnvironmentClaim.test.ts
For dashboard changes, visually verify the running Remix app with Chrome DevTools MCP, using snapshots, screenshots, interaction, and console-message checks as appropriate.

📄 CodeRabbit inference engine (apps/webapp/CLAUDE.md)

Files:

  • apps/webapp/app/components/dashboard-agent/InvestigationCard.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.in.$.ts
  • apps/webapp/app/components/dashboard-agent/InvestigationCard.render.test.ts
  • apps/webapp/app/services/dashboardAgentWatchInvestigate.server.ts
  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.test.ts
  • apps/webapp/app/routes/api.v1.projects.$projectRef.$env.jwt.ts
  • apps/webapp/app/services/dashboardAgent.server.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
  • apps/webapp/app/services/dashboardAgentTokenScope.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.alerts.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.ts
  • apps/webapp/app/services/dashboardAgentWatchRunChecks.ts
  • apps/webapp/app/services/userActorEnvironment.server.ts
  • apps/webapp/app/components/code/StreamdownRenderer.test.ts
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.ts
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.test.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.watches.ts
  • apps/webapp/app/components/code/StreamdownRenderer.tsx
  • apps/webapp/app/routes/api.v1.dashboard-agent.alerts.$channelId.ts
  • apps/webapp/app/presenters/v3/ApiRetrieveRunPresenter.server.ts
  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.server.ts
  • apps/webapp/app/services/dashboardAgentAlertContext.server.ts
**Prefer static imports over dynamic imports.** Only use dynamic `import()` when:

📄 CodeRabbit inference engine (AGENTS.md)

Files:

  • apps/webapp/app/components/dashboard-agent/InvestigationCard.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.in.$.ts
  • apps/webapp/app/components/dashboard-agent/InvestigationCard.render.test.ts
  • internal-packages/dashboard-agent/src/tools.ts
  • apps/webapp/app/services/dashboardAgentWatchInvestigate.server.ts
  • internal-packages/run-engine/src/engine/index.ts
  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.test.ts
  • apps/webapp/app/routes/api.v1.projects.$projectRef.$env.jwt.ts
  • apps/webapp/test/dashboardAgentTokenScope.test.ts
  • internal-packages/dashboard-agent-contracts/src/page-context.ts
  • internal-packages/dashboard-agent/src/tool-api-transport.test.ts
  • apps/webapp/test/helpers/dashboardAgentWatchesTestHelpers.ts
  • apps/webapp/app/services/dashboardAgent.server.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
  • internal-packages/dashboard-agent/src/agent-runtime.ts
  • internal-packages/dashboard-agent/src/tool-evidence.test.ts
  • apps/webapp/app/services/dashboardAgentTokenScope.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.alerts.ts
  • internal-packages/dashboard-agent/src/tool-source-ledger.test.ts
  • internal-packages/dashboard-agent/src/tool-evidence.ts
  • apps/webapp/vitest.config.ts
  • apps/webapp/test/userActorOrgWideEnvironmentScope.test.ts
  • internal-packages/dashboard-agent/src/tool-api-branch.test.ts
  • internal-packages/dashboard-agent/src/tool-query-retry-cap.test.ts
  • internal-packages/dashboard-agent/src/tool-api-paths.test.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.ts
  • internal-packages/dashboard-agent-contracts/src/evidence.ts
  • apps/webapp/test/dashboardAgentUserActorToken.test.ts
  • internal-packages/dashboard-agent/src/tool-ask-support.test.ts
  • apps/webapp/app/services/dashboardAgentWatchRunChecks.ts
  • internal-packages/dashboard-agent/src/tool-curation.test.ts
  • apps/webapp/app/services/userActorEnvironment.server.ts
  • apps/webapp/app/components/code/StreamdownRenderer.test.ts
  • internal-packages/dashboard-agent/src/tool-queue.test.ts
  • apps/webapp/test/dashboardAgentWatches.lifecycle.test.ts
  • internal-packages/run-engine/src/run-queue/tests/slotHolders.test.ts
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.ts
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.test.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.watches.ts
  • internal-packages/dashboard-agent/src/tool-api.ts
  • apps/webapp/app/components/code/StreamdownRenderer.tsx
  • internal-packages/dashboard-agent/src/tool-source-ledger.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.alerts.$channelId.ts
  • internal-packages/dashboard-agent/src/tool-curation.ts
  • internal-packages/dashboard-agent/src/repo-tools.test.ts
  • apps/webapp/test/uatEnvironmentClaim.test.ts
  • internal-packages/dashboard-agent/src/dashboard-agent.test.ts
  • apps/webapp/app/presenters/v3/ApiRetrieveRunPresenter.server.ts
  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.server.ts
  • internal-packages/run-engine/src/run-queue/index.ts
  • internal-packages/dashboard-agent/src/repo-tools.ts
  • scripts/seed-dashboard-agent-uat.ts
  • internal-packages/dashboard-agent/src/tool-schemas.ts
  • internal-packages/dashboard-agent-contracts/src/contracts.test.ts
  • packages/plugins/src/rbac.ts
  • apps/webapp/app/services/dashboardAgentAlertContext.server.ts
Add crumbs as you write code — not just when debugging. Mark lines with

📄 CodeRabbit inference engine (AGENTS.md)

Files:

  • apps/webapp/app/components/dashboard-agent/InvestigationCard.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.in.$.ts
  • apps/webapp/app/components/dashboard-agent/InvestigationCard.render.test.ts
  • internal-packages/dashboard-agent/src/tools.ts
  • apps/webapp/app/services/dashboardAgentWatchInvestigate.server.ts
  • internal-packages/run-engine/src/engine/index.ts
  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.test.ts
  • apps/webapp/app/routes/api.v1.projects.$projectRef.$env.jwt.ts
  • apps/webapp/test/dashboardAgentTokenScope.test.ts
  • internal-packages/dashboard-agent-contracts/src/page-context.ts
  • internal-packages/dashboard-agent/src/tool-api-transport.test.ts
  • apps/webapp/test/helpers/dashboardAgentWatchesTestHelpers.ts
  • apps/webapp/app/services/dashboardAgent.server.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
  • internal-packages/dashboard-agent/src/agent-runtime.ts
  • internal-packages/dashboard-agent/src/tool-evidence.test.ts
  • apps/webapp/app/services/dashboardAgentTokenScope.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.alerts.ts
  • internal-packages/dashboard-agent/src/tool-source-ledger.test.ts
  • internal-packages/dashboard-agent/src/tool-evidence.ts
  • apps/webapp/vitest.config.ts
  • apps/webapp/test/userActorOrgWideEnvironmentScope.test.ts
  • internal-packages/dashboard-agent/src/tool-api-branch.test.ts
  • internal-packages/dashboard-agent/src/tool-query-retry-cap.test.ts
  • internal-packages/dashboard-agent/src/tool-api-paths.test.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.ts
  • internal-packages/dashboard-agent-contracts/src/evidence.ts
  • apps/webapp/test/dashboardAgentUserActorToken.test.ts
  • internal-packages/dashboard-agent/src/tool-ask-support.test.ts
  • apps/webapp/app/services/dashboardAgentWatchRunChecks.ts
  • internal-packages/dashboard-agent/src/tool-curation.test.ts
  • apps/webapp/app/services/userActorEnvironment.server.ts
  • apps/webapp/app/components/code/StreamdownRenderer.test.ts
  • internal-packages/dashboard-agent/src/tool-queue.test.ts
  • apps/webapp/test/dashboardAgentWatches.lifecycle.test.ts
  • internal-packages/run-engine/src/run-queue/tests/slotHolders.test.ts
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.ts
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.test.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.watches.ts
  • internal-packages/dashboard-agent/src/tool-api.ts
  • apps/webapp/app/components/code/StreamdownRenderer.tsx
  • internal-packages/dashboard-agent/src/tool-source-ledger.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.alerts.$channelId.ts
  • internal-packages/dashboard-agent/src/tool-curation.ts
  • internal-packages/dashboard-agent/src/repo-tools.test.ts
  • apps/webapp/test/uatEnvironmentClaim.test.ts
  • internal-packages/dashboard-agent/src/dashboard-agent.test.ts
  • apps/webapp/app/presenters/v3/ApiRetrieveRunPresenter.server.ts
  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.server.ts
  • internal-packages/run-engine/src/run-queue/index.ts
  • internal-packages/dashboard-agent/src/repo-tools.ts
  • scripts/seed-dashboard-agent-uat.ts
  • internal-packages/dashboard-agent/src/tool-schemas.ts
  • internal-packages/dashboard-agent-contracts/src/contracts.test.ts
  • packages/plugins/src/rbac.ts
  • apps/webapp/app/services/dashboardAgentAlertContext.server.ts
Use zod for validation in packages/core and apps/webapp

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Files:

  • apps/webapp/app/components/dashboard-agent/InvestigationCard.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.in.$.ts
  • apps/webapp/app/components/dashboard-agent/InvestigationCard.render.test.ts
  • apps/webapp/app/services/dashboardAgentWatchInvestigate.server.ts
  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.test.ts
  • apps/webapp/app/routes/api.v1.projects.$projectRef.$env.jwt.ts
  • apps/webapp/test/dashboardAgentTokenScope.test.ts
  • apps/webapp/test/helpers/dashboardAgentWatchesTestHelpers.ts
  • apps/webapp/app/services/dashboardAgent.server.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
  • apps/webapp/app/services/dashboardAgentTokenScope.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.alerts.ts
  • apps/webapp/vitest.config.ts
  • apps/webapp/test/userActorOrgWideEnvironmentScope.test.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.ts
  • apps/webapp/test/dashboardAgentUserActorToken.test.ts
  • apps/webapp/app/services/dashboardAgentWatchRunChecks.ts
  • apps/webapp/app/services/userActorEnvironment.server.ts
  • apps/webapp/app/components/code/StreamdownRenderer.test.ts
  • apps/webapp/test/dashboardAgentWatches.lifecycle.test.ts
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.ts
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.test.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.watches.ts
  • apps/webapp/app/components/code/StreamdownRenderer.tsx
  • apps/webapp/app/routes/api.v1.dashboard-agent.alerts.$channelId.ts
  • apps/webapp/test/uatEnvironmentClaim.test.ts
  • apps/webapp/app/presenters/v3/ApiRetrieveRunPresenter.server.ts
  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.server.ts
  • apps/webapp/app/services/dashboardAgentAlertContext.server.ts
Do not import `env.server.ts` directly or indirectly into test files; instead pass environment-dependent values through options/parameters to make code testable

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Files:

  • apps/webapp/app/components/dashboard-agent/InvestigationCard.render.test.ts
  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.test.ts
  • apps/webapp/test/dashboardAgentTokenScope.test.ts
  • apps/webapp/test/userActorOrgWideEnvironmentScope.test.ts
  • apps/webapp/test/dashboardAgentUserActorToken.test.ts
  • apps/webapp/app/components/code/StreamdownRenderer.test.ts
  • apps/webapp/test/dashboardAgentWatches.lifecycle.test.ts
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.test.ts
  • apps/webapp/test/uatEnvironmentClaim.test.ts
Access environment variables through the `env` export of `env.server.ts` instead of directly accessing `process.env`

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Files:

  • apps/webapp/app/components/dashboard-agent/InvestigationCard.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.in.$.ts
  • apps/webapp/app/components/dashboard-agent/InvestigationCard.render.test.ts
  • apps/webapp/app/services/dashboardAgentWatchInvestigate.server.ts
  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.test.ts
  • apps/webapp/app/routes/api.v1.projects.$projectRef.$env.jwt.ts
  • apps/webapp/test/dashboardAgentTokenScope.test.ts
  • apps/webapp/test/helpers/dashboardAgentWatchesTestHelpers.ts
  • apps/webapp/app/services/dashboardAgent.server.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
  • apps/webapp/app/services/dashboardAgentTokenScope.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.alerts.ts
  • apps/webapp/vitest.config.ts
  • apps/webapp/test/userActorOrgWideEnvironmentScope.test.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.ts
  • apps/webapp/test/dashboardAgentUserActorToken.test.ts
  • apps/webapp/app/services/dashboardAgentWatchRunChecks.ts
  • apps/webapp/app/services/userActorEnvironment.server.ts
  • apps/webapp/app/components/code/StreamdownRenderer.test.ts
  • apps/webapp/test/dashboardAgentWatches.lifecycle.test.ts
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.ts
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.test.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.watches.ts
  • apps/webapp/app/components/code/StreamdownRenderer.tsx
  • apps/webapp/app/routes/api.v1.dashboard-agent.alerts.$channelId.ts
  • apps/webapp/test/uatEnvironmentClaim.test.ts
  • apps/webapp/app/presenters/v3/ApiRetrieveRunPresenter.server.ts
  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.server.ts
  • apps/webapp/app/services/dashboardAgentAlertContext.server.ts
Use vitest for all tests in the Trigger.dev repository

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Files:

  • apps/webapp/app/components/dashboard-agent/InvestigationCard.render.test.ts
  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.test.ts
  • apps/webapp/test/dashboardAgentTokenScope.test.ts
  • internal-packages/dashboard-agent/src/tool-api-transport.test.ts
  • internal-packages/dashboard-agent/src/tool-evidence.test.ts
  • internal-packages/dashboard-agent/src/tool-source-ledger.test.ts
  • apps/webapp/test/userActorOrgWideEnvironmentScope.test.ts
  • internal-packages/dashboard-agent/src/tool-api-branch.test.ts
  • internal-packages/dashboard-agent/src/tool-query-retry-cap.test.ts
  • internal-packages/dashboard-agent/src/tool-api-paths.test.ts
  • apps/webapp/test/dashboardAgentUserActorToken.test.ts
  • internal-packages/dashboard-agent/src/tool-ask-support.test.ts
  • internal-packages/dashboard-agent/src/tool-curation.test.ts
  • apps/webapp/app/components/code/StreamdownRenderer.test.ts
  • internal-packages/dashboard-agent/src/tool-queue.test.ts
  • apps/webapp/test/dashboardAgentWatches.lifecycle.test.ts
  • internal-packages/run-engine/src/run-queue/tests/slotHolders.test.ts
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.test.ts
  • internal-packages/dashboard-agent/src/repo-tools.test.ts
  • apps/webapp/test/uatEnvironmentClaim.test.ts
  • internal-packages/dashboard-agent/src/dashboard-agent.test.ts
  • internal-packages/dashboard-agent-contracts/src/contracts.test.ts
Use function declarations instead of default exports

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Files:

  • apps/webapp/app/components/dashboard-agent/InvestigationCard.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.in.$.ts
  • apps/webapp/app/components/dashboard-agent/InvestigationCard.render.test.ts
  • internal-packages/dashboard-agent/src/tools.ts
  • apps/webapp/app/services/dashboardAgentWatchInvestigate.server.ts
  • internal-packages/run-engine/src/engine/index.ts
  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.test.ts
  • apps/webapp/app/routes/api.v1.projects.$projectRef.$env.jwt.ts
  • apps/webapp/test/dashboardAgentTokenScope.test.ts
  • internal-packages/dashboard-agent-contracts/src/page-context.ts
  • internal-packages/dashboard-agent/src/tool-api-transport.test.ts
  • apps/webapp/test/helpers/dashboardAgentWatchesTestHelpers.ts
  • apps/webapp/app/services/dashboardAgent.server.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
  • internal-packages/dashboard-agent/src/agent-runtime.ts
  • internal-packages/dashboard-agent/src/tool-evidence.test.ts
  • apps/webapp/app/services/dashboardAgentTokenScope.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.alerts.ts
  • internal-packages/dashboard-agent/src/tool-source-ledger.test.ts
  • internal-packages/dashboard-agent/src/tool-evidence.ts
  • apps/webapp/vitest.config.ts
  • apps/webapp/test/userActorOrgWideEnvironmentScope.test.ts
  • internal-packages/dashboard-agent/src/tool-api-branch.test.ts
  • internal-packages/dashboard-agent/src/tool-query-retry-cap.test.ts
  • internal-packages/dashboard-agent/src/tool-api-paths.test.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.ts
  • internal-packages/dashboard-agent-contracts/src/evidence.ts
  • apps/webapp/test/dashboardAgentUserActorToken.test.ts
  • internal-packages/dashboard-agent/src/tool-ask-support.test.ts
  • apps/webapp/app/services/dashboardAgentWatchRunChecks.ts
  • internal-packages/dashboard-agent/src/tool-curation.test.ts
  • apps/webapp/app/services/userActorEnvironment.server.ts
  • apps/webapp/app/components/code/StreamdownRenderer.test.ts
  • internal-packages/dashboard-agent/src/tool-queue.test.ts
  • apps/webapp/test/dashboardAgentWatches.lifecycle.test.ts
  • internal-packages/run-engine/src/run-queue/tests/slotHolders.test.ts
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.ts
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.test.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.watches.ts
  • internal-packages/dashboard-agent/src/tool-api.ts
  • apps/webapp/app/components/code/StreamdownRenderer.tsx
  • internal-packages/dashboard-agent/src/tool-source-ledger.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.alerts.$channelId.ts
  • internal-packages/dashboard-agent/src/tool-curation.ts
  • internal-packages/dashboard-agent/src/repo-tools.test.ts
  • apps/webapp/test/uatEnvironmentClaim.test.ts
  • internal-packages/dashboard-agent/src/dashboard-agent.test.ts
  • apps/webapp/app/presenters/v3/ApiRetrieveRunPresenter.server.ts
  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.server.ts
  • internal-packages/run-engine/src/run-queue/index.ts
  • internal-packages/dashboard-agent/src/repo-tools.ts
  • scripts/seed-dashboard-agent-uat.ts
  • internal-packages/dashboard-agent/src/tool-schemas.ts
  • internal-packages/dashboard-agent-contracts/src/contracts.test.ts
  • packages/plugins/src/rbac.ts
  • apps/webapp/app/services/dashboardAgentAlertContext.server.ts
Use types over interfaces for TypeScript

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Files:

  • apps/webapp/app/components/dashboard-agent/InvestigationCard.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.in.$.ts
  • apps/webapp/app/components/dashboard-agent/InvestigationCard.render.test.ts
  • internal-packages/dashboard-agent/src/tools.ts
  • apps/webapp/app/services/dashboardAgentWatchInvestigate.server.ts
  • internal-packages/run-engine/src/engine/index.ts
  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.test.ts
  • apps/webapp/app/routes/api.v1.projects.$projectRef.$env.jwt.ts
  • apps/webapp/test/dashboardAgentTokenScope.test.ts
  • internal-packages/dashboard-agent-contracts/src/page-context.ts
  • internal-packages/dashboard-agent/src/tool-api-transport.test.ts
  • apps/webapp/test/helpers/dashboardAgentWatchesTestHelpers.ts
  • apps/webapp/app/services/dashboardAgent.server.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
  • internal-packages/dashboard-agent/src/agent-runtime.ts
  • internal-packages/dashboard-agent/src/tool-evidence.test.ts
  • apps/webapp/app/services/dashboardAgentTokenScope.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.alerts.ts
  • internal-packages/dashboard-agent/src/tool-source-ledger.test.ts
  • internal-packages/dashboard-agent/src/tool-evidence.ts
  • apps/webapp/vitest.config.ts
  • apps/webapp/test/userActorOrgWideEnvironmentScope.test.ts
  • internal-packages/dashboard-agent/src/tool-api-branch.test.ts
  • internal-packages/dashboard-agent/src/tool-query-retry-cap.test.ts
  • internal-packages/dashboard-agent/src/tool-api-paths.test.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.ts
  • internal-packages/dashboard-agent-contracts/src/evidence.ts
  • apps/webapp/test/dashboardAgentUserActorToken.test.ts
  • internal-packages/dashboard-agent/src/tool-ask-support.test.ts
  • apps/webapp/app/services/dashboardAgentWatchRunChecks.ts
  • internal-packages/dashboard-agent/src/tool-curation.test.ts
  • apps/webapp/app/services/userActorEnvironment.server.ts
  • apps/webapp/app/components/code/StreamdownRenderer.test.ts
  • internal-packages/dashboard-agent/src/tool-queue.test.ts
  • apps/webapp/test/dashboardAgentWatches.lifecycle.test.ts
  • internal-packages/run-engine/src/run-queue/tests/slotHolders.test.ts
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.ts
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.test.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.watches.ts
  • internal-packages/dashboard-agent/src/tool-api.ts
  • apps/webapp/app/components/code/StreamdownRenderer.tsx
  • internal-packages/dashboard-agent/src/tool-source-ledger.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.alerts.$channelId.ts
  • internal-packages/dashboard-agent/src/tool-curation.ts
  • internal-packages/dashboard-agent/src/repo-tools.test.ts
  • apps/webapp/test/uatEnvironmentClaim.test.ts
  • internal-packages/dashboard-agent/src/dashboard-agent.test.ts
  • apps/webapp/app/presenters/v3/ApiRetrieveRunPresenter.server.ts
  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.server.ts
  • internal-packages/run-engine/src/run-queue/index.ts
  • internal-packages/dashboard-agent/src/repo-tools.ts
  • scripts/seed-dashboard-agent-uat.ts
  • internal-packages/dashboard-agent/src/tool-schemas.ts
  • internal-packages/dashboard-agent-contracts/src/contracts.test.ts
  • packages/plugins/src/rbac.ts
  • apps/webapp/app/services/dashboardAgentAlertContext.server.ts
When creating or editing OTEL metrics (counters, histograms, gauges), ensure metric attributes have low cardinality by using only enums, booleans, bounded error codes, or bounded shard IDs

📄 CodeRabbit inference engine (.cursor/rules/otel-metrics.mdc)

Files:

  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.in.$.ts
  • apps/webapp/app/components/dashboard-agent/InvestigationCard.render.test.ts
  • internal-packages/dashboard-agent/src/tools.ts
  • apps/webapp/app/services/dashboardAgentWatchInvestigate.server.ts
  • internal-packages/run-engine/src/engine/index.ts
  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.test.ts
  • apps/webapp/app/routes/api.v1.projects.$projectRef.$env.jwt.ts
  • apps/webapp/test/dashboardAgentTokenScope.test.ts
  • internal-packages/dashboard-agent-contracts/src/page-context.ts
  • internal-packages/dashboard-agent/src/tool-api-transport.test.ts
  • apps/webapp/test/helpers/dashboardAgentWatchesTestHelpers.ts
  • apps/webapp/app/services/dashboardAgent.server.ts
  • internal-packages/dashboard-agent/src/agent-runtime.ts
  • internal-packages/dashboard-agent/src/tool-evidence.test.ts
  • apps/webapp/app/services/dashboardAgentTokenScope.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.alerts.ts
  • internal-packages/dashboard-agent/src/tool-source-ledger.test.ts
  • internal-packages/dashboard-agent/src/tool-evidence.ts
  • apps/webapp/vitest.config.ts
  • apps/webapp/test/userActorOrgWideEnvironmentScope.test.ts
  • internal-packages/dashboard-agent/src/tool-api-branch.test.ts
  • internal-packages/dashboard-agent/src/tool-query-retry-cap.test.ts
  • internal-packages/dashboard-agent/src/tool-api-paths.test.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.ts
  • internal-packages/dashboard-agent-contracts/src/evidence.ts
  • apps/webapp/test/dashboardAgentUserActorToken.test.ts
  • internal-packages/dashboard-agent/src/tool-ask-support.test.ts
  • apps/webapp/app/services/dashboardAgentWatchRunChecks.ts
  • internal-packages/dashboard-agent/src/tool-curation.test.ts
  • apps/webapp/app/services/userActorEnvironment.server.ts
  • apps/webapp/app/components/code/StreamdownRenderer.test.ts
  • internal-packages/dashboard-agent/src/tool-queue.test.ts
  • apps/webapp/test/dashboardAgentWatches.lifecycle.test.ts
  • internal-packages/run-engine/src/run-queue/tests/slotHolders.test.ts
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.ts
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.test.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.watches.ts
  • internal-packages/dashboard-agent/src/tool-api.ts
  • internal-packages/dashboard-agent/src/tool-source-ledger.ts
  • apps/webapp/app/routes/api.v1.dashboard-agent.alerts.$channelId.ts
  • internal-packages/dashboard-agent/src/tool-curation.ts
  • internal-packages/dashboard-agent/src/repo-tools.test.ts
  • apps/webapp/test/uatEnvironmentClaim.test.ts
  • internal-packages/dashboard-agent/src/dashboard-agent.test.ts
  • apps/webapp/app/presenters/v3/ApiRetrieveRunPresenter.server.ts
  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.server.ts
  • internal-packages/run-engine/src/run-queue/index.ts
  • internal-packages/dashboard-agent/src/repo-tools.ts
  • scripts/seed-dashboard-agent-uat.ts
  • internal-packages/dashboard-agent/src/tool-schemas.ts
  • internal-packages/dashboard-agent-contracts/src/contracts.test.ts
  • packages/plugins/src/rbac.ts
  • apps/webapp/app/services/dashboardAgentAlertContext.server.ts
🧠 Learnings (5)
📚 Learning: 2026-07-26T13:14:02.968Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 4378
File: .server-changes/realtime-run-reads-from-primary.md:0-0
Timestamp: 2026-07-26T13:14:02.968Z
Learning: For files in the .server-changes directory, the body text is published verbatim as dashboard-facing user release notes. Write entries in terms of user-visible behavior (what users can do/see), and avoid implementation-oriented details such as environment-variable names, internal mechanisms, or configuration knobs. If you need to include operational/configuration specifics, put those details in the PR description instead of the .server-changes entry.

Applied to files:

  • .server-changes/agent-chat-code-renderer-fallback.md
  • .server-changes/agent-grounded-queue-answers.md
📚 Learning: 2026-06-04T18:16:35.386Z
Learnt from: nicktrn
Repo: triggerdotdev/trigger.dev PR: 3836
File: apps/supervisor/src/backpressure/backpressureMonitor.ts:3-5
Timestamp: 2026-06-04T18:16:35.386Z
Learning: When reviewing TypeScript in this repo, apply the rule “prefer type aliases over interfaces” only to data/object shapes and union/intersection type modeling. If an interface is being used as a behavioral contract for collaborators to implement (e.g., method-shape interfaces that define required behavior, such as `BackpressureLogger` / `BackpressureSignalSource` in `apps/supervisor/src/backpressure/backpressureMonitor.ts`), keep it as an `interface` and do not flag it as a type-alias-vs-interface violation.

Applied to files:

  • apps/webapp/app/services/dashboardAgentTokenScope.ts
  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.server.ts
  • internal-packages/run-engine/src/run-queue/index.ts
📚 Learning: 2026-05-01T15:45:08.099Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 3499
File: packages/plugins/tsup.config.ts:3-3
Timestamp: 2026-05-01T15:45:08.099Z
Learning: In build/tool configuration files (e.g., tsup.config.ts, vite.config.ts, vitest.config.ts), follow the tool’s documented export pattern and use `export default defineConfig(...)` (or the equivalent documented default export). The repo-wide guideline “use named exports instead of default exports” should apply only to application code (*.{ts,tsx,js,jsx}), not to these build/tool config files—so do not flag `export default defineConfig(...)` in these config files as a violation.

Applied to files:

  • apps/webapp/vitest.config.ts
📚 Learning: 2026-06-16T09:19:47.637Z
Learnt from: d-cs
Repo: triggerdotdev/trigger.dev PR: 3960
File: apps/webapp/test/prismaInfrastructureErrorCapture.test.ts:0-0
Timestamp: 2026-06-16T09:19:47.637Z
Learning: In this repo’s Vitest setup, `vitest.config.ts` uses `globals: true`, so identifiers like `vi`, `describe`, `it`, and `expect` are available as globals in Vitest test files. During code review, do not flag missing `vi`/`describe`/`it`/`expect` imports as a runtime error or correctness issue when they’re used in `*.test.ts/tsx` or `*.spec.ts/tsx` files. Explicit imports are still preferred for consistency, but they’re not required for runtime behavior.

Applied to files:

  • internal-packages/run-engine/src/run-queue/tests/slotHolders.test.ts
  • apps/webapp/test/uatEnvironmentClaim.test.ts
📚 Learning: 2026-05-12T21:04:05.815Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 3542
File: apps/webapp/app/components/sessions/v1/SessionStatus.tsx:1-3
Timestamp: 2026-05-12T21:04:05.815Z
Learning: In this Remix + TypeScript codebase, do not flag a server/client boundary violation when a file imports only types from a module matching `*.server`.

Specifically, it’s safe to import types using `import type { Foo } from "*.server"` or `import { type Foo } from "*.server"` because TypeScript erases type-only imports at compile time and they emit no JavaScript, so they won’t cross the Remix server/client bundle boundary.

Only raise the boundary concern for value imports (e.g., `import { Foo }` without `type`, or `import Foo`), since those produce JavaScript output.

Applied to files:

  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.server.ts
🪛 ast-grep (0.45.2)
internal-packages/dashboard-agent/src/repo-tools.test.ts

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { execFileSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

internal-packages/dashboard-agent/src/repo-tools.ts

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { execFile } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

🪛 GitHub Check: code-quality / code-quality
apps/webapp/app/components/code/StreamdownRenderer.tsx

[failure] 67-67: typescript(consistent-type-imports)
apps/webapp/app/components/code/StreamdownRenderer.tsx:67:77: import() type annotations are forbidden.


[failure] 67-67: typescript(consistent-type-imports)
apps/webapp/app/components/code/StreamdownRenderer.tsx:67:42: import() type annotations are forbidden.


[failure] 67-67: typescript(consistent-type-imports)
apps/webapp/app/components/code/StreamdownRenderer.tsx:67:13: import() type annotations are forbidden.

🔇 Additional comments (14)
scripts/seed-dashboard-agent-uat.ts (1)

61-149: LGTM!

Also applies to: 155-238, 244-341, 357-431, 437-483, 489-568, 635-708, 714-837

apps/webapp/app/components/dashboard-agent/InvestigationCard.tsx (1)

211-216: LGTM!

apps/webapp/app/components/dashboard-agent/InvestigationCard.render.test.ts (1)

69-79: LGTM!

apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx (1)

1185-1195: LGTM!

internal-packages/dashboard-agent/src/tool-curation.ts (1)

50-63: 🎯 Functional Correctness

Keep the fallback aligned with describeRunWait. describeRunWait explicitly uses run.startedAt ?? now for stale queuedAt values, and computeRunWait matches that contract.

.server-changes/agent-chat-code-renderer-fallback.md (1)

1-6: LGTM!

apps/webapp/app/components/code/StreamdownRenderer.tsx (1)

65-68: 📐 Maintainability & Code Quality

No change needed. StreamdownRenderer.tsx already uses type-only namespace imports in the tuple annotation.

apps/webapp/app/presenters/v3/ApiRetrieveRunPresenter.server.ts (1)

41-41: LGTM!

Also applies to: 697-698

apps/webapp/app/services/dashboardAgentWatchRunChecks.ts (1)

34-42: LGTM!

internal-packages/run-engine/src/run-queue/index.ts (1)

715-730: LGTM!

internal-packages/run-engine/src/engine/index.ts (1)

1736-1742: LGTM!

internal-packages/run-engine/src/run-queue/tests/slotHolders.test.ts (1)

75-265: LGTM!

apps/webapp/app/presenters/v3/QueueRetrievePresenter.server.ts (1)

227-295: LGTM!

.server-changes/agent-grounded-queue-answers.md (1)

1-6: LGTM!

Comment on lines +99 to +117
const importer = vi.fn().mockResolvedValue("ok");
await expect(retryImport(importer, [0, 0])).resolves.toBe("ok");
expect(importer).toHaveBeenCalledTimes(1);
});

it("retries after failures then succeeds", async () => {
const importer = vi
.fn()
.mockRejectedValueOnce(new Error("fail1"))
.mockRejectedValueOnce(new Error("fail2"))
.mockResolvedValue("ok");
await expect(retryImport(importer, [0, 0])).resolves.toBe("ok");
expect(importer).toHaveBeenCalledTimes(3);
});

it("throws after exhausting retries", async () => {
const importer = vi.fn().mockRejectedValue(new Error("always fails"));
await expect(retryImport(importer, [0, 0])).rejects.toThrow("always fails");
expect(importer).toHaveBeenCalledTimes(3);

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.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Remove the vi.fn() mocks from these tests.

Use deterministic importer closures with local attempt counters. This tests retryImport without mocks.

As per coding guidelines: “We use vitest exclusively. Never mock anything - use testcontainers instead.”

Source: Coding guidelines

Comment on lines +126 to +141
const priorListeners = process.listeners("unhandledRejection");
process.removeAllListeners("unhandledRejection");
const caught = new Promise<Error>((resolve) => {
process.once("unhandledRejection", (err) => resolve(err as Error));
});

const mod = await loadStreamdownRenderer(() => Promise.reject(new Error("boom")), [0, 0]);
const html = renderToStaticMarkup(createElement(mod.default, null, "hello **world**"));
expect(html).toContain("hello");

const dispatched = await caught;
expect(dispatched.message).toMatch(/boom/);

for (const listener of priorListeners) {
process.on("unhandledRejection", listener as NodeJS.UnhandledRejectionListener);
}

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 | 🟡 Minor | ⚡ Quick win

Restore process listeners in a finally block.

If loadStreamdownRenderer, rendering, or an assertion fails, the loop at Line 139 does not run. Later tests then run without the original unhandledRejection listeners.

Wrap the test body after Line 127 in try/finally and restore the listeners in finally.

Comment on lines +155 to +161
signals.push({
kind: "concurrency_saturation",
severity: queued >= limit ? "crit" : "warn",
scope: "env",
limit,
current: running,
});

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.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

🔎 Supported by static analysis

🏁 Script executed:

printf '%s\n' '--- applicable repository conventions ---'
find /tmp/coderabbit-repo-knowledge/triggerdotdev-trigger-dev-0bdd0019 -type f -name '*.md' -print
printf '%s\n' '--- changed files and hunks ---'
git diff --stat
git diff -- apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.ts \
  apps/webapp/app/presenters/v3/QueueRetrievePresenter.test.ts \
  apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.test.ts \
  internal-packages/dashboard-agent-contracts/src/page-context.ts \
  internal-packages/dashboard-agent-contracts/src/contracts.test.ts \
  apps/webapp/vitest.config.ts
printf '%s\n' '--- crumb policy references ---'
rg -n -C 3 'crumb|namespace|agentcrumbs' /tmp/coderabbit-repo-knowledge/triggerdotdev-trigger-dev-0bdd0019 \
  --glob '*.md'

Repository: triggerdotdev/trigger.dev

Length of output: 8339


🏁 Script executed:

printf '%s\n' '--- crumb convention and namespace table ---'
sed -n '80,115p' /tmp/coderabbit-repo-knowledge/triggerdotdev-trigger-dev-0bdd0019/conventions/repo-wide.md
printf '%s\n' '--- repository state ---'
git status --short
git diff --name-only
printf '%s\n' '--- current crumb markers in the listed files ---'
rg -n '`@crumbs`|agentcrumbs' \
  apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.ts \
  apps/webapp/app/presenters/v3/QueueRetrievePresenter.test.ts \
  apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.test.ts \
  internal-packages/dashboard-agent-contracts/src/page-context.ts \
  internal-packages/dashboard-agent-contracts/src/contracts.test.ts \
  apps/webapp/vitest.config.ts || true
printf '%s\n' '--- exact listed source ranges ---'
for spec in \
  'apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.ts:150:165' \
  'apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.ts:218:244' \
  'apps/webapp/app/presenters/v3/QueueRetrievePresenter.test.ts:1:68' \
  'apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.test.ts:232:265' \
  'apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.test.ts:306:323' \
  'apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.test.ts:413:438' \
  'internal-packages/dashboard-agent-contracts/src/page-context.ts:138:155' \
  'internal-packages/dashboard-agent-contracts/src/contracts.test.ts:105:130' \
  'apps/webapp/vitest.config.ts:22:31'; do
  file=${spec%%:*}; range=${spec#*:}; start=${range%%:*}; end=${range##*:}
  printf '%s\n' "--- $file:$start-$end ---"
  sed -n "${start},${end}p" "$file"
done

Repository: triggerdotdev/trigger.dev

Length of output: 9684


Add approved crumbs to the changed blocks before merge.

The repository convention requires crumbs during development and strips them before merge. None of the listed blocks contains a crumb marker. Use an existing approved namespace; do not invent one.

📍 Affects 6 files
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.ts#L155-L161 (this comment)
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.ts#L223-L239
  • apps/webapp/app/presenters/v3/QueueRetrievePresenter.test.ts#L4-L64
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.test.ts#L237-L261
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.test.ts#L311-L320
  • apps/webapp/app/components/dashboard-agent/suggested-prompts/page-mappers.test.ts#L418-L434
  • internal-packages/dashboard-agent-contracts/src/page-context.ts#L143-L151
  • internal-packages/dashboard-agent-contracts/src/contracts.test.ts#L110-L126
  • apps/webapp/vitest.config.ts#L27-L27

Source: Coding guidelines

Comment on lines +569 to +572
queuedAt: run.queuedAt ?? undefined,
// Mirrors dashboardAgentWatchRunChecks.describeRunWait: a resumed/retried/paused run's
// queuedAt is a leftover from an earlier enqueue, not this attempt's wait.
queueWaitReliable: run.queuedAt !== null && !STALE_QUEUED_AT_STATUSES.has(run.status),

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.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🔎 Supported by static analysis

🏁 Script executed:

#!/bin/bash
# Locate the run-retrieve response schema/type and check for the new fields.
fd -t f -e ts . packages/core/src | xargs rg -n --type=ts -C4 '\bRetrieveRunResponse\b|\bqueueWaitReliable\b|\bqueuedAt\b' | head -100

Repository: triggerdotdev/trigger.dev

Length of output: 6684


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- applicable repository conventions ---'
find /tmp/coderabbit-repo-knowledge/triggerdotdev-trigger-dev-0bdd0019 -type f -name '*.md' -print \
  | while read -r f; do
    case "$f" in
      */apps-webapp/*|*/packages-core/*) head -80 "$f";;
    esac
  done
printf '%s\n' '--- RetrieveRun schemas and shared fields ---'
sed -n '1240,1345p' packages/core/src/v3/schemas/api.ts
sed -n '1535,1590p' packages/core/src/v3/schemas/api.ts
printf '%s\n' '--- queueWaitReliable declarations/usages ---'
rg -n -C3 --glob '*.{ts,tsx}' '\bqueueWaitReliable\b' apps/webapp packages/core

Repository: triggerdotdev/trigger.dev

Length of output: 9990


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- presenter payload construction ---'
sed -n '500,590p' apps/webapp/app/presenters/v3/ApiRetrieveRunPresenter.server.ts
rg -n -C8 'createCommonRunStructure|relatedRuns' apps/webapp/app/presenters/v3/ApiRetrieveRunPresenter.server.ts
printf '%s\n' '--- zodfetch binding and Zod version ---'
rg -n -C5 'function zodfetch|const zodfetch|export .*zodfetch|zodfetch' packages/core/src/v3 packages/core/package.json package.json
rg -n '"zod"|zod@' package.json packages/core/package.json pnpm-lock.yaml yarn.lock package-lock.json 2>/dev/null | head -20

Repository: triggerdotdev/trigger.dev

Length of output: 50381


Add queuedAt and queueWaitReliable to RetrieveRunCommandFields.

createCommonRunStructure returns both fields for the main run and relatedRuns. RetrieveRunResponse and RelatedRunDetails declare neither field. ApiClient.retrieveRun parses responses with RetrieveRunResponse; Zod strips undeclared keys, so SDK consumers also lack both fields in the inferred types.

@@ -1,15 +1,93 @@
import { formatTriggerUri } from "@internal/dashboard-agent-contracts";
import { assertExhaustive } from "@trigger.dev/core";

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Import assertExhaustive from a @trigger.dev/core subpath.

This file imports from the root @trigger.dev/core path. Use the subpath export that owns the symbol.

As per coding guidelines: "Use subpath exports from @trigger.dev/core package instead of importing from the root @trigger.dev/core path".

Source: Coding guidelines

ctx,
client: createApiClient(ctx),
renderInvestigations: (() => []) as any,
spanLedger: { recordTraceSpans: () => {} },

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Replace the no-op span-ledger test doubles.

Each new spanLedger: { recordTraceSpans: () => {} } fixture is a mock. Use a real SourceReadLedger fixture instead.

  • internal-packages/dashboard-agent/src/tool-api-branch.test.ts#L86-L86: pass a real source-read ledger.
  • internal-packages/dashboard-agent/src/tool-api-paths.test.ts#L35-L35: pass a real source-read ledger.
  • internal-packages/dashboard-agent/src/tool-api-transport.test.ts#L25-L25: pass a real source-read ledger.
  • internal-packages/dashboard-agent/src/tool-query-retry-cap.test.ts#L24-L24: pass a real source-read ledger.
  • internal-packages/dashboard-agent/src/tool-queue.test.ts#L182-L182: pass a real source-read ledger.
  • internal-packages/dashboard-agent/src/tool-queue.test.ts#L248-L248: pass a real source-read ledger.
  • internal-packages/dashboard-agent/src/tool-queue.test.ts#L324-L324: pass a real source-read ledger.

As per coding guidelines: “Never mock anything - use testcontainers instead.”

📍 Affects 5 files
  • internal-packages/dashboard-agent/src/tool-api-branch.test.ts#L86-L86 (this comment)
  • internal-packages/dashboard-agent/src/tool-api-paths.test.ts#L35-L35
  • internal-packages/dashboard-agent/src/tool-api-transport.test.ts#L25-L25
  • internal-packages/dashboard-agent/src/tool-query-retry-cap.test.ts#L24-L24
  • internal-packages/dashboard-agent/src/tool-queue.test.ts#L182-L182
  • internal-packages/dashboard-agent/src/tool-queue.test.ts#L248-L248
  • internal-packages/dashboard-agent/src/tool-queue.test.ts#L324-L324

Source: Coding guidelines

Comment on lines +293 to +310
function stubFetch(liveRow: Record<string, unknown>) {
vi.stubGlobal(
"fetch",
vi.fn(async (input: any) => {
const url = typeof input === "string" ? input : input.url;
if (url.endsWith("/jwt")) {
return new Response(JSON.stringify({ token: "env-jwt" }), { status: 200 });
}
if (url.includes("/metrics")) {
return new Response(JSON.stringify({ peakQueued: 4800, startedCount: 12 }), {
status: 200,
});
}
return new Response(JSON.stringify({ type: "custom", paused: false, ...liveRow }), {
status: 200,
});
})
);

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.

📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Replace the mocked fetch transport.

The added vi.stubGlobal and vi.fn calls mock the JWT and queue API responses. Use a Testcontainers-backed service for these new queue integration tests.

As per coding guidelines: “Never mock anything - use testcontainers instead.”

Source: Coding guidelines

Comment on lines +21 to +27
function fakeRepoTools(path: string): ToolSet {
return {
read_file: {
execute: async () => ({ path, content: "..." }),
},
} as unknown as ToolSet;
}

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.

📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

🔎 Supported by static analysis

🏁 Script executed:

#!/bin/bash
set -eu

echo '--- applicable convention files ---'
find /tmp/coderabbit-repo-knowledge/triggerdotdev-trigger-dev-0bdd0019 -type f -name '*.md' -print | sort
echo '--- convention excerpts for dashboard-agent/tests ---'
for f in $(find /tmp/coderabbit-repo-knowledge/triggerdotdev-trigger-dev-0bdd0019 -type f -name '*.md' | sort); do
  if grep -qEi 'mock|stub|fake|testcontainer|dashboard-agent|test' "$f"; then
    echo "### $f"
    cat "$f"
  fi
done

echo '--- changed test sites ---'
for spec in \
  internal-packages/dashboard-agent/src/tool-source-ledger.test.ts \
  internal-packages/dashboard-agent/src/tool-evidence.test.ts \
  internal-packages/dashboard-agent/src/dashboard-agent.test.ts \
  internal-packages/dashboard-agent/src/tool-ask-support.test.ts
do
  echo "### $spec"
  wc -l "$spec"
  case "$spec" in
    *tool-source-ledger.test.ts) sed -n '1,105p' "$spec" ;;
    *tool-evidence.test.ts) sed -n '1,45p' "$spec" ;;
    *dashboard-agent.test.ts) sed -n '1365,1430p' "$spec" ;;
    *tool-ask-support.test.ts) sed -n '1,40p' "$spec" ;;
  esac
done

echo '--- nearby test infrastructure and direct definitions ---'
rg -n --glob '*.{ts,tsx,js,jsx}' \
  'function (fakeRepoTools|fakeReads|stubFetch)|const (fetchMock|fetchStub)|stubFetch|recordTraceSpans|SourceReadLookup|ToolSet|vi\.(fn|stubGlobal|mock)|testcontainers|GenericContainer|Testcontainers' \
  internal-packages/dashboard-agent
git ls-files '*test*' '*container*' | head -80

Repository: triggerdotdev/trigger.dev

Length of output: 50381


🏁 Script executed:

#!/bin/bash
set -eu

echo '--- source-read ledger contract and implementation ---'
sed -n '1,180p' internal-packages/dashboard-agent/src/tool-source-ledger.ts

echo '--- repository tool construction and read tool contract ---'
sed -n '1,80p' internal-packages/dashboard-agent/src/repo-tools.ts
sed -n '180,255p' internal-packages/dashboard-agent/src/repo-tools.ts

echo '--- API tool contract and span-ledger call site ---'
sed -n '185,320p' internal-packages/dashboard-agent/src/tool-api.ts

echo '--- ask-support test remainder ---'
sed -n '1,90p' internal-packages/dashboard-agent/src/tool-ask-support.test.ts

echo '--- dashboard-agent local fetch stub definition and cited test ---'
sed -n '1385,1435p' internal-packages/dashboard-agent/src/dashboard-agent.test.ts
sed -n '1970,2015p' internal-packages/dashboard-agent/src/dashboard-agent.test.ts

echo '--- source-read ledger tests remainder ---'
sed -n '90,125p' internal-packages/dashboard-agent/src/tool-source-ledger.test.ts

echo '--- testcontainers patterns in this package ---'
sed -n '1,80p' internal-packages/dashboard-agent/src/maintenance.test.ts
sed -n '1,70p' internal-packages/dashboard-agent/src/investigation-sweep.test.ts

Repository: triggerdotdev/trigger.dev

Length of output: 31263


🏁 Script executed:

#!/bin/bash
set -eu

echo '--- API client fetch binding ---'
sed -n '1,220p' internal-packages/dashboard-agent/src/tool-api-client.ts

echo '--- ask_support implementation ---'
rg -n -A55 -B15 'ask_support|SUPPORT_ASK_URL|SUPPORT_ASK_SECRET' internal-packages/dashboard-agent/src/tool-api.ts

echo '--- dashboard tool assembly and ledger binding ---'
sed -n '1,80p' internal-packages/dashboard-agent/src/tools.ts
rg -n -A45 -B15 'createSourceReadLedger|withReadTracking|buildRepoTools|buildApiTools' internal-packages/dashboard-agent/src/agent-runtime.ts internal-packages/dashboard-agent/src/tools.ts

Repository: triggerdotdev/trigger.dev

Length of output: 19580


Replace the test doubles with real collaborators.

The repository rule for *.test.ts prohibits mocks and requires Testcontainers. Use concrete collaborators for fakeRepoTools, fakeReads, and the no-op spanLedger. Replace both vi.stubGlobal("fetch", ...) implementations with a Testcontainers-backed HTTP endpoint so these tests exercise the production paths.

📍 Affects 4 files
  • internal-packages/dashboard-agent/src/tool-source-ledger.test.ts#L21-L27 (this comment)
  • internal-packages/dashboard-agent/src/tool-source-ledger.test.ts#L77-L81
  • internal-packages/dashboard-agent/src/tool-evidence.test.ts#L7-L15
  • internal-packages/dashboard-agent/src/dashboard-agent.test.ts#L1400-L1406
  • internal-packages/dashboard-agent/src/tool-ask-support.test.ts#L18-L18

Source: Coding guidelines

Comment on lines +5697 to +5714
collect(baseQueueKey, '')

local variants = redis.call('ZRANGE', ckIndexKey, 0, -1)
for _, v in ipairs(variants) do
collect(keyPrefix .. v, v)
end

local baseDequeued = redis.call('SCARD', baseQueueKey .. ':currentDequeued')
local ckRunning = tonumber(redis.call('GET', runningCounterKey) or '0') or 0

return {
admittedCount,
dequeuedCount,
baseDequeued + ckRunning,
orphanCount,
truncated,
holders,
}

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.

🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win

Cap the CK variant scan, not only the holder output.

ZRANGE ckIndexKey 0 -1 returns every concurrency-key variant, and collect then issues two SMEMBERS calls per variant. maxHolders bounds only the returned list, so a base queue with many concurrency keys makes this script read every variant set inside one blocking Redis invocation. Redis executes scripts single-threaded, so the whole run-queue instance stalls for the duration. concurrencyKeyBreakdown already bounds its variant fan-out to a caller limit for this reason.

The cost is request-driven: QueueRetrievePresenter.#slotHolders calls slotHoldersOfQueue on every queue-retrieve request (see apps/webapp/app/presenters/v3/QueueRetrievePresenter.server.ts Line 245), so a single hot CK queue is enough to trigger it.

Bound the variant scan and report the remainder, so the payload stays honest about incompleteness.

⚡ Sketch: bound the scan and report skipped variants
 local keyPrefix = ARGV[1]
 local maxHolders = tonumber(ARGV[2])
+local maxVariants = tonumber(ARGV[3])
@@
-local variants = redis.call('ZRANGE', ckIndexKey, 0, -1)
-for _, v in ipairs(variants) do
-  collect(keyPrefix .. v, v)
-end
+local totalVariants = redis.call('ZCARD', ckIndexKey)
+local variants = redis.call('ZRANGE', ckIndexKey, 0, maxVariants - 1)
+for _, v in ipairs(variants) do
+  collect(keyPrefix .. v, v)
+end
+local skippedVariants = math.max(0, totalVariants - `#variants`)

Return skippedVariants on the reply, surface it on QueueSlotHolders, and treat a non-zero value as another reason the holder list is incomplete.

Comment on lines +606 to +624
const errorJson = JSON.stringify({
data: {
type: "Error",
message: "uat recurred fixture error",
stack: "Error: uat recurred fixture error\n at uatFixture (uat.ts:1:1)",
},
}).replace(/'/g, "''");

console.log("\nS10: Postgres side done. ClickHouse errors_v1 is a materialized view over");
console.log("task_runs_v2 - run this manually to make the error 'recur' after resolvedAt:\n");
console.log(
`clickhouse-client --query "INSERT INTO trigger_dev.task_runs_v2 ` +
`(environment_id, organization_id, project_id, run_id, friendly_id, environment_type, ` +
`engine, status, task_identifier, queue, task_version, error, created_at, updated_at, _version) ` +
`VALUES ('${ctx.devEnv.id}', '${ctx.orgId}', '${ctx.projectId}', 'uat-recurred-run', ` +
`'run_uatrecurred', 'DEVELOPMENT', 'V2', 'COMPLETED_WITH_ERRORS', '${taskIdentifier}', ` +
`'uat-recurred-task', 'uat', '${errorJson}', '${formatChDateTime(lastSeen)}', ` +
`'${formatChDateTime(lastSeen)}', ${version})"\n`
);

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Fix the shell quoting in the printed ClickHouse command.

errorJson comes from JSON.stringify, so it contains double quotes. The printed command wraps the query in double quotes (--query "..."). A copy-paste of that command ends the quoted string early and the shell fails or runs a truncated query. Escaping only single quotes is not sufficient here.

Wrap the query in single quotes instead. The SQL-level '' escaping already prevents single quotes from appearing in errorJson.

🐛 Proposed fix for the printed command
   console.log(
-    `clickhouse-client --query "INSERT INTO trigger_dev.task_runs_v2 ` +
+    `clickhouse-client --query 'INSERT INTO trigger_dev.task_runs_v2 ` +
       `(environment_id, organization_id, project_id, run_id, friendly_id, environment_type, ` +
       `engine, status, task_identifier, queue, task_version, error, created_at, updated_at, _version) ` +
       `VALUES ('${ctx.devEnv.id}', '${ctx.orgId}', '${ctx.projectId}', 'uat-recurred-run', ` +
       `'run_uatrecurred', 'DEVELOPMENT', 'V2', 'COMPLETED_WITH_ERRORS', '${taskIdentifier}', ` +
       `'uat-recurred-task', 'uat', '${errorJson}', '${formatChDateTime(lastSeen)}', ` +
-      `'${formatChDateTime(lastSeen)}', ${version})"\n`
+      `'${formatChDateTime(lastSeen)}', ${version})'\n`
   );

Note that the SQL string literals inside the query use single quotes too, so a single-quoted shell string also needs those inner quotes handled. A robust alternative is to pipe the query on stdin:

console.log("Save the statement below to /tmp/uat-recurred.sql, then run:");
console.log("  clickhouse-client --queries-file /tmp/uat-recurred.sql\n");
console.log(query);

@devin-ai-integration devin-ai-integration 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.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Open in Devin Review

DEVELOPMENT envs are per-user; without --user the script picked the
project's first dev env, seeding data into the wrong tester's env.
clean now sweeps every env in the project regardless of --user.

@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 platform limitations.

⚠️ Outside diff range comments (1)
scripts/seed-dashboard-agent-uat.ts (1)

141-188: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Add required @crumbs markers to the new fixture lifecycle.

Add // @Crumbs markers or `// `#region` `@crumbs blocks around project resolution, target selection, fixture seeding, and cleanup. This script mutates Postgres and Redis state. Crumbs make incorrect target selection and incomplete cleanup easier to diagnose during branch development.

As per coding guidelines, “Add crumbs as you write code — not just when debugging.”

Source: Coding guidelines


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 904a8509-2e6d-4567-a12e-43bf07fdb6b0

📥 Commits

Reviewing files that changed from the base of the PR and between 10c3d2b and 55f0211.

📒 Files selected for processing (2)
  • apps/webapp/app/components/code/StreamdownRenderer.tsx
  • scripts/seed-dashboard-agent-uat.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/webapp/app/components/code/StreamdownRenderer.tsx

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

📜 Review details
⏰ Context from checks skipped due to timeout. (37)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (8, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (20, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (23, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (21, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (14, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (19, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (24, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (22, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (12, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (17, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (6, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (18, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (13, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (16, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (15, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (5, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (11, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (7, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (3, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (10, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (2, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (9, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (4, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (1, 24)
  • GitHub Check: fk-cascade-guard / fk-cascade-guard
  • GitHub Check: internal / 🧪 Unit Tests: Internal
  • GitHub Check: packages / 🧪 Unit Tests: Packages (2, 3)
  • GitHub Check: e2e-webapp / 🧪 E2E Tests: Webapp (2, 2)
  • GitHub Check: obsmap / 🧪 Unit Tests: Observability Map
  • GitHub Check: e2e-webapp / 🧪 E2E Tests: Webapp (1, 2)
  • GitHub Check: packages / 🧪 Unit Tests: Packages (3, 3)
  • GitHub Check: packages / 🧪 Unit Tests: Packages (1, 3)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: runops-guard / runops-guard
  • GitHub Check: code-quality / code-quality
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: 🛡️ E2E Auth Tests (full)
🧰 Additional context used
📓 Path-based instructions (5)
**Prefer static imports over dynamic imports.** Only use dynamic `import()` when:

📄 CodeRabbit inference engine (AGENTS.md)

Files:

  • scripts/seed-dashboard-agent-uat.ts
Add crumbs as you write code — not just when debugging. Mark lines with

📄 CodeRabbit inference engine (AGENTS.md)

Files:

  • scripts/seed-dashboard-agent-uat.ts
Use function declarations instead of default exports

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Files:

  • scripts/seed-dashboard-agent-uat.ts
Use types over interfaces for TypeScript

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Files:

  • scripts/seed-dashboard-agent-uat.ts
When creating or editing OTEL metrics (counters, histograms, gauges), ensure metric attributes have low cardinality by using only enums, booleans, bounded error codes, or bounded shard IDs

📄 CodeRabbit inference engine (.cursor/rules/otel-metrics.mdc)

Files:

  • scripts/seed-dashboard-agent-uat.ts
🧠 Learnings (1)
📚 Learning: 2026-06-04T18:16:35.386Z
Learnt from: nicktrn
Repo: triggerdotdev/trigger.dev PR: 3836
File: apps/supervisor/src/backpressure/backpressureMonitor.ts:3-5
Timestamp: 2026-06-04T18:16:35.386Z
Learning: When reviewing TypeScript in this repo, apply the rule “prefer type aliases over interfaces” only to data/object shapes and union/intersection type modeling. If an interface is being used as a behavioral contract for collaborators to implement (e.g., method-shape interfaces that define required behavior, such as `BackpressureLogger` / `BackpressureSignalSource` in `apps/supervisor/src/backpressure/backpressureMonitor.ts`), keep it as an `interface` and do not flag it as a type-alias-vs-interface violation.

Applied to files:

  • scripts/seed-dashboard-agent-uat.ts

…d script

Confirmed QueueRetrievePresenter's type=custom lookup matches TaskQueue.name
exactly (no prefix, unlike type=task). Seeded queue names already satisfy
this; the earlier 404 was the wrong-env queue, now fixed. Documents the
contract so future scenarios don't regress it.
Add client-side deadlines for the first stream event (45s) and a
single pending tool call (120s), surfacing the existing turn-error
callout instead of hanging forever. Wrap the chat-creation head-start
and session-start awaits with a 20s timeout so a stuck trigger fails
the request instead of hanging it.
Gate the tool-pending deadline by turn status so a dangling tool part
on an idle chat never arms. Reset both deadlines' keys on retry and
dismiss so a re-fired condition re-arms. Reword the route comment for
the timeout path. Add wiring tests for both fixes.
A retry can resend under status "submitted" again, the same value the
failed turn already left it in, so the first-event effect never re-ran.
Bump an attempt counter in retry/dismissError to force it. Reword the
deadline tests to state they prove the extracted predicate and reset,
not full component wiring.
Only retry bumps the attempt counter; dismiss just stops the callout.
Drop the inert eslint-disable, keep the explanatory comment.
…nment

Add a per-call project/environment override on list_runs, get_run,
get_run_trace, get_error, and get_queue, so a not-found lookup can be
retried elsewhere in the org. The env-JWT exchange targets and caches
per override; the default (no-override) path is unchanged. System
prompt gains the grounding rule to retry and name where it was found.
…r scoping

Resolve the list_projects prompt contradiction, drop preview from the
environment override (branches aren't targetable that way), and make
envUnavailableError name the overridden project/environment instead of
"the current environment". Add a branch-retention test for the
default (no-override) path.
devin-ai-integration[bot]

This comment was marked as resolved.

@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: 4

🧹 Nitpick comments (1)
apps/webapp/app/components/dashboard-agent/DashboardAgentChat.tsx (1)

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

Remove the unnecessary useMemo.

effectiveError is a small derived value passed directly to DashboardAgentMessages. It is not a context value, an expensive computation, or a stable dependency reference.

Source: Coding guidelines


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3276f8a7-c01a-494c-a043-87c6cdf4f8cc

📥 Commits

Reviewing files that changed from the base of the PR and between 64d84db and 62c1940.

⛔ Files ignored due to path filters (1)
  • internal-packages/dashboard-agent/src/__snapshots__/prompt-prefix.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (11)
  • .server-changes/dashboard-agent-bounded-wait-errors.md
  • apps/webapp/app/components/dashboard-agent/DashboardAgentChat.tsx
  • apps/webapp/app/components/dashboard-agent/turn-deadlines.test.ts
  • apps/webapp/app/components/dashboard-agent/turn-deadlines.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.ts
  • apps/webapp/app/utils/withTimeout.server.test.ts
  • apps/webapp/app/utils/withTimeout.server.ts
  • internal-packages/dashboard-agent/src/tool-api-client.ts
  • internal-packages/dashboard-agent/src/tool-api-cross-project.test.ts
  • internal-packages/dashboard-agent/src/tool-api.ts
  • internal-packages/dashboard-agent/src/tool-schemas.ts

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

📜 Review details
⏰ Context from checks skipped due to timeout. (22)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (20, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (7, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (19, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (18, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (17, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (12, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (21, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (16, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (15, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (14, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (11, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (8, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (13, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (9, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (5, 24)
  • GitHub Check: packages / 🧪 Unit Tests: Packages (1, 3)
  • GitHub Check: internal / 🧪 Unit Tests: Internal
  • GitHub Check: packages / 🧪 Unit Tests: Packages (3, 3)
  • GitHub Check: packages / 🧪 Unit Tests: Packages (2, 3)
  • GitHub Check: e2e-webapp / 🧪 E2E Tests: Webapp (1, 2)
  • GitHub Check: e2e-webapp / 🧪 E2E Tests: Webapp (2, 2)
  • GitHub Check: Analyze (javascript-typescript)
🧰 Additional context used
📓 Path-based instructions (14)
Use Remix flat-file route conventions with dot-separated segments; for example, `api.v1.tasks.$taskId.trigger.ts` maps to `/api/v1/tasks/:taskId/trigger`.

📄 CodeRabbit inference engine (apps/webapp/CLAUDE.md)

Files:

  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.ts
Never use `request.signal` to detect client disconnects. Use `getRequestAbortSignal()` from `app/services/httpAsyncStorage.server.ts`, which is wired to Express response close events.

📄 CodeRabbit inference engine (apps/webapp/CLAUDE.md)

Files:

  • apps/webapp/app/utils/withTimeout.server.ts
  • apps/webapp/app/components/dashboard-agent/turn-deadlines.test.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.ts
  • apps/webapp/app/utils/withTimeout.server.test.ts
  • apps/webapp/app/components/dashboard-agent/turn-deadlines.ts
We use vitest exclusively. **Never mock anything** - use testcontainers instead.

📄 CodeRabbit inference engine (AGENTS.md)

Files:

  • apps/webapp/app/components/dashboard-agent/turn-deadlines.test.ts
  • apps/webapp/app/utils/withTimeout.server.test.ts
  • internal-packages/dashboard-agent/src/tool-api-cross-project.test.ts
Test files must not import `app/env.server.ts`; pass configuration as options instead.

📄 CodeRabbit inference engine (apps/webapp/CLAUDE.md)

Files:

  • apps/webapp/app/components/dashboard-agent/turn-deadlines.test.ts
  • apps/webapp/app/utils/withTimeout.server.test.ts
For dashboard changes, visually verify the running Remix app with Chrome DevTools MCP, using snapshots, screenshots, interaction, and console-message checks as appropriate.

📄 CodeRabbit inference engine (apps/webapp/CLAUDE.md)

Files:

  • apps/webapp/app/utils/withTimeout.server.ts
  • apps/webapp/app/components/dashboard-agent/turn-deadlines.test.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.ts
  • apps/webapp/app/utils/withTimeout.server.test.ts
  • apps/webapp/app/components/dashboard-agent/turn-deadlines.ts
  • apps/webapp/app/components/dashboard-agent/DashboardAgentChat.tsx
**Prefer static imports over dynamic imports.** Only use dynamic `import()` when:

📄 CodeRabbit inference engine (AGENTS.md)

Files:

  • apps/webapp/app/utils/withTimeout.server.ts
  • internal-packages/dashboard-agent/src/tool-api-client.ts
  • apps/webapp/app/components/dashboard-agent/turn-deadlines.test.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.ts
  • apps/webapp/app/utils/withTimeout.server.test.ts
  • apps/webapp/app/components/dashboard-agent/turn-deadlines.ts
  • internal-packages/dashboard-agent/src/tool-api-cross-project.test.ts
  • internal-packages/dashboard-agent/src/tool-api.ts
  • apps/webapp/app/components/dashboard-agent/DashboardAgentChat.tsx
  • internal-packages/dashboard-agent/src/tool-schemas.ts
Add crumbs as you write code — not just when debugging. Mark lines with

📄 CodeRabbit inference engine (AGENTS.md)

Files:

  • apps/webapp/app/utils/withTimeout.server.ts
  • internal-packages/dashboard-agent/src/tool-api-client.ts
  • apps/webapp/app/components/dashboard-agent/turn-deadlines.test.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.ts
  • apps/webapp/app/utils/withTimeout.server.test.ts
  • apps/webapp/app/components/dashboard-agent/turn-deadlines.ts
  • internal-packages/dashboard-agent/src/tool-api-cross-project.test.ts
  • internal-packages/dashboard-agent/src/tool-api.ts
  • apps/webapp/app/components/dashboard-agent/DashboardAgentChat.tsx
  • internal-packages/dashboard-agent/src/tool-schemas.ts
Use zod for validation in packages/core and apps/webapp

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Files:

  • apps/webapp/app/utils/withTimeout.server.ts
  • apps/webapp/app/components/dashboard-agent/turn-deadlines.test.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.ts
  • apps/webapp/app/utils/withTimeout.server.test.ts
  • apps/webapp/app/components/dashboard-agent/turn-deadlines.ts
  • apps/webapp/app/components/dashboard-agent/DashboardAgentChat.tsx
Do not import `env.server.ts` directly or indirectly into test files; instead pass environment-dependent values through options/parameters to make code testable

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Files:

  • apps/webapp/app/components/dashboard-agent/turn-deadlines.test.ts
  • apps/webapp/app/utils/withTimeout.server.test.ts
Access environment variables through the `env` export of `env.server.ts` instead of directly accessing `process.env`

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Files:

  • apps/webapp/app/utils/withTimeout.server.ts
  • apps/webapp/app/components/dashboard-agent/turn-deadlines.test.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.ts
  • apps/webapp/app/utils/withTimeout.server.test.ts
  • apps/webapp/app/components/dashboard-agent/turn-deadlines.ts
  • apps/webapp/app/components/dashboard-agent/DashboardAgentChat.tsx
Use vitest for all tests in the Trigger.dev repository

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Files:

  • apps/webapp/app/components/dashboard-agent/turn-deadlines.test.ts
  • apps/webapp/app/utils/withTimeout.server.test.ts
  • internal-packages/dashboard-agent/src/tool-api-cross-project.test.ts
Use function declarations instead of default exports

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Files:

  • apps/webapp/app/utils/withTimeout.server.ts
  • internal-packages/dashboard-agent/src/tool-api-client.ts
  • apps/webapp/app/components/dashboard-agent/turn-deadlines.test.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.ts
  • apps/webapp/app/utils/withTimeout.server.test.ts
  • apps/webapp/app/components/dashboard-agent/turn-deadlines.ts
  • internal-packages/dashboard-agent/src/tool-api-cross-project.test.ts
  • internal-packages/dashboard-agent/src/tool-api.ts
  • apps/webapp/app/components/dashboard-agent/DashboardAgentChat.tsx
  • internal-packages/dashboard-agent/src/tool-schemas.ts
Use types over interfaces for TypeScript

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Files:

  • apps/webapp/app/utils/withTimeout.server.ts
  • internal-packages/dashboard-agent/src/tool-api-client.ts
  • apps/webapp/app/components/dashboard-agent/turn-deadlines.test.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.ts
  • apps/webapp/app/utils/withTimeout.server.test.ts
  • apps/webapp/app/components/dashboard-agent/turn-deadlines.ts
  • internal-packages/dashboard-agent/src/tool-api-cross-project.test.ts
  • internal-packages/dashboard-agent/src/tool-api.ts
  • apps/webapp/app/components/dashboard-agent/DashboardAgentChat.tsx
  • internal-packages/dashboard-agent/src/tool-schemas.ts
When creating or editing OTEL metrics (counters, histograms, gauges), ensure metric attributes have low cardinality by using only enums, booleans, bounded error codes, or bounded shard IDs

📄 CodeRabbit inference engine (.cursor/rules/otel-metrics.mdc)

Files:

  • apps/webapp/app/utils/withTimeout.server.ts
  • internal-packages/dashboard-agent/src/tool-api-client.ts
  • apps/webapp/app/components/dashboard-agent/turn-deadlines.test.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboard-agent.ts
  • apps/webapp/app/utils/withTimeout.server.test.ts
  • apps/webapp/app/components/dashboard-agent/turn-deadlines.ts
  • internal-packages/dashboard-agent/src/tool-api-cross-project.test.ts
  • internal-packages/dashboard-agent/src/tool-api.ts
  • internal-packages/dashboard-agent/src/tool-schemas.ts
🧠 Learnings (4)
📚 Learning: 2026-07-26T13:14:02.968Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 4378
File: .server-changes/realtime-run-reads-from-primary.md:0-0
Timestamp: 2026-07-26T13:14:02.968Z
Learning: For files in the .server-changes directory, the body text is published verbatim as dashboard-facing user release notes. Write entries in terms of user-visible behavior (what users can do/see), and avoid implementation-oriented details such as environment-variable names, internal mechanisms, or configuration knobs. If you need to include operational/configuration specifics, put those details in the PR description instead of the .server-changes entry.

Applied to files:

  • .server-changes/dashboard-agent-bounded-wait-errors.md
📚 Learning: 2026-06-04T18:16:35.386Z
Learnt from: nicktrn
Repo: triggerdotdev/trigger.dev PR: 3836
File: apps/supervisor/src/backpressure/backpressureMonitor.ts:3-5
Timestamp: 2026-06-04T18:16:35.386Z
Learning: When reviewing TypeScript in this repo, apply the rule “prefer type aliases over interfaces” only to data/object shapes and union/intersection type modeling. If an interface is being used as a behavioral contract for collaborators to implement (e.g., method-shape interfaces that define required behavior, such as `BackpressureLogger` / `BackpressureSignalSource` in `apps/supervisor/src/backpressure/backpressureMonitor.ts`), keep it as an `interface` and do not flag it as a type-alias-vs-interface violation.

Applied to files:

  • internal-packages/dashboard-agent/src/tool-api-client.ts
  • apps/webapp/app/components/dashboard-agent/turn-deadlines.ts
📚 Learning: 2026-06-16T09:19:47.637Z
Learnt from: d-cs
Repo: triggerdotdev/trigger.dev PR: 3960
File: apps/webapp/test/prismaInfrastructureErrorCapture.test.ts:0-0
Timestamp: 2026-06-16T09:19:47.637Z
Learning: In this repo’s Vitest setup, `vitest.config.ts` uses `globals: true`, so identifiers like `vi`, `describe`, `it`, and `expect` are available as globals in Vitest test files. During code review, do not flag missing `vi`/`describe`/`it`/`expect` imports as a runtime error or correctness issue when they’re used in `*.test.ts/tsx` or `*.spec.ts/tsx` files. Explicit imports are still preferred for consistency, but they’re not required for runtime behavior.

Applied to files:

  • internal-packages/dashboard-agent/src/tool-api-cross-project.test.ts
📚 Learning: 2026-05-18T14:40:02.173Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 3658
File: packages/core/src/v3/realtimeStreams/manager.test.ts:1-147
Timestamp: 2026-05-18T14:40:02.173Z
Learning: In the triggerdotdev/trigger.dev repo, the policy “Never mock anything — use testcontainers instead” should only be enforced for integration tests that interact with real external services (e.g., Redis, Postgres) via actual infrastructure. For unit tests that exercise pure in-memory logic (e.g., cache semantics) it is OK to stub collaborators such as `ApiClient` using Vitest (`vi.fn()`) to assert call counts or control behavior. Do not flag `vi.fn()`-based `ApiClient` stubs in unit tests as violations of the testcontainers policy.

Applied to files:

  • internal-packages/dashboard-agent/src/tool-api-cross-project.test.ts

Comment on lines +263 to +264
toolPendingDeadline.sync(activeToolPendingKey(status, inFlightToolName(messages)));
}, [messages, status, toolPendingDeadline]);

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🔎 Supported by static analysis

🏁 Script executed:

#!/bin/bash
printf '%s\n' '--- changed component ---'
sed -n '1,330p' apps/webapp/app/components/dashboard-agent/DashboardAgentChat.tsx
printf '%s\n' '--- direct dependency ---'
sed -n '70,125p' apps/webapp/app/components/dashboard-agent/progress-line.ts
printf '%s\n' '--- related symbols ---'
rg -n -C 5 'activeToolPendingKey|toolPendingDeadline|inFlightToolName|function use.*Deadline|sync\(' apps/webapp/app/components/dashboard-agent

Repository: triggerdotdev/trigger.dev

Length of output: 50381


🏁 Script executed:

#!/bin/bash
printf '%s\n' '--- deadline implementation ---'
cat -n apps/webapp/app/components/dashboard-agent/turn-deadlines.ts
printf '%s\n' '--- progress definitions and tool states ---'
sed -n '1,115p' apps/webapp/app/components/dashboard-agent/progress-line.ts
printf '%s\n' '--- deadline tests around key behavior ---'
sed -n '45,100p' apps/webapp/app/components/dashboard-agent/turn-deadlines.test.ts

Repository: triggerdotdev/trigger.dev

Length of output: 9983


Use a per-invocation key for the tool deadline.

inFlightToolName(messages) returns only the tool name, and createKeyedDeadline.sync() ignores an unchanged key. Consecutive calls to the same tool can therefore reuse the previous timer and show an early or stale timeout. Include a stable tool-call identifier in the deadline key and add a regression test without an intermediate null key.

Comment on lines +25 to +29
beforeEach(() => {
vi.useFakeTimers();
});
afterEach(() => {
vi.useRealTimers();

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.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Remove fake timers from these tests.

vi.useFakeTimers() mocks the timer runtime. The test policy prohibits mocks. Use short real deadlines and real timer scheduling instead.

As per coding guidelines: “We use vitest exclusively. Never mock anything.”

Also applies to: 132-137

Source: Coding guidelines

Comment on lines +145 to +158
function getEnvJwt(refresh = false, target?: ApiTarget): Promise<EnvJwt> {
// An override drops the branch: it names another project/environment, which the
// current branch can't be assumed to apply to. A field left off the override still
// falls back to ctx's own value.
const ref = target?.projectRef ?? projectRef;
const env = target?.environmentName ?? environmentName;
const branch = target ? undefined : environmentBranch;
if (!hasAuth || !ref || !env) return Promise.resolve(MISSING_ENV);
const key = `${ref}/${env}/${branch ?? ""}`;
if (refresh) envJwts.delete(key);
let pending = envJwts.get(key);
if (!pending) {
// A failed exchange is not cached: a 403 or a 5xx would otherwise pin the whole turn.
pending = exchangeEnvJwt(
origin,
userActorToken!,
projectRef,
environmentName,
environmentBranch
).then((result) => {
pending = exchangeEnvJwt(origin, userActorToken!, ref, env, branch).then((result) => {

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.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Add @crumbs markers to the newly added paths.

Mark the cross-target resolution and forwarding logic, override-field behavior, deadline lifecycle, displayed deadline errors, startup timeout cleanup, and timeout settlement with // @crumbs`` or an approved @crumbs region.

📍 Affects 2 files
  • internal-packages/dashboard-agent/src/tool-api-client.ts#L145-L158 (this comment)
  • apps/webapp/app/components/dashboard-agent/turn-deadlines.ts#L58-L91

Source: Coding guidelines

Comment thread internal-packages/dashboard-agent/src/tool-schemas.ts Outdated

@devin-ai-integration devin-ai-integration 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.

Devin Review found 1 new potential issue.

Open in Devin Review

Comment on lines 148 to 154
createdAt: r.createdAt,
startedAt: r.startedAt,
finishedAt: r.finishedAt,
wait: computeRunWait(r),
durationMs: r.durationMs,
tags: r.tags,
})),

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.

🔍 Run wait measured differently between get_run and list_runs

computeRunWait measures from queuedAt only when queueWaitReliable === true. ApiRetrieveRunPresenter.createCommonRunStructure emits that field, but the list-runs payload does not, so curateRuns list items always fall back to measuredFrom: "created". The same run can therefore show a different wait label via list_runs than via get_run.

(Refers to this code)

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

The not-found fallback only checked siblings' same-name env, then
told the user to check the environment switcher for scopes the agent
can already read. Now it also sweeps the current project's other
environments and each sibling's matching one, and the final wording
names exactly what was checked instead of hedging.
The not-found rule could be satisfied by a past turn's sweep restated
as if done now. Require scopes named to be checked THIS turn, with a
past sweep cited as past. Trimmed verbose passages elsewhere in the
prompt and the shared project/environment describes to hold budget.
…ing line

The post-verdict close only banned list-form repeats of remediation/
checkNext, so a reworded restatement of the card's findings still
passed. Now it must contain only what the card doesn't. Also fixes
projectOverrideField's describe, broken by an earlier trim.
…e only

concluded/inconclusive instructions describe CARD content and were
read as contradicting the closing-line ban; prefix them "On the
card:". Also restores the antecedent sentence an earlier trim dropped.

@devin-ai-integration devin-ai-integration 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.

Devin Review found 3 new potential issues.

Open in Devin Review

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.

🔍 Bounded-wait retry can resend during a live turn

effectiveError in DashboardAgentChat.tsx surfaces a deadline error while the SDK status is still submitted/streaming and error is undefined. The retry callout then calls retry(), which can sendMessage/regenerate while the previous turn's stream is still open server-side. This is the intended bounded-wait behavior, but overlapping sends depend on how useChat handles a resend mid-turn; worth confirming it does not duplicate turns.

(Refers to this code)

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +691 to +724
public async slotHoldersOfQueue(
env: MinimalAuthenticatedEnvironment,
queue: string,
options?: { limit?: number }
): Promise<QueueSlotHolders> {
const limit = options?.limit ?? DEFAULT_SLOT_HOLDER_LIMIT;
const baseQueueKey = this.keys.queueKey(env, queue);

const [admittedCount, dequeuedCount, runningReported, orphanCount, truncated, rawHolders] =
await this.redis.slotHoldersOfQueue(
baseQueueKey,
this.keys.ckIndexKeyFromQueue(baseQueueKey),
this.keys.queueRunningCounterKey(env, queue),
this.options.redis.keyPrefix ?? "",
String(limit)
);

const holders = rawHolders.map(([runId, variant, phase]) => ({
runId,
concurrencyKey: variant ? (this.#concurrencyKeyFromQueue(variant) ?? null) : null,
phase: phase === "dequeued" ? ("dequeued" as const) : ("admitted" as const),
}));

return {
holders,
admittedCount,
dequeuedCount,
runningReported,
truncated: truncated === 1,
unlistedRunning: Math.max(0, runningReported - dequeuedCount),
consistency:
dequeuedCount === runningReported && orphanCount === 0 ? "consistent" : "mismatch",
};
}

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.

🔍 Queue retrieve enumerates every concurrency-key variant per call

slotHoldersOfQueue (index.ts) runs a Lua script doing ZRANGE ckIndexKey 0 -1 plus two SMEMBERS per backlogged concurrency-key variant, now invoked on every /api/v1/queues/:queue retrieve via QueueRetrievePresenter.#slotHolders. The holder list caps at 20, but the counts force full enumeration, so a queue with many concurrency-key variants triggers an O(N) blocking Lua on single-threaded Redis. Existing concurrencyKeyBreakdown uses a similar scan, so this may be acceptable, but it is worth confirming for high-cardinality CK queues.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread scripts/seed-dashboard-agent-uat.ts
…omaly

Diagnostic/causal questions always get the investigation card, even
when the verdict is healthy (concluded, severity info, no
remediation) — lookups/navigation/how-to never do. The card schema
already supports a healthy verdict without remediation, so no gap.
Trimmed other bullets to hold the budget.
…n collisions

Health questions route through get_report as the gather step, so the
ALWAYS-investigate rule no longer duplicates that procedure. concluded
now names the healthy-verdict case explicitly, plus an overclaim
guard. Trimmed several unrelated bullets to hold the prompt budget.

@devin-ai-integration devin-ai-integration 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.

Devin Review found 1 new potential issue.

Open in Devin Review

Comment on lines +377 to 411
await withTimeout(
startDashboardAgentHeadStart({
chatId,
messages: [firstMessage],
mode: repoSnapshot ? "code" : "assistant",
metadata: headStartMetadata,
}),
CHAT_CREATE_TIMEOUT_MS,
"Dashboard agent head start"
);
} else {
// Cold start: the client sends the first message through the `in` proxy, which
// injects the token.
// Same server-owned identity the head-start path injects; the `in` proxy adds the
// delegated token on the first turn.
await startDashboardAgentSession({
chatId,
clientData: {
...clientContext,
organizationId: project.organizationId,
userId,
projectId: project.id,
environmentId: runtimeEnv.id,
...environmentAddress,
},
});
await withTimeout(
startDashboardAgentSession({
chatId,
clientData: {
...clientContext,
organizationId: project.organizationId,
userId,
projectId: project.id,
environmentId: runtimeEnv.id,
...environmentAddress,
},
}),
CHAT_CREATE_TIMEOUT_MS,
"Dashboard agent session start"
);
}
} catch (error) {
// Both starts are one create-session-and-trigger round trip, so a rejection means no
// handover was dispatched and no message was sent: a session the call did create in
// spite of the error idles out having done nothing. The empty row is all there is to undo.
// Swallowed so the start's own error is what surfaces and gets logged.
// A rejection usually means nothing was dispatched, except `withTimeout`'s trigger
// can still land after the soft-delete below; the `in` proxy just treats it as missing.
await softDeleteChat(dashboardAgentDb, {

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.

🔍 Head-start timeout skips quota accounting for a message that may still send

When withTimeout around startDashboardAgentHeadStart fires, the chat is soft-deleted and the error rethrown before recordAgentMessageSent runs. The code comment notes the trigger can still land after the soft-delete, so a head-started first message can reach the agent while never counting against the org's message quota.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

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