iT邦幫忙

2026 iThome 鐵人賽

DAY 26
1
Build on Google AI

從 Vibe Coding 到 Production:用 Google AI 打造上線守門員系列 第 26

Day 26|把 Agent 放進 Pull Request:自動檢查每次程式碼變更

  • 分享至 

  • xImage
  •  

Day 25,我們把 Vibe Guard 包成一條本機指令:

npm run vibe-guard -- scan .

它會執行 Recon、Hunter、Challenger 與動態測試,再輸出:

Canonical Findings Report
Markdown Summary
Policy Gate
Exit Code

開發者可以在提交前主動執行。

但本機檢查有一個無法避免的限制:

它可以被忘記,也可以被跳過。

今天要把相同 Contract 放進 GitHub Pull Request。

每次 PR 建立或更新時,GitHub Actions 會:

Checkout PR Revision
  → 安裝固定相依套件
  → 計算 Base 與 Head 的變更行
  → 執行 Vibe Guard CLI
  → 產生 Job Summary 與 Annotation
  → 保存完整 Artifact
  → 依 Policy 決定 Check 成功或失敗

重點不是在 CI 裡重新做一套 Reviewer。

本機與 Pull Request 必須共用:

同一條掃描流程
同一份 Findings Schema
同一套 Severity Policy
同一組 Exit Code 語意

否則很容易出現:

本機顯示通過,
Pull Request 卻用另一套規則失敗。

PR Check 是 Policy Consumer,不是新的 Agent

Day 25 的資料流是:

Agent Workflow
  → Findings Report
  → Policy Evaluation
  → Terminal / JSON / Markdown
  → Exit Code

Day 26 不改變這條流程。

GitHub Actions 只是增加新的 Consumer:

Findings Report
  → Pull Request Adapter
  → Check Annotation
  → Job Summary
  → Workflow Artifact
  → Required Status Check

Pull Request Adapter 不會:

  • 重新呼叫模型判斷 Severity。
  • 改寫 Challenger 的 Verdict。
  • requires_evidence 自動升級成 High。
  • 因為 Finding 位於 PR 中,就直接宣稱是新漏洞。

它只回答:

這項 Finding 是否落在本次變更範圍?
依照 PR Policy,是否應阻擋合併?
應該在 GitHub 顯示成 Error、Warning 還是 Notice?

這是確定性的 Policy 與格式轉換,不需要另一個 LLM。

先區分四種 PR Scope

完整 Repository Scan 可能找到:

  1. 本次新增或修改行上的 Finding。
  2. 本次修改檔案中,但不在實際 Diff Line 的 Finding。
  3. Repository 其他位置既有的 Finding。
  4. 沒有 Source Location 的全域 Evidence Gap。

今天將它們分類為:

Scope 意義
changed-line Finding Location 與 PR 新增/修改行重疊
changed-file 檔案有變更,但 Finding 行不在 Diff Hunk
existing Finding 位於本次沒有修改的檔案
global 沒有單一 Source Location,例如部署證據缺口

第一版 PR Gate 只阻擋:

confirmed
severity >= high
scope = changed-line

其他結果仍然顯示,但不直接把這次 PR 判定失敗。

這是刻意採取的過渡政策。

如果第一天導入工具就要求:

整個 Repository 的所有既有 High Finding 都必須清零,
否則任何 PR 都不能合併。

團隊很可能因為大量既有問題而直接停用 Check。

比較可行的起點是:

先阻止 PR 在修改行引入或重新暴露已確認的 High 問題,
同時把既有問題與 Evidence Gap 保存到 Summary。

不過,changed-line 仍不等於 new

一項問題可能早已存在,只是這次 PR 剛好修改同一行。

真正的 New、Unchanged、Resolved 與 Reopened,需要 Day 24 的 Fingerprint 搭配 Base Revision Baseline 比較。

今天只使用精確名稱:

changed-line finding

不把它誤稱為新漏洞。

不能只用 Changed Files

假設 PR 修改:

src/main.js

而 Scanner 在同一個檔案的另一個舊 Function 找到 High Finding。

如果 Policy 只判斷:

changedFiles.includes(location.path)

這項既有問題會被誤認為本次變更造成。

所以 Day 26 需要解析 Unified Diff Hunk。

Git 指令使用:

git diff --unified=0 --no-color \
  "$BASE_SHA...$HEAD_SHA" \
  -- demo-app

--unified=0 讓輸出只保留真正新增或修改的行,減少 Context Line 對範圍判斷的干擾。

Hunk Header 類似:

@@ -6 +6 @@

表示新版本的第 6 行被修改。

Parser 會追蹤:

const hunk = line.match(
  /^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@/
);

並將 + 開頭的新行記錄為:

{
  "path": "demo-app/firestore.rules",
  "lines": [6]
}

刪除行不存在於 Head Revision,因此不能直接在新的 Source 上建立 Line Annotation。

若 Finding 只存在於已刪除程式碼,通常代表它應該在 Baseline 比較中變成 Resolved,而不是對不存在的行留下 Error。

實作 Diff Collector

專案新增:

demo-app/pr-review-demo/
├── collect-diff.js
├── diff.js
├── report.js
├── scenario.js
└── fixtures/
    ├── event.json
    └── pull-request.diff

diff.js 將 Unified Diff 轉成 Changed Line Map:

export function parseUnifiedDiff(diff) {
  const files = new Map();
  let currentPath;
  let newLine = 0;

  for (const line of diff.split("\n")) {
    if (line.startsWith("+++ ")) {
      // Record the new revision path.
    }

    const hunk = line.match(
      /^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@/
    );

    if (hunk) {
      newLine = Number(hunk[1]);
    }

    if (line.startsWith("+")) {
      files.get(currentPath).add(newLine);
      newLine += 1;
    } else if (!line.startsWith("-")) {
      newLine += 1;
    }
  }
}

正式 Workflow 傳入:

Base SHA
Head SHA
Pathspec
Output Path
node demo-app/pr-review-demo/collect-diff.js \
  --base "$BASE_SHA" \
  --head "$HEAD_SHA" \
  --path demo-app \
  --output demo-app/vibe-guard-pr-output/changed-lines.json

Base 與 Head 從 GitHub Event 取得,但不直接插入產生中的 Shell Script。

Workflow 先將它們放入 Environment Variable:

env:
  BASE_SHA: ${{ github.event.pull_request.base.sha }}
  HEAD_SHA: ${{ github.event.pull_request.head.sha }}

再使用:

"$BASE_SHA"
"$HEAD_SHA"

GitHub 的 Secure Use 文件建議,處理可能不可信的 Context Value 時,使用 Intermediate Environment Variable,而不是直接拼進 Inline Script。

PR Adapter 如何判斷 Blocking Finding?

Adapter 讀取三份資料:

vibe-guard-pr-output/findings-report.json
vibe-guard-pr-output/changed-lines.json
GITHUB_EVENT_PATH

第一份是 Day 25 CLI 產生的 Canonical Report。

第二份是本次 PR 的 Diff Scope。

第三份提供 PR Number、Base SHA 與 Head SHA。

每項 Finding 先轉成 Repository Path:

const repositoryPath =
  `demo-app/${location.path}`;

再判斷 Location 是否與 Changed Line 重疊:

const changed = [...lines].some(
  (line) =>
    line >= location.startLine &&
    line <= location.endLine
);

Blocking Rule 為:

const blocking =
  finding.verdict === "confirmed" &&
  scope === "changed-line" &&
  severityBlocks(finding.severity, "high");

注意 Policy 不會修改原 Finding。

AUTH-01 仍然是:

confirmed / open / high

PR Adapter 只額外記錄:

scope = changed-line
gate = block

Check Annotation 要由程式產生

GitHub Actions 支援 Workflow Command:

::error file=app.js,line=1::Message

它會在 Check 中建立與檔案、行號關聯的 Annotation。

Day 26 依結果選擇:

Finding Annotation
Blocking Confirmed Finding error
Requires Evidence warning
非阻擋 Confirmed Finding notice
Rejected Candidate 不建立 Source Annotation

AUTH-01 會產生概念上類似:

::error file=demo-app/firestore.rules,line=6,title=Vibe Guard AUTH-01::Any signed-in user can access another user's project

Annotation 內容可能包含:

百分比符號
換行
逗號
冒號
Repository 中的不可信文字

不能直接拼接。

Demo 先做 Workflow Command Escape:

function escapeWorkflowCommand(value) {
  return value
    .replaceAll("%", "%25")
    .replaceAll("\r", "%0D")
    .replaceAll("\n", "%0A")
    .replaceAll(":", "%3A")
    .replaceAll(",", "%2C");
}

更完整的產品可以使用 @actions/core 的 Annotation API,減少自行處理 Workflow Command Encoding。

無論使用哪種方式,都不能把模型或 Repository 產生的任意字串當成可信 Runner Command。

Job Summary 與 Annotation 解決不同問題

Annotation 適合回答:

哪個檔案、哪一行有問題?

Job Summary 適合回答:

這次掃描整體是否通過?
有哪些 Confirmed、Rejected 與 Requires Evidence?
哪些 Finding 位於本次 Diff?
缺少哪些正式環境證據?

Adapter 會把 Markdown 寫入:

vibe-guard-pr-output/pr-summary.md

若環境存在:

GITHUB_STEP_SUMMARY

也會將同一份內容附加到 GitHub Job Summary。

GitHub Actions 官方文件將 GITHUB_STEP_SUMMARY 定義為建立每個 Job 摘要的 Environment File。

因此不需要呼叫 GitHub API,也不需要給 Workflow pull-requests: write

這是今天刻意選擇的安全預設。

為什麼第一版不自動留言?

PR Comment 很方便,但它需要 Write Permission。

如果 Workflow:

  1. Checkout 不可信 PR 程式碼。
  2. 執行 Repository 中的 Script。
  3. 同時持有可寫入 Pull Request 的 Token。

惡意 PR 就可能修改 Script,竊取或濫用該 Token。

今天的 Workflow 使用:

permissions:
  contents: read

它只需要讀取 Checkout 的程式碼。

結果透過:

Check Status
Annotation
Job Summary
Artifact

回到 GitHub,不需要 PR Write Permission。

若未來一定要更新 Sticky Comment,可以拆成兩個 Workflow:

Untrusted Scan Workflow
  pull_request
  read-only token
  no secrets
  upload sanitized artifact

Trusted Publisher Workflow
  workflow_run
  write permission
  never checkout or execute PR code
  validate and sanitize downloaded artifact
  publish comment

workflow_run Artifact 仍是不可信輸入。

Publisher 只能解析固定 Schema、限制大小與文字內容,不能執行 Artifact 中的任何檔案。

絕對不要為了取得 Secrets 或 Write Permission,改用:

pull_request_target:

然後 Checkout 並執行 PR Head。

GitHub 的 Secure Use 文件明確提醒,pull_request_targetworkflow_run 若搭配不可信程式碼 Checkout,可能讓攻擊者取得 Repository Write Access 或 Secrets。

建立 GitHub Actions Workflow

Workflow 放在:

.github/workflows/vibe-guard-pr.yml

觸發條件:

on:
  pull_request:
    types: [opened, synchronize, reopened, ready_for_review]
    paths:
      - "demo-app/**"
      - ".github/workflows/vibe-guard-pr.yml"

synchronize 會在 PR 推送新 Commit 時重新執行。

ready_for_review 則讓 Draft PR 轉成正式 Review 時開始建立 Gate。

Job 另外排除仍在 Draft 的 PR:

if: github.event.pull_request.draft == false

這項選擇取決於團隊。

如果希望 Draft 階段就提早回饋,可以移除這個條件,但不把 Check 設為 Required。

避免同一個 PR 排隊執行舊 Revision

AI Review 與 Emulator Test 比一般 Lint 慢。

如果開發者連續推送三個 Commit,舊 Run 繼續執行通常沒有價值。

Workflow 加入:

concurrency:
  group: vibe-guard-${{ github.event.pull_request.number }}
  cancel-in-progress: true

同一個 PR 只保留最新 Run。

不同 PR 使用不同 Group,因此可以平行執行。

取消舊 Run 不應刪除已完成的歷史 Artifact,但進行中的舊 Revision 不再消耗 Runner 與 API Quota。

Checkout 需要完整 Diff 歷史

Diff Collector 要比較 Base 與 Head:

- name: Checkout pull request
  uses: actions/checkout@v6
  with:
    fetch-depth: 0

預設 Shallow Checkout 可能沒有 Base Commit。

fetch-depth: 0 取得完整歷史,讓:

git diff "$BASE_SHA...$HEAD_SHA"

可以穩定執行。

代價是大型 Repository Checkout 會變慢。

正式 Monorepo 可以改成只 Fetch 需要的 Base 與 Head,但必須處理 Merge Base 不存在或 Force Push 等情況。

第一版先使用較容易驗證的完整歷史。

依賴安裝必須可重現

Workflow 使用:

- name: Install dependencies
  working-directory: demo-app
  run: npm ci

不用:

npm install

npm ci 會依照 Lockfile 建立相依套件,且不修改 Manifest。

Node Version 也固定:

node-version: 24

這能降低:

本機與 CI Runtime 不一致
最新 Node 改變語意
Lockfile 被隱性更新

正式環境還應將第三方 Action Pin 到完整 Commit SHA。

GitHub 官方安全指南指出,完整 Commit SHA 是將 Action 固定為不可變版本的方式。

文章 Demo 使用 Major Tag 方便閱讀:

actions/checkout@v6
actions/setup-node@v6
actions/upload-artifact@v4

導入真實 Repository 前,應把經審查的版本換成完整 SHA,並使用 Dependabot 或 Renovate 管理更新。

保留 CLI Exit Code,但不要太早終止

Day 25 定義:

Exit Code 意義
0 Scan 完成,Local Policy 通過
1 Scan 完成,Finding Policy 不通過
2 Scan、Artifact 或 Schema 發生錯誤

如果 Workflow 直接執行:

- run: npm run vibe-guard -- scan .

遇到 Exit Code 1 時,後面的 Summary 與 Artifact Upload 可能不會執行。

開發者只看到紅色叉號,卻拿不到完整報告。

今天先捕捉 Exit Code:

set +e

npm run vibe-guard -- scan . \
  --output vibe-guard-pr-output \
  --format markdown \
  --fail-on high \
  --evidence-policy warn

code=$?
echo "exit_code=$code" >> "$GITHUB_OUTPUT"
exit 0

這不是吞掉失敗。

它只是延後裁決,讓 Workflow 還能:

建立 Annotation
寫入 Job Summary
上傳 Artifact
區分 Policy Fail 與 Execution Error

最後的 Enforce Step 才決定 Job 結果:

if [ "$SCAN_EXIT_CODE" = "2" ]; then
  exit 2
fi

if [ "$PR_GATE" = "fail" ]; then
  exit 1
fi

這裡再次保留:

Finding Fail != Tool Error

Artifact 即使失敗也要保存

Workflow 使用:

- name: Upload review artifacts
  if: always()
  uses: actions/upload-artifact@v4

if: always() 確保前面 Finding Gate 不通過時,仍會嘗試保存:

findings-report.json
summary.md
changed-lines.json
pr-summary.md
annotations.json

Artifact 設定:

retention-days: 14
if-no-files-found: warn

Retention 需要配合 Source Code 與安全報告的敏感度。

Artifact 可能包含:

Source Snippet
路徑
弱點描述
測試結果
部署證據缺口

不能因為它由 CI 產生,就假設適合永久保存或提供所有人下載。

GitHub Artifact 上傳也會產生 SHA-256 Digest;下載時可以驗證內容是否與上傳 Artifact 一致。

不過 Digest 只能證明傳輸後內容一致,不能證明 Artifact 本身是可信的。

執行 Day 26 本機 PR Fixture

在沒有實際 GitHub Repository 的情況下,Demo 使用一份 Pull Request Event 與 Unified Diff Fixture。

執行:

cd /media/mickey/777/ithome/demo-app
npm run pr-review:demo

Fixture 模擬兩項變更。

第一項將安全 Rules:

request.auth.uid == resource.data.ownerId

改成:

request.auth != null

第二項將 Owner-filtered Query 改成整個 Collection:

query(collection(db, "projects"))

PR Adapter 取得:

demo-app/firestore.rules:6
demo-app/src/main.js:143

因此 AUTH-01 的 Primary Location:

firestore.rules:6

會被判斷為:

changed-line

Demo 執行結果

實際 Summary:

# Vibe Guard Pull Request Review

- Pull request: #26
- Base: 1111111111111111111111111111111111111111
- Head: 2222222222222222222222222222222222222222
- Changed files: 2
- Gate: FAIL

| ID | Verdict | Severity | Diff scope | Gate | Location |
|---|---|---|---|---|---|
| AUTH-01 | confirmed | high | changed-line | BLOCK | firestore.rules:6 |
| SECRET-01 | rejected | - | global | report | - |
| RATE-01 | requires_evidence | - | global | report | - |

AUTH-01 同時滿足:

confirmed
high
changed-line

因此阻擋。

SECRET-01 是 Rejected Candidate,只保存於 Summary 與 Artifact,不建立修正警告。

RATE-01 沒有單一 Source Location,屬於 Global Evidence Gap。第一版 Policy 會顯示 Missing Evidence,但不把它錯誤定位到某一行。

Branch Protection 才會真正阻止合併

Workflow Failure 本身不一定阻止 Pull Request 合併。

Repository 還要在 Ruleset 或 Branch Protection 中,將:

Production readiness gate

設成 Required Status Check。

設定時要注意:

  • Check Name 必須穩定。
  • 不應依 Model 自由產生 Job Name。
  • Draft PR 是否要求 Check 要符合團隊流程。
  • Bot、Administrator 與 Emergency Merge 是否允許 Bypass。
  • Bypass 必須留下 Actor 與原因。

若 Check Name 經常修改:

Vibe Guard
Vibe Guard Review
Production Readiness

Branch Rule 可能仍等待已不存在的舊 Check,或新 Check 根本沒有被設為 Required。

今天固定 Job Name:

name: Production readiness gate

為什麼不只掃描 Diff?

只把 Unified Diff 交給 Agent 速度很快,但容易缺少:

被呼叫 Function
資料模型
Security Rules
既有 Mitigation
跨檔案 Data Flow
部署設定
測試

Day 21 已說明 Context 必須從 Rule 與架構反推。

所以今天的策略是:

完整 Repository 用於分析與驗證
Pull Request Diff 用於 Scope 與 Gate Policy

這兩者不能交換。

Repository Context 回答:

Finding 是否成立?

Diff Scope 回答:

這項 Finding 與本次變更的關係是什麼?

如果只掃 Diff,AUTH-01 可能只看到:

request.auth != null

卻沒有看到 ownerId、Client Query 與雙帳號測試。

如果完全忽略 Diff,則任何無關 PR 都可能被既有問題阻擋。

PR Comment、Annotation、SARIF 要選哪一個?

三者用途不同。

Channel 適合內容
Job Summary 本次 Run、Gate、統計、Evidence Gap
Check Annotation 與檔案及行號直接相關的少量高信號結果
PR Comment 需要對話、狀態更新或無 Source Location 的摘要
SARIF / Code Scanning 跨 Run 的 Alert、Fingerprint、Baseline 與安全工作流
Artifact 完整 Canonical Report、驗證紀錄與除錯資料

第一版使用 Summary、Annotation 與 Artifact。

Day 24 已建立 Fingerprint,因此後續可以新增 SARIF Exporter,再使用:

github/codeql-action/upload-sarif

將第三方掃描結果匯入 GitHub Code Scanning。

GitHub 文件指出,SARIF 可以透過 partialFingerprints 減少重複 Alert;多份分析則應使用不同 Category。

但 SARIF Upload 需要 security-events: write,私人 Repository 也需要啟用對應的 GitHub Code Security 功能。

在完成 SARIF Schema Mapping 以前,不應把不完整 JSON 改名成 .sarif 上傳。

PR Workflow 的安全邊界

這個 Workflow 會執行 Pull Request 中的:

package.json Script
JavaScript Scanner
Firebase Test
相依套件程式碼

所以應把整個 Job 視為執行不可信程式碼。

今天採用:

  1. pull_request Trigger。
  2. contents: read 的最小 Token 權限。
  3. 不提供 Repository Secret。
  4. 不自動部署。
  5. 不寫入 PR Comment。
  6. 不使用 pull_request_target Checkout PR Head。
  7. 設定 15 分鐘 Timeout。
  8. Artifact 有限期保存。

正式 Agent 若需要 GEMINI_API_KEY,Fork PR 會遇到另一個問題:

不應把 API Secret 暴露給不可信 Fork。

可選策略包括:

  • Fork PR 只執行不需要 Secret 的 Deterministic Checks。
  • 維護者核准後才執行需要 Secret 的 Environment Job。
  • 將模型呼叫移到隔離服務,使用短期、最小權限 Token。
  • 對外部貢獻者使用不同的低權限 Review Pipeline。

不能因為 AI Scan 需要 Credential,就把長期 API Key 直接開放給所有 PR。

避免 Annotation 變成新的噪音

如果一個 PR 產生 200 個 Annotation,Reviewer 很可能不再閱讀。

第一版可以設定:

最多 10 個 Error Annotation
最多 20 個 Warning
其餘只放 Job Summary 與 Artifact

排序依據:

Blocking
Severity
Confidence
Diff Proximity
Impact

同一 Root Cause 的多個 Location 也應合併。

例如同一條 Firestore Rule 造成十個 Query 都能越權,不應在每個 Client Call Site 留下一模一樣的 High Annotation。

Primary Location 可以指向授權 Root Cause:

firestore.rules:6

其他 Data Flow 放在 Finding Detail 與 Artifact。

今天 Demo 只有一個 Blocking Annotation,因此尚未實作上限,但正式版本必須加入。

重新執行與舊 Comment 問題

PR 每次 Push 都會重新執行。

如果每次都建立新的 Comment:

Vibe Guard Result 1
Vibe Guard Result 2
Vibe Guard Result 3

Conversation 很快會被 Bot 洗版。

Job Summary 不會有這個問題,因為每個 Workflow Run 有自己的摘要。

若未來加入 Comment,應使用 Marker 更新同一則 Sticky Comment:

<!-- vibe-guard-pr-summary -->

並保存:

Run ID
Head SHA
更新時間
Gate
Artifact Link

Publisher 必須確認 Comment 對應目前 Head SHA,避免舊 Run 在較晚完成後覆蓋新結果。

今天的 concurrency.cancel-in-progress 已先降低這種 Race Condition。

第一版還缺少什麼?

今天完成的是可重現的 PR Gate 與安全的唯讀回報。

正式版本還需要:

  • 比較 Base 與 Head 的 Fingerprint,判斷 New、Unchanged、Resolved、Reopened。
  • 處理 Rename、Copy、Submodule、Symlink 與 Binary Diff。
  • 對 Monorepo 只執行受影響的 Rule Pack 與 Test Fixture。
  • 限制 Annotation 數量並合併 Root Cause。
  • 為 Fork PR 設計不需要 Secret 的掃描模式。
  • 將第三方 Action Pin 到完整 Commit SHA。
  • 產生 SARIF 並上傳 Code Scanning。
  • 將 Requires Evidence 指派給 Platform、Security 或 SRE Owner。
  • 保存 Commit SHA、Rule Digest、Prompt Version 與 Tool Image。
  • 在 Workflow Cancel 或 Timeout 時仍保存部分執行狀態。
  • 對 Scanner 自身的修改要求 CODEOWNERS Review。
  • .github/workflows/** 啟用 CodeQL 或其他 Workflow Security Scan。
  • 對 Self-hosted Runner 建立隔離、清理與網路限制。

目前 Demo 會執行完整 Repository Scan,再以 Diff Scope 決定 Gate。

當 Repository 變大後,可以先用 Diff 找出受影響元件,再由 Context Selector 向外擴張必要依賴,而不是永遠全量掃描。

但不能只保留 Diff,否則會回到缺少跨檔案 Context 的問題。

今天的結論

把 Agent 放進 Pull Request,不只是新增一份 YAML。

一個可信的 PR Review Workflow 至少要定義:

  1. 使用哪個 Event,如何處理 Fork 與 Secret。
  2. Checkout 的 Revision 與 Diff Base 是什麼。
  3. 本機 CLI 與 CI 是否共用相同 Scanner、Schema 與 Policy。
  4. Finding 如何映射到 Changed Line、Changed File、Existing 與 Global。
  5. 哪些 Verdict、Severity 與 Scope 會阻擋。
  6. Policy Fail 與 Execution Error 如何分開。
  7. 如何在失敗時仍保存 Summary 與 Artifact。
  8. Annotation 中的不可信文字如何 Escape。
  9. Token 與第三方 Action 使用哪些最小權限。
  10. Branch Protection 如何把 Check 變成真正的 Merge Gate。

今天建立:

.github/workflows/vibe-guard-pr.yml
demo-app/pr-review-demo/

本機 Fixture 模擬 PR 將 Owner Check 改成:

request.auth != null

Vibe Guard 重新執行完整的對抗驗證後,確認:

AUTH-01
confirmed / high / changed-line

因此建立 Error Annotation,並讓:

Production readiness gate

失敗。

被拒絕的 SECRET-01 與缺少部署證據的 RATE-01 仍保留在 Summary,但不會被改寫成這次 PR 的新 High Finding。

這讓 Vibe Guard 從開發者主動執行的工具,進一步成為每次變更都會經過的自動化上線守門員。

明天,我們會替 AI 稽核建立正式考試:使用標註資料集計算檢出率、誤報率與漏報率,而不是只展示幾個成功案例。

參考資料


上一篇
Day 25|把 Agent 放進 Terminal:一行指令檢查本機專案
下一篇
Day 27|替 AI 稽核做考試:計算檢出率、誤報率與漏報率
系列文
從 Vibe Coding 到 Production:用 Google AI 打造上線守門員30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言