diff --git a/server/src/__tests__/heartbeat-workspace-session.test.ts b/server/src/__tests__/heartbeat-workspace-session.test.ts index 5f94040ce6..26734c687d 100644 --- a/server/src/__tests__/heartbeat-workspace-session.test.ts +++ b/server/src/__tests__/heartbeat-workspace-session.test.ts @@ -30,7 +30,6 @@ import { resolveExecutionWorkspaceReuseProvisioningPolicy, resolveNextSessionState, resolveTaskSessionConfigFreshness, - issueTextImpliesPrDeliverable, isWorkspaceSyncConflictFailure, requiresPushCapabilityPreflight, resolveWorkspaceAfterLowTrustPreflight, @@ -972,58 +971,7 @@ describe("assertPushCapabilityCheckoutValid", () => { }); }); -describe("issueTextImpliesPrDeliverable", () => { - it("matches verb-anchored PR deliverables", () => { - expect(issueTextImpliesPrDeliverable("Review and open PR for the CI shard split")).toBe(true); - expect(issueTextImpliesPrDeliverable("Push the branch and open a pull request")).toBe(true); - expect(issueTextImpliesPrDeliverable("Each run: make the change and open a draft PR")).toBe(true); - expect(issueTextImpliesPrDeliverable("push feature work to origin when done")).toBe(true); - }); - - it("ignores passing mentions and unrelated text", () => { - expect(issueTextImpliesPrDeliverable("The PR merged yesterday; investigate the regression")).toBe(false); - expect(issueTextImpliesPrDeliverable("PR feedback addressed")).toBe(false); - expect(issueTextImpliesPrDeliverable("Update the pricing page copy")).toBe(false); - expect(issueTextImpliesPrDeliverable("a proper approach to pushing back on scope")).toBe(false); - expect(issueTextImpliesPrDeliverable(null)).toBe(false); - expect(issueTextImpliesPrDeliverable("")).toBe(false); - }); - - it("ignores non-git uses of push", () => { - expect(issueTextImpliesPrDeliverable("push back on the upstream dependency change")).toBe(false); - expect(issueTextImpliesPrDeliverable("push back the branch cut date")).toBe(false); - expect(issueTextImpliesPrDeliverable("push notifications for mobile")).toBe(false); - // Git shapes still match. - expect(issueTextImpliesPrDeliverable("pushing the release branch")).toBe(true); - expect(issueTextImpliesPrDeliverable("push feature work to origin when done")).toBe(true); - }); -}); - describe("requiresPushCapabilityPreflight", () => { - it("enables the guard when the issue text states the PR deliverable", () => { - expect(requiresPushCapabilityPreflight({ - adapterType: "codex_local", - issueId: "issue-1", - explicitRunScopedSkillKeys: [], - issueText: "Push ci/shard-split and open PR", - })).toBe(true); - - expect(requiresPushCapabilityPreflight({ - adapterType: "codex_local", - issueId: "issue-1", - explicitRunScopedSkillKeys: [], - issueText: "Investigate why the PR checks were slow", - })).toBe(false); - - // Without an issue there is nothing to preflight. - expect(requiresPushCapabilityPreflight({ - adapterType: "codex_local", - issueId: null, - explicitRunScopedSkillKeys: [], - issueText: "open a PR", - })).toBe(false); - }); - it("only enables the guard when the issue explicitly mentions the GitHub PR workflow skill", () => { expect(requiresPushCapabilityPreflight({ adapterType: "codex_local", diff --git a/server/src/services/heartbeat.ts b/server/src/services/heartbeat.ts index f027ab3d9c..e931f6dab9 100644 --- a/server/src/services/heartbeat.ts +++ b/server/src/services/heartbeat.ts @@ -736,44 +736,14 @@ function hasGithubPrWorkflowSkill(desiredSkills: string[]) { }); } -/** - * Conservative, verb-anchored patterns for an issue whose deliverable is a - * pushed branch or opened pull request. Verb anchoring keeps passing mentions - * ("the PR merged yesterday") from triggering the credential preflight. - */ -const PR_DELIVERABLE_TEXT_PATTERNS = [ - /\bopen(?:s|ed|ing)?\s+(?:a\s+|the\s+|an?\s+draft\s+)?(?:pull\s+request|pr)\b/i, - /\b(?:create|creates|created|creating|raise|raises|raised|raising|submit|submits|submitted|submitting)\s+(?:a\s+|the\s+|an?\s+draft\s+)?(?:pull\s+request|pr)\b/i, - // "push back" (an objection or a date) is never a git push, and bare - // proximity to words like "upstream" over-matches ("push back on the - // upstream dependency change"); require the git object shape instead. - /\bpush(?:es|ed|ing)?\b(?!\s+back\b)[^.\n]{0,40}\bbranch(?:es)?\b/i, - /\bpush(?:es|ed|ing)?\s+(?:[^.\n]{0,30}\s)?to\s+(?:origin|remote|upstream|github)\b/i, -]; - -export function issueTextImpliesPrDeliverable(text: string | null | undefined): boolean { - if (!text) return false; - return PR_DELIVERABLE_TEXT_PATTERNS.some((pattern) => pattern.test(text)); -} - export function requiresPushCapabilityPreflight(input: { adapterType: string; issueId: string | null | undefined; explicitRunScopedSkillKeys: string[]; - /** - * Issue title + description. Routine-created issues and agent-to-agent - * handoffs rarely mention the GitHub PR workflow skill explicitly, yet - * state the PR deliverable in plain text — without this, the credential - * gap only surfaces after the implementation and review work is done. - */ - issueText?: string | null; }) { return Boolean(input.issueId) && GIT_SENSITIVE_LOCAL_ADAPTER_TYPES.has(input.adapterType) - && ( - hasGithubPrWorkflowSkill(input.explicitRunScopedSkillKeys) - || issueTextImpliesPrDeliverable(input.issueText) - ); + && hasGithubPrWorkflowSkill(input.explicitRunScopedSkillKeys); } const LOW_TRUST_SENSITIVE_ENV_KEY_RE = @@ -13840,7 +13810,6 @@ export function heartbeatService(db: Db, options: HeartbeatServiceOptions = {}) adapterType: agent.adapterType, issueId, explicitRunScopedSkillKeys: runScopedMentionedSkillKeys, - issueText: issueRef ? `${issueRef.title ?? ""}\n${issueRef.description ?? ""}` : null, }); const { resolvedConfig, secretKeys, secretManifest } = await resolveExecutionRunAdapterConfig({ companyId: agent.companyId,