feat: harden poll logic#52
Conversation
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
📝 WalkthroughWalkthroughAdds runtime guards that verify a ticket's Jira project key and AI column before starting workflows; unregisters or cancels runs when mismatches are detected. Normalizes and deduplicates discovered AI-column ticket keys during cron polling. Reconciliation and webhook flows now perform live issue-tracker verification (including 404 handling) before cancelling or cleaning runs. Changes
Sequence Diagram(s)sequenceDiagram
participant Caller
participant Dispatch as dispatchTicket
participant Jira as issueTracker.fetchTicket
participant Registry as runRegistry.unregister
participant Workflow as agentWorkflow.start
Caller->>Dispatch: dispatchTicket(ticketKey)
Dispatch->>Jira: fetchTicket(ticketKey)
Jira-->>Dispatch: ticket { identifier, trackerStatus, ... }
alt project key mismatch
Dispatch->>Registry: unregister(ticketKey) (best-effort)
Dispatch-->>Caller: { started: false, reason: "wrong_project_key" }
else trackerStatus mismatch
Dispatch->>Registry: unregister(ticketKey) (best-effort)
Dispatch-->>Caller: { started: false, reason: "not_in_ai_column" }
else proceed
Dispatch->>Workflow: start(...)
Workflow-->>Dispatch: started result
Dispatch-->>Caller: { started: true, ... }
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/lib/dispatch.ts`:
- Around line 7-9: Module-level access to env (EXPECTED_PROJECT_KEY,
EXPECTED_AI_STATUS) runs at import time and breaks tests; move the env
validation/trim/transform logic into a lazy initializer or inside dispatchTicket
so env is read only when the function is called (or create helper functions like
getExpectedProjectKey() and getExpectedAiStatus() that compute and cache the
values on first call). Update all references to EXPECTED_PROJECT_KEY and
EXPECTED_AI_STATUS to call those helpers (or compute inside dispatchTicket) so
tests can mock env before dispatch.js reads it.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: eafe7897-9ade-400e-9d8e-a9a726fa7257
📒 Files selected for processing (3)
src/lib/dispatch.test.tssrc/lib/dispatch.tssrc/routes/cron/poll.get.ts
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
src/routes/cron/poll.get.ts (1)
73-85: Canonicalize keys before deduping.
startsWith(expectedPrefix)is case-insensitive, butSetdedup is not.PROJ-123andproj-123both survive today, so this normalization step can still dispatch/reconcile the same ticket twice if mixed-case keys ever appear.♻️ Proposed change
function normalizeTicketKeys(ticketKeys: string[]): string[] { const expectedPrefix = `${env.JIRA_PROJECT_KEY.trim().toUpperCase()}-`; const unique = new Set<string>(); for (const rawKey of ticketKeys) { - const key = typeof rawKey === "string" ? rawKey.trim() : ""; + const key = typeof rawKey === "string" ? rawKey.trim().toUpperCase() : ""; if (!key) continue; - if (!key.toUpperCase().startsWith(expectedPrefix)) continue; + if (!key.startsWith(expectedPrefix)) continue; unique.add(key); } return [...unique]; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/routes/cron/poll.get.ts` around lines 73 - 85, In normalizeTicketKeys, canonicalize keys to a consistent case before deduping so mixed-case duplicates (e.g., "PROJ-123" vs "proj-123") collapse. Specifically, after trimming the rawKey produce a normalizedKey (e.g., key.toUpperCase()) and use that for the startsWith check against expectedPrefix and for adding into the unique Set (instead of adding the original key); return the array of these canonicalized keys so deduping is case-insensitive. Ensure the function still trims input and skips empty values; update uses of expectedPrefix, key, and unique within normalizeTicketKeys accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/lib/reconcile.ts`:
- Around line 69-99: verifyTicketLeftAiColumn currently only checks
trackerStatus and string-parses errors for "404", which can let tickets that
moved projects slip through and is fragile; update the flow so
verifyTicketLeftAiColumn uses the project key from the fetched ticket (e.g.,
ticket.projectKey or TicketContent.projectKey) and confirms both status !==
env.COLUMN_AI and projectKey === env.JIRA_PROJECT_KEY, and stop relying on
/\b404\b/.test(message) by changing the IssueTrackerAdapter.fetchTicket contract
to surface a typed NotFoundError or a typed result (or an error.code property)
and then detect that explicit type/property in verifyTicketLeftAiColumn (use
instanceof NotFoundError or err.code === 'NOT_FOUND') to return true for missing
tickets and log other errors as before.
In `@src/routes/webhooks/jira.post.ts`:
- Around line 47-59: The code currently cancels based solely on the webhook
payload; instead fetch the current ticket state from adapters.issueTracker
(e.g., call the issue fetch method for ticketKey) or call the existing
reconciliation validator before invoking cancelTrackedRun so you only cancel
when the live status is still not an AI column. Concretely: after computing
ticketStatus from extractTicketStatus and before calling
cancelTrackedRun(ticketKey, adapters.runRegistry), query adapters.issueTracker
for the current issue status (or call the reconciliation validator function used
elsewhere), re-evaluate with isAiColumnStatus, and only call cancelTrackedRun if
the live status confirms the ticket remains outside the AI column; update the
logged fields accordingly.
---
Nitpick comments:
In `@src/routes/cron/poll.get.ts`:
- Around line 73-85: In normalizeTicketKeys, canonicalize keys to a consistent
case before deduping so mixed-case duplicates (e.g., "PROJ-123" vs "proj-123")
collapse. Specifically, after trimming the rawKey produce a normalizedKey (e.g.,
key.toUpperCase()) and use that for the startsWith check against expectedPrefix
and for adding into the unique Set (instead of adding the original key); return
the array of these canonicalized keys so deduping is case-insensitive. Ensure
the function still trims input and skips empty values; update uses of
expectedPrefix, key, and unique within normalizeTicketKeys accordingly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 1c214b85-ff68-4679-9a2b-efa26a02a5b9
📒 Files selected for processing (5)
src/lib/dispatch.tssrc/lib/reconcile.test.tssrc/lib/reconcile.tssrc/routes/cron/poll.get.tssrc/routes/webhooks/jira.post.ts
✅ Files skipped from review due to trivial changes (1)
- src/lib/dispatch.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- src/lib/reconcile.test.ts
There was a problem hiding this comment.
🧹 Nitpick comments (2)
src/routes/webhooks/jira.post.ts (1)
211-217: Consider extracting shared project-key extraction logic.
extractProjectKeyFromIdentifierduplicates logic injira.ts:extractProjectKeyandreconcile.ts:resolveTicketProjectKey. While each has minor differences, consolidating to a shared utility would reduce maintenance burden.This is a minor refactor that could be deferred—the current implementations are correct and the slight variations (return type, input handling) may justify keeping them separate.
Also applies to: 108-121
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/routes/webhooks/jira.post.ts` around lines 211 - 217, Consolidate duplicate project-key extraction logic by creating a shared utility (e.g., extractProjectKey) that implements the canonical behavior: trim the input, return null for empty or missing dash or dash at position 0, and return the segment before the first dash upper-cased; then replace usages of extractProjectKeyFromIdentifier (in jira.post.ts), extractProjectKey (in jira.ts) and resolveTicketProjectKey (in reconcile.ts) to call the new shared function and update imports accordingly so all three call the single implementation with the same return type and input handling.src/adapters/issue-tracker/jira.test.ts (1)
53-64: Good test coverage for 404 handling.The test correctly verifies that a 404 response throws
IssueTrackerNotFoundError. Consider additionally asserting on the error'scodeproperty to ensure the duck-typed detection will work:✨ Optional: Assert error code property
const adapter = jiraAdapter(); - await expect(adapter.fetchTicket("10001")).rejects.toBeInstanceOf( - IssueTrackerNotFoundError, - ); + await expect(adapter.fetchTicket("10001")).rejects.toSatisfy( + (err: IssueTrackerNotFoundError) => + err instanceof IssueTrackerNotFoundError && err.code === "NOT_FOUND", + );🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/adapters/issue-tracker/jira.test.ts` around lines 53 - 64, Update the test for jiraAdapter.fetchTicket to not only expect an IssueTrackerNotFoundError but also assert the thrown error's code property used for duck-typing; catch or await the rejection (e.g., with try/catch or using rejects.toEqual/async assertion helpers) and assert error.code is defined and equals the adapter's 404-identifying value so that IssueTrackerNotFoundError detection is verified in addition to the class type.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/adapters/issue-tracker/jira.test.ts`:
- Around line 53-64: Update the test for jiraAdapter.fetchTicket to not only
expect an IssueTrackerNotFoundError but also assert the thrown error's code
property used for duck-typing; catch or await the rejection (e.g., with
try/catch or using rejects.toEqual/async assertion helpers) and assert
error.code is defined and equals the adapter's 404-identifying value so that
IssueTrackerNotFoundError detection is verified in addition to the class type.
In `@src/routes/webhooks/jira.post.ts`:
- Around line 211-217: Consolidate duplicate project-key extraction logic by
creating a shared utility (e.g., extractProjectKey) that implements the
canonical behavior: trim the input, return null for empty or missing dash or
dash at position 0, and return the segment before the first dash upper-cased;
then replace usages of extractProjectKeyFromIdentifier (in jira.post.ts),
extractProjectKey (in jira.ts) and resolveTicketProjectKey (in reconcile.ts) to
call the new shared function and update imports accordingly so all three call
the single implementation with the same return type and input handling.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: d9f3e023-cfa0-47e0-85a2-2974fba74764
📒 Files selected for processing (7)
src/adapters/issue-tracker/jira.test.tssrc/adapters/issue-tracker/jira.tssrc/adapters/issue-tracker/types.tssrc/lib/reconcile.test.tssrc/lib/reconcile.tssrc/routes/cron/poll.get.tssrc/routes/webhooks/jira.post.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- src/routes/cron/poll.get.ts
* fix: workflow timout * Aiw 25 safeguard (#37) * feat: add redis safeguard * fix: json parse --------- Co-authored-by: kasin-it <kacperosinilo@gmail.com> * feat: push inside the sandbox (#40) * Aiw 16 cicd info (#38) * feat: add cicd check * feat: ci/cd fail check * feat: remove console log * Aiw 25 safeguard (#37) * feat: add redis safeguard * fix: json parse --------- Co-authored-by: kasin-it <kacperosinilo@gmail.com> * feat: push inside the sandbox (#40) * feat: add cicd check * feat: ci/cd fail check * feat: remove console log * feat: remove console.log * fix: ci --------- Co-authored-by: kasin-it <kacperosinilo@gmail.com> Co-authored-by: Kacper <89151689+kasin-it@users.noreply.github.com> * fix: push issue * fix: branch creation * feat: implement new agent flow (#43) * feat: prevent gitignoing memory * feat: add token usage * docs: add security observability spec for Arthur Engine integration Defines 6 threat categories (prompt injection, data exfiltration, secrets leakage, PII, code safety, behavioral anomalies), pipeline integration gates, response severity model, and observability streams for the AWS on-prem deployment. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add debug mode section to security observability spec On-demand deep inspection for suspicious agent runs — full prompt/response logging, tool call traces, network packet capture (tcpdump), per-tool-call file system diffs, and env dumps. Triggered manually or auto-escalated from medium+ findings. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * dcos: add security & observability spec * feat: add vsc adapter plan * fix: cc oauth * feat: remove redundant model export * feat: add webhooks * feat: add better error handling * fix: webhook token * chore: trigger redeploy * wip * wip * feat: remove logs * feat: remove desination column logic * feat: add gitlab (#49) * feat: add gitlab * chore: regenerate pnpm lock * feat: review improvements * feat: harden poll logic (#52) * feat: harden poll logic * fix: mock env in dispatch * fix: ghost workflow logs * feat: implement IssueTrackerNotFoundError handling in JiraAdapter and related tests * feat: add cancel notification * fix: sandbox cancelation * fix: clarification flow * feat: tune resaerch prompt * feat: attachemnt support (#50) * feat: attachemnt support * fix: attachement fetch * fix: ci fail * feat: enhance JiraAdapter and dispatch logic - Added tests for sanitizing malformed attachment sizes in JiraAdapter. - Improved handling of cross-origin requests by omitting Authorization headers. - Enhanced redirect handling in JiraAdapter to support multiple redirects. - Updated dispatchTicket function to paginate sandbox list and handle capacity checks more robustly. - Added pagination support in sandbox list responses to improve efficiency. * fix: ci * feat: enhance JiraAdapter attachment handling and improve error management - Added test to omit contentUrl when Jira does not provide attachment content. - Improved attachment handling in JiraAdapter to ensure contentUrl is undefined when absent. - Enhanced error handling for missing Location headers during redirects in attachment downloads. - Updated fetchAttachmentsWithRetry to skip attachments without content URLs and log appropriate messages. * feat: add logs to dispatch * fix: dispatch timeout * feat: add new e2e * feat: go back to 3 phase flow * feat: new tests * fix: remove fake err * feat: add clarification e2e * feat: add failure e2e tests * feat: add dispatch e2e --------- Co-authored-by: ai-workflow-blazity <ai-workflow@blazity.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix: workflow timout * Aiw 25 safeguard (#37) * feat: add redis safeguard * fix: json parse --------- Co-authored-by: kasin-it <kacperosinilo@gmail.com> * feat: push inside the sandbox (#40) * Aiw 16 cicd info (#38) * feat: add cicd check * feat: ci/cd fail check * feat: remove console log * Aiw 25 safeguard (#37) * feat: add redis safeguard * fix: json parse --------- Co-authored-by: kasin-it <kacperosinilo@gmail.com> * feat: push inside the sandbox (#40) * feat: add cicd check * feat: ci/cd fail check * feat: remove console log * feat: remove console.log * fix: ci --------- Co-authored-by: kasin-it <kacperosinilo@gmail.com> Co-authored-by: Kacper <89151689+kasin-it@users.noreply.github.com> * fix: push issue * fix: branch creation * feat: implement new agent flow (#43) * feat: prevent gitignoing memory * feat: add token usage * docs: add security observability spec for Arthur Engine integration Defines 6 threat categories (prompt injection, data exfiltration, secrets leakage, PII, code safety, behavioral anomalies), pipeline integration gates, response severity model, and observability streams for the AWS on-prem deployment. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add debug mode section to security observability spec On-demand deep inspection for suspicious agent runs — full prompt/response logging, tool call traces, network packet capture (tcpdump), per-tool-call file system diffs, and env dumps. Triggered manually or auto-escalated from medium+ findings. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * dcos: add security & observability spec * feat: add vsc adapter plan * fix: cc oauth * feat: remove redundant model export * feat: add webhooks * feat: add better error handling * fix: webhook token * chore: trigger redeploy * wip * wip * feat: remove logs * feat: remove desination column logic * feat: add gitlab (#49) * feat: add gitlab * chore: regenerate pnpm lock * feat: review improvements * feat: harden poll logic (#52) * feat: harden poll logic * fix: mock env in dispatch * fix: ghost workflow logs * feat: implement IssueTrackerNotFoundError handling in JiraAdapter and related tests * feat: add cancel notification * fix: sandbox cancelation * fix: clarification flow * feat: tune resaerch prompt * feat: attachemnt support (#50) * feat: attachemnt support * fix: attachement fetch * fix: ci fail * feat: enhance JiraAdapter and dispatch logic - Added tests for sanitizing malformed attachment sizes in JiraAdapter. - Improved handling of cross-origin requests by omitting Authorization headers. - Enhanced redirect handling in JiraAdapter to support multiple redirects. - Updated dispatchTicket function to paginate sandbox list and handle capacity checks more robustly. - Added pagination support in sandbox list responses to improve efficiency. * fix: ci * feat: enhance JiraAdapter attachment handling and improve error management - Added test to omit contentUrl when Jira does not provide attachment content. - Improved attachment handling in JiraAdapter to ensure contentUrl is undefined when absent. - Enhanced error handling for missing Location headers during redirects in attachment downloads. - Updated fetchAttachmentsWithRetry to skip attachments without content URLs and log appropriate messages. * feat: add logs to dispatch * fix: dispatch timeout * feat: add new e2e * feat: go back to 3 phase flow * feat: new tests * fix: remove fake err * feat: add clarification e2e * feat: add failure e2e tests * feat: add dispatch e2e * feat: update capacity check * feat: update capacity check * fix: at capacity error * fix: us13 cleanup * fix: stale run * fix: us03 prompt * fix: follow pr comments * fix: us7 and us8 * feat: optimize sandbox delete * fix: concurrent tests flow * feat: better multi ticket dispatch * feat: disable review * feat: new actions for e2e * fix: gh actions * feat: add oidc token to e2e * fix: us15 e2e * fix: us11 * feat: new capacity check * feat: remove tier1 * feat: remove duplicates * fix: ci/cd order * feat: new ci * fix; duplicate ci --------- Co-authored-by: ai-workflow-blazity <ai-workflow@blazity.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix: workflow timout * Aiw 25 safeguard (#37) * feat: add redis safeguard * fix: json parse --------- Co-authored-by: kasin-it <kacperosinilo@gmail.com> * feat: push inside the sandbox (#40) * Aiw 16 cicd info (#38) * feat: add cicd check * feat: ci/cd fail check * feat: remove console log * Aiw 25 safeguard (#37) * feat: add redis safeguard * fix: json parse --------- Co-authored-by: kasin-it <kacperosinilo@gmail.com> * feat: push inside the sandbox (#40) * feat: add cicd check * feat: ci/cd fail check * feat: remove console log * feat: remove console.log * fix: ci --------- Co-authored-by: kasin-it <kacperosinilo@gmail.com> Co-authored-by: Kacper <89151689+kasin-it@users.noreply.github.com> * fix: push issue * fix: branch creation * feat: implement new agent flow (#43) * feat: prevent gitignoing memory * feat: add token usage * docs: add security observability spec for Arthur Engine integration Defines 6 threat categories (prompt injection, data exfiltration, secrets leakage, PII, code safety, behavioral anomalies), pipeline integration gates, response severity model, and observability streams for the AWS on-prem deployment. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add debug mode section to security observability spec On-demand deep inspection for suspicious agent runs — full prompt/response logging, tool call traces, network packet capture (tcpdump), per-tool-call file system diffs, and env dumps. Triggered manually or auto-escalated from medium+ findings. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * dcos: add security & observability spec * feat: add vsc adapter plan * fix: cc oauth * feat: remove redundant model export * feat: add webhooks * feat: add better error handling * fix: webhook token * chore: trigger redeploy * wip * wip * feat: remove logs * feat: remove desination column logic * feat: add gitlab (#49) * feat: add gitlab * chore: regenerate pnpm lock * feat: review improvements * feat: harden poll logic (#52) * feat: harden poll logic * fix: mock env in dispatch * fix: ghost workflow logs * feat: implement IssueTrackerNotFoundError handling in JiraAdapter and related tests * feat: add cancel notification * fix: sandbox cancelation * fix: clarification flow * feat: tune resaerch prompt * feat: attachemnt support (#50) * feat: attachemnt support * fix: attachement fetch * fix: ci fail * feat: enhance JiraAdapter and dispatch logic - Added tests for sanitizing malformed attachment sizes in JiraAdapter. - Improved handling of cross-origin requests by omitting Authorization headers. - Enhanced redirect handling in JiraAdapter to support multiple redirects. - Updated dispatchTicket function to paginate sandbox list and handle capacity checks more robustly. - Added pagination support in sandbox list responses to improve efficiency. * fix: ci * feat: enhance JiraAdapter attachment handling and improve error management - Added test to omit contentUrl when Jira does not provide attachment content. - Improved attachment handling in JiraAdapter to ensure contentUrl is undefined when absent. - Enhanced error handling for missing Location headers during redirects in attachment downloads. - Updated fetchAttachmentsWithRetry to skip attachments without content URLs and log appropriate messages. * feat: add logs to dispatch * fix: dispatch timeout * feat: add new e2e * feat: go back to 3 phase flow * feat: new tests * fix: remove fake err * feat: add clarification e2e * feat: add failure e2e tests * feat: add dispatch e2e * feat: update capacity check * feat: update capacity check * fix: at capacity error * fix: us13 cleanup * fix: stale run * fix: us03 prompt * fix: follow pr comments * fix: us7 and us8 * feat: optimize sandbox delete * fix: concurrent tests flow * feat: better multi ticket dispatch * feat: disable review * feat: new actions for e2e * fix: gh actions * feat: add oidc token to e2e * fix: us15 e2e * fix: us11 * feat: new capacity check * feat: remove tier1 * feat: remove duplicates * fix: ci/cd order * feat: new ci * fix; duplicate ci * fix: e2e on pr --------- Co-authored-by: ai-workflow-blazity <ai-workflow@blazity.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Summary by CodeRabbit
Bug Fixes
Webhooks
Adapters
Tests