# PR Agent

You handle **all git operations** for the **{FLOW}** implementation of **{CONNECTOR}**: committing on the preflight-created run branch, scrubbing credentials, pushing, and opening a **PR** on `juspay/hyperswitch-prism`.

**First**: Read this file (`grace/workflow/2.4_pr.md`) fully to understand all phases and rules before proceeding.

**This agent handles BOTH successful and failed connectors.** For failed connectors, the PR is created with a "do not merge" label and the failure details in the description, so that the team has visibility into what was attempted and what went wrong.

**HARD GUARDRAIL — DIRECT WORKFLOW ON `juspay/hyperswitch-prism`**: We work directly on `juspay/hyperswitch-prism`. The `origin` remote points to `juspay/hyperswitch-prism`. All pushes go to `origin`. PRs are created as same-repo PRs (no cross-fork syntax needed).

**HARD GUARDRAIL — TARGET REPOSITORY**: ALL `gh` commands MUST use `--repo juspay/hyperswitch-prism`. This is the ONLY valid target repository. Do NOT use any other org or repo name.

**HARD GUARDRAIL — NO RETRYING SAME COMMAND**: If a `gh pr create` or `git push` command fails, do NOT retry the exact same command. Diagnose the error, fix the root cause, then retry with corrected parameters. Retrying identical commands wastes time and will produce identical errors.

**HARD GUARDRAIL — NO BRANCH CREATION, NO CHERRY-PICK**: The run branch (`{BRANCH}`) was already created and checked out by the preflight checkpoint, and the implementation checkpoint wrote the connector files there. Do NOT run `git checkout -b ...` and do NOT run `git cherry-pick ...` in this agent. Commit and push directly on `{BRANCH}`.

---

## Inputs

| Parameter | Description | Example |
|-----------|-------------|---------|
| `{CONNECTOR}` | Connector name (lowercase for branches/files, original casing for display) | `cybersource` |
| `{FLOW}` | Payment flow being implemented | `BankDebit` |
| `{BRANCH}` | Feature branch the implementation checkpoint committed on. For dashboard-driven single-connector runs this is a runId-suffixed branch from preflight; for the orchestrator's bulk CLI mode this is the shared dev branch. | `feat/grace-cybersource-bankdebit-3f69a1` (dashboard) or `feat/mit` (bulk CLI) |
| `{CONNECTOR_STATUS}` | Whether the connector implementation passed or failed | `SUCCESS` or `FAILED` |
| `{FAILURE_REASON}` | Why the connector failed (empty if SUCCESS) | `cargo build failed: missing field 'amount'` |
| `{GRPCURL_OUTPUT}` | The full grpcurl test output from the Codegen Agent (may be partial/error output for FAILED connectors) | *(raw text)* |
| `{CONNECTOR_SOURCE_FILES}` | Paths to connector source files that were modified | `crates/integrations/connector-integration/src/connectors/cybersource.rs, .../cybersource/transformers.rs` |

---

## Phase 1: Commit on the Run Branch

The implementation checkpoint left modified connector files in the working tree on `{BRANCH}`. Verify you are on that branch, then commit.

### 1a: Verify branch and check for changes

```bash
git branch --show-current                   # must equal {BRANCH}
```

If the current branch does NOT equal `{BRANCH}`, switch to it (preflight created it earlier in the run, so it exists locally):

```bash
git checkout {BRANCH}
```

Then check for changes:

```bash
git status -- crates/integrations/connector-integration/src/connectors/{connector}*
```

If there are no modified/new connector files, there is nothing to commit. Return FAILED with reason "No connector files to commit."

### 1b: Pre-commit validation (SUCCESS connectors only)

**If `{CONNECTOR_STATUS}` is `SUCCESS`, you MUST verify ALL of the following by inspecting the Codegen Agent's report and the contents of `{GRPCURL_OUTPUT}` (the raw grpcurl output captured upstream and passed in as an input). If ANY answer is NO, reclassify as FAILED.**

```
PRE-COMMIT CHECKLIST (mandatory for SUCCESS):
[ ] Did `cargo build` complete with zero errors? (YES/NO)
[ ] Did the gRPC test checkpoint run a grpcurl Authorize call?
    Verify {GRPCURL_OUTPUT} contains the request and response of that call. (YES/NO)
[ ] Was the `status_code` in the response 2xx (200-299)? (YES/NO)
[ ] Did the grpcurl response contain a JSON object with a success status
    (authorized/PENDING/charged/REQUIRES_CUSTOMER_ACTION)? (YES/NO)
[ ] Was the grpcurl output free of "Error invoking method", "PAYMENT_FLOW_ERROR",
    or any error messages? (YES/NO)
```

If any answer is NO, reclassify `{CONNECTOR_STATUS}` as `FAILED` and set `{FAILURE_REASON}` accordingly.

### 1c: Stage and commit

**For SUCCESS connectors:**

```bash
git add crates/integrations/connector-integration/src/connectors/{connector}*
git status  # verify only expected files staged
git commit -m "feat(connector): implement {FLOW} for {connector}"
```

**For FAILED connectors:**

```bash
git add crates/integrations/connector-integration/src/connectors/{connector}*
git status  # verify only expected files staged
git commit -m "wip(connector): [FAILED] implement {FLOW} for {connector}"
```

Capture the commit SHA for the JSON output:

```bash
git log -1 --format='%H'
```

Store as `{COMMIT_HASH}`.

---

## Phase 2: Credential Scrub (MANDATORY)

**You MUST verify that no credentials, API keys, or secrets are present in the committed files before pushing.**

### 2a: Inspect the diff

```bash
git diff origin/main..{BRANCH} -- crates/integrations/connector-integration/src/connectors/{connector}*
```

### 2b: Search for credential patterns

Scan the diff output for any of these patterns:
- Hardcoded API keys (long alphanumeric strings that look like secrets)
- Bearer tokens
- `x-api-key: <actual_value>` (not a placeholder)
- `Authorization: Basic <actual_value>`
- Strings from `creds.json` values
- Any test credentials embedded in source code (account numbers, IBANs, routing numbers that match real test creds)

**Source code should NEVER contain credentials.** Connector implementations read credentials at runtime from the request context — they do not hardcode them. If you find hardcoded credentials in source files, that is a bug in the codegen output. Fix it:

```bash
# Edit the file to remove the hardcoded credential
# Replace with the correct runtime credential access pattern used by other connectors
git add <fixed_files>
git commit --amend --no-edit
```

### 2c: Verify creds.json is NOT staged

```bash
git diff --name-only origin/main..{BRANCH}
```

If `creds.json` or any `.env` file appears in this list, something went wrong. Remove it:

```bash
git reset HEAD~ -- creds.json .env
git commit --amend --no-edit
```

---

## Phase 3: Push the Branch

**Push to `origin` (`juspay/hyperswitch-prism`).**

```bash
git push origin {BRANCH}
```

If push fails:
- **Branch already exists on remote with diverged history**: Try `git push origin {BRANCH} --force-with-lease` only if this is a retry of a previous failed PR attempt for the same run (same `{BRANCH}` value).
- **Permission denied**: Return FAILED — credentials may be misconfigured.

The runId6 suffix in `{BRANCH}` makes collisions across runs effectively impossible, so the legacy "append `-v2` suffix" workaround no longer applies.

---

## Phase 4: Prepare PR Description

### 4a: Sanitize grpcurl output

Take the `{GRPCURL_OUTPUT}` and **redact ALL credentials** (this applies whether the connector passed or failed — even partial/error grpcurl output must be sanitized):

1. Replace any `-H 'x-api-key: ...'` header values with `<REDACTED>`
2. Replace any `-H 'x-key1: ...'` header values with `<REDACTED>`
3. Replace any `-H 'x-api-secret: ...'` header values with `<REDACTED>`
4. Replace any `-H 'x-merchant-id: ...'` header values with `<REDACTED>`
5. Replace any `-H 'Authorization: ...'` header values with `<REDACTED>`
6. Replace any other `-H` header values that look like credentials (long alphanumeric strings, base64, etc.) with `<REDACTED>`
7. Replace any account numbers, IBANs, routing numbers, sort codes, BSB numbers with `<REDACTED>`
8. Preserve the grpcurl command structure, endpoint, request body fields (keys only), and the full response JSON

**Example of sanitized output:**
```
grpcurl -plaintext \
  -H 'x-connector: adyen' \
  -H 'x-api-key: <REDACTED>' \
  -H 'x-merchant-id: <REDACTED>' \
  -d '{
    "request_ref_id": {"id": "test_adyen_bankdebit_001"},
    "amount": 100,
    "minor_amount": 10000,
    "currency": "EUR",
    ...
    "payment_method": {
      "sepa": {
        "iban": {"value": "<REDACTED>"},
        "bank_account_holder_name": {"value": "John Doe"}
      }
    }
  }' \
  localhost:8000 \
  ucs.v2.PaymentService/Authorize

Response:
{
  "status": "authorized",
  "status_code": 200,
  ...
}
```

### 4b: Build the PR description

**Use the appropriate template based on `{CONNECTOR_STATUS}`:**

#### Template for SUCCESS connectors:

```markdown
## Summary

Implement **{FLOW}** flow for **{CONNECTOR}** connector.

This implementation was generated and validated by **GRACE** (automated connector integration pipeline).

## Changes

- Added {FLOW} support to `{connector}.rs` (added to `create_all_prerequisites!` macro, added `macro_connector_implementation!`)
- Added {FLOW} request/response types and `TryFrom` implementations in `{connector}/transformers.rs`

## Files Modified

{list each file from CONNECTOR_SOURCE_FILES}

## gRPC Test Results

**Status: PASS**

<details>
<summary>grpcurl Authorize call (credentials redacted)</summary>

```
{SANITIZED_GRPCURL_OUTPUT}
```

</details>

## Validation Checklist

- [x] `cargo build` passed with zero errors
- [x] grpcurl Authorize returned success status (2xx)
- [x] No credentials in committed source code
- [x] Only connector-specific files modified
```

#### Template for FAILED connectors:

```markdown
## Summary

**[FAILED — DO NOT MERGE]** Attempted implementation of **{FLOW}** flow for **{CONNECTOR}** connector.

This implementation was generated by **GRACE** (automated connector integration pipeline) but **did not pass validation**. This PR is opened for visibility and review — it requires manual intervention before merging.

## Failure Reason

{FAILURE_REASON}

## Changes (incomplete/broken)

- Attempted {FLOW} support in `{connector}.rs`
- Attempted {FLOW} request/response types in `{connector}/transformers.rs`

## Files Modified

{list each file from CONNECTOR_SOURCE_FILES}

## gRPC Test Results

**Status: FAIL**

<details>
<summary>grpcurl output / error details (credentials redacted)</summary>

```
{SANITIZED_GRPCURL_OUTPUT}
```

</details>

## Validation Checklist

- [ ] `cargo build` passed with zero errors
- [ ] grpcurl Authorize returned success status (2xx)
- [x] No credentials in committed source code
- [x] Only connector-specific files modified

> **Note**: This PR was auto-generated by GRACE and marked as "do not merge" because validation failed. Please review the failure reason and grpcurl output above, fix the issues manually, and remove the "do not merge" label when ready.
```

---

## Phase 5: Create the Pull Request

**CRITICAL: All `gh` commands MUST use `--repo juspay/hyperswitch-prism`.**

### 5a: Check for existing PR (idempotency)

```bash
gh pr list --repo juspay/hyperswitch-prism --head {BRANCH} --state open --json url --jq '.[0].url' 2>/dev/null
```

Because `{BRANCH}` includes the runId6 suffix, this match only happens if the **same run** is re-entering this checkpoint (e.g. after a retry). If a PR URL is returned, the PR already exists for this run. Report SUCCESS with that URL and finish.

### 5b: Ensure labels exist

```bash
gh label create "GRACE" --repo juspay/hyperswitch-prism --description "Auto-generated by GRACE pipeline" --color "7057ff" 2>/dev/null || true
gh label create "do not merge" --repo juspay/hyperswitch-prism --description "PR requires manual intervention before merging" --color "e11d48" 2>/dev/null || true
```

### 5c: Determine labels and title

**For SUCCESS connectors:**
- Labels: `GRACE`
- Title: `feat(connector): implement {FLOW} for {connector}`

**For FAILED connectors:**
- Labels: `GRACE`, `do not merge`
- Title: `[GRACE-FAILED] feat(connector): implement {FLOW} for {connector}`

### 5d: Create the PR

**For SUCCESS connectors:**
```bash
gh pr create \
  --repo juspay/hyperswitch-prism \
  --base main \
  --head {BRANCH} \
  --title "feat(connector): implement {FLOW} for {connector}" \
  --label "GRACE" \
  --body "$(cat <<'EOF'
<PR_DESCRIPTION_FROM_PHASE_4B_SUCCESS_TEMPLATE>
EOF
)"
```

**For FAILED connectors:**
```bash
gh pr create \
  --repo juspay/hyperswitch-prism \
  --base main \
  --head {BRANCH} \
  --title "[GRACE-FAILED] feat(connector): implement {FLOW} for {connector}" \
  --label "GRACE" \
  --label "do not merge" \
  --body "$(cat <<'EOF'
<PR_DESCRIPTION_FROM_PHASE_4B_FAILED_TEMPLATE>
EOF
)"
```

Capture the PR URL from the output.

---

## Output

Return your final answer as JSON. This is the only output format the engine accepts; the legacy `STATUS:`/`PR_URL:` free-text format is no longer parsed. Reply with ONLY the JSON object — no prose, no markdown fences.

```json
{
  "approved": true,
  "status": "SUCCESS",
  "prUrl": "https://github.com/juspay/hyperswitch-prism/pull/1206",
  "branchName": "{BRANCH}",
  "commitHash": "<commit SHA from Phase 1c>",
  "reason": ""
}
```

Field rules:

- For SUCCESS connectors: `approved=true`, `status="SUCCESS"`, `prUrl` is the URL captured from `gh pr create` output (or from the existing-PR check in Phase 5a), `reason` is empty.
- For FAILED connectors: `approved=false`, `status="FAILED"`, `prUrl` is still the URL of the do-not-merge PR (Rule 11: every connector gets a PR), `reason` explains the failure.
- `branchName` is always `{BRANCH}` — the suffixed run branch from preflight (e.g. `feat/grace-cybersource-bankdebit-3f69a1`).
- `commitHash` is the SHA stored in Phase 1c.

---

## Rules

1. **Target repo is `juspay/hyperswitch-prism` — ALWAYS** — every `gh pr create`, `gh label create`, `gh pr list`, and any other `gh` command MUST include `--repo juspay/hyperswitch-prism`. Do NOT omit the `--repo` flag. Do NOT use any other org/repo. This is non-negotiable.
2. **Same-repo PRs use bare branch names** — when creating or listing PRs, the `--head` flag uses bare branch names (e.g., `feat/grace-cybersource-bankdebit-3f69a1`). No fork owner prefix needed.
3. **Push to `origin` (`juspay/hyperswitch-prism`)** — all branches are pushed directly to `juspay/hyperswitch-prism`.
4. **No connector logic changes** — this agent commits, scrubs, pushes, and creates PRs. It does NOT modify connector logic (except removing hardcoded credentials, which is a scrub fix, not a logic change).
5. **No branch creation, no cherry-pick** — the run branch was created by the preflight checkpoint. This agent commits and pushes on that branch directly.
6. **Never force push to main** — only `--force-with-lease` on the feature branch is permitted, and only as a retry within the same run.
7. **Credential scrub is mandatory** — applies to BOTH success and failed PRs. If credentials are found in source files, fix them before pushing. If credentials cannot be removed cleanly, return FAILED.
8. **Sanitize ALL grpcurl output** — every header value, every account number, every secret must be redacted in the PR description. This applies to both successful and failed/partial grpcurl output.
9. **Idempotent within a run** — if a PR already exists for `{BRANCH}` (check with `gh pr list --repo juspay/hyperswitch-prism --head {BRANCH} --state open`), report SUCCESS with the existing PR URL. Do NOT create a duplicate.
10. **Failed connectors get "do not merge"** — if `{CONNECTOR_STATUS}` is `FAILED`, the PR MUST have both "GRACE" and "do not merge" labels, and the title MUST be prefixed with `[GRACE-FAILED]`.
11. **Always create a PR** — both successful and failed connectors get PRs. The only reason to NOT create a PR is if there are no connector files to commit (Phase 1a).
12. **Never retry identical commands** — if `gh pr create` or `git push` fails, diagnose the error first. Common causes: (a) permission denied, (b) PR already exists (treat as idempotency hit, see Phase 5a). Fix the root cause, then retry with corrected parameters.
13. **Scoped git staging** — only stage connector-specific files (`git add crates/integrations/connector-integration/src/connectors/{connector}*`). Never `git add -A`. Never stage `creds.json` or `.env`.
