Một AI agent chạy trong phiên chat của bạn và một AI agent chạy tự động trong pipeline (chuỗi bước build, test, deploy được tự động hoá) CI/CD là hai sinh vật rất khác nhau. Trong chat, bạn ngồi đó, nhắc lại context khi cần, sửa hướng đi ngay khi thấy sai. Trong CI, không có ai ngồi cạnh — agent tự khởi động, tự đọc code, tự quyết định test gì, và tự báo cáo kết quả, tất cả trong vài phút, không có con người can thiệp giữa chừng. Nếu agent đó không có đủ persistent context (ngữ cảnh bền vững) về hệ thống, về quy ước test, về mức độ rủi ro của từng module, nó sẽ hành xử như một tân binh mới vào công ty ngày đầu tiên — mỗi lần chạy lại phải "học lại từ đầu", và tệ hơn, nó không biết mình đang thiếu gì để mà hỏi. Bài này đi vào chi tiết cách xây dựng ba lớp context bền vững — CLAUDE.md tối ưu cho CI, các context file bổ sung, và repo map (bản đồ định hướng agent tới đúng vị trí trong codebase) — rồi nối chúng vào GitHub Actions để agent tự trigger (kích hoạt chạy) đúng lúc, và cuối cùng là một mô hình phân cấp để con người review output của agent một cách có kỷ luật, không bị ngập trong noise nhưng cũng không bỏ lọt rủi ro thật.
Persistent Context Là Gì và Vì Sao Nó Quan Trọng với Autonomous QA Agent trong CI/CD?
Persistent context là tập hợp thông tin về hệ thống, quy ước, và lịch sử QA được lưu trữ trong repo, tồn tại độc lập với bất kỳ phiên chạy agent cụ thể nào, và được tự động nạp lại mỗi khi agent khởi động. Nó khác hoàn toàn với việc bạn dán một đoạn hướng dẫn dài vào prompt mỗi lần chạy — vì persistent context sống ở file, được version control, được review qua pull request (hay PR, yêu cầu hợp nhất code) như code, và được tái sử dụng qua hàng trăm lượt chạy agent mà không ai phải nhớ để copy-paste lại.
Với một agent chạy trong chat session của con người, thiếu context không phải vấn đề chí mạng — con người ở đó để bù đắp, để nói "không, hệ thống này dùng optimistic locking, đừng giả định pessimistic". Nhưng một agent tự động trong CI không có ai để hỏi giữa lúc chạy. Nếu nó không biết rằng module thanh toán có risk weight (trọng số rủi ro) cao nhất trong hệ thống, nó có thể dành 80% thời gian test một trang settings ít quan trọng và chỉ lướt qua checkout. Nếu nó không biết quy ước đặt tên selector (bộ chọn dùng để định vị phần tử trên UI) của team là data-testid, nó có thể tự chế ra XPath dễ vỡ, chỉ tồn tại được một lần chạy. Persistent context chính là thứ biến agent CI từ "một con bot chạy script ngẫu nhiên" thành "một QA engineer ảo đã được onboard đầy đủ".
Sự Khác Biệt Giữa Session Context và Persistent Context
Session context (ngữ cảnh phiên) là tất cả những gì bạn gõ vào cửa sổ chat trong một lượt làm việc — nó biến mất khi phiên kết thúc, hoặc bị cắt bớt khi vượt quá context window (giới hạn dung lượng ngữ cảnh agent có thể đọc cùng lúc). Persistent context là tập file sống trong repo, được agent tự đọc lại từ đầu ở mỗi lần chạy mới, không phụ thuộc vào lịch sử chat trước đó.
Sự khác biệt này quan trọng vì ba lý do thực tế:
- Tính lặp lại (reproducibility) — Agent chạy trên PR #482 hôm nay phải có cùng hiểu biết nền tảng với agent chạy trên PR #501 tuần sau. Nếu context chỉ tồn tại trong đầu người viết prompt, mỗi lần chạy sẽ khác nhau một cách không kiểm soát được.
- Khả năng audit — Khi agent đưa ra một quyết định QA sai (ví dụ bỏ qua một luồng rủi ro cao), bạn cần trace được: agent đã "biết" gì tại thời điểm đó? Nếu context nằm trong file version control, bạn xem lại được chính xác phiên bản context ở commit đó.
- Khả năng cải tiến tăng dần — Mỗi lần agent bỏ sót thứ gì đó vì thiếu thông tin, bạn sửa một lần trong context file, và tất cả các lần chạy sau đều được hưởng lợi. Không có persistent context, bạn phải sửa lời nhắc trong đầu mỗi người viết prompt, tức là không sửa được gì cả về lâu dài.
Một cách nghĩ khác: session context là trí nhớ ngắn hạn, persistent context là "hồ sơ nhân viên" đã được viết ra giấy. Agent CI không có trí nhớ ngắn hạn nào để mang từ lần chạy này sang lần chạy khác — nó chỉ có thể "nhớ" thông qua những gì bạn ghi lại thành file.
Mẹo: Đừng coi persistent context là tài liệu viết một lần rồi để đó. Hãy coi mỗi lần agent hành xử sai trong CI là một tín hiệu cho biết context file đang thiếu gì — và sửa ngay trong PR đó, giống như sửa một bug production.
Làm Thế Nào Để Thiết Lập CLAUDE.md, Context Files và Repo Map cho CI Agent?
Có ba lớp context bổ sung cho nhau, mỗi lớp phục vụ một mục đích khác nhau. Nhầm lẫn phổ biến nhất là nhồi tất cả vào một file CLAUDE.md khổng lồ — điều này khiến agent phải đọc quá nhiều thông tin không liên quan mỗi lần chạy, làm loãng context window và tăng chi phí token một cách vô ích.
Lớp 1: CLAUDE.md Tối Ưu cho CI
CLAUDE.md dùng cho agent tương tác trong IDE thường tập trung vào coding convention. CLAUDE.md tối ưu cho QA agent chạy trong CI cần khác biệt: nó phải trả lời được câu hỏi "agent này cần biết gì để tự quyết định test cái gì, test bằng cách nào, và báo cáo theo format nào" — mà không cần ai giải thích thêm.
Dưới đây là một CLAUDE.md mẫu, cấu trúc theo các phần mà một CI QA agent thực sự cần:
## Environment: CI/CD
This file is read by the autonomous QA agent running inside GitHub Actions.
Do not assume an interactive human is present. Never wait for confirmation —
if a decision is ambiguous, flag it in the report instead of guessing silently.
## Test Stack
- E2E: Playwright (TypeScript), config at playwright.config.ts
- API: Vitest + supertest, tests under tests/api/**
- Component: React Testing Library
- Test runner in CI: `npm run test:ci` (never `npm test` — different reporters)
## Test File Conventions
- E2E specs: tests/e2e/**/*.spec.ts, one file per user flow, not per page
- API specs: tests/api/**/*.spec.ts, named after the endpoint under test
- Naming: `should_<expected behavior>_when_<condition>`
- Every new spec file MUST import fixtures from tests/e2e/fixtures/base.ts
## Selector Strategy
- Primary: data-testid attributes only (e.g., [data-testid="checkout-submit"])
- NEVER use text-based selectors for i18n'd UI (see /locales — 6 languages live)
- NEVER use nth-child or CSS class selectors — they break on every redesign
- If a data-testid is missing on an element you need to test, flag it in the
report as "missing test hook" — do not invent an XPath workaround
## Domain Model (QA-critical entities)
- Order: has states [draft, pending_payment, paid, fulfilled, cancelled, refunded]
- Cart: session-scoped, expires after 45 min of inactivity
- User: guest vs registered vs wholesale (wholesale has different pricing rules)
- Inventory: oversell is possible by design during flash sales — not a bug
## Risk Weights (for test planning)
- checkout/payment/*: CRITICAL — any change here requires full regression
- pricing/discount-engine/*: HIGH — history of silent rounding bugs
- account/profile/*: MEDIUM
- marketing/banners/*: LOW — visual-only, cosmetic regressions acceptable
## Historical QA Context
- Known flaky area: tests/e2e/checkout/express-pay.spec.ts (3rd-party sandbox
latency) — retry twice before flagging as a real failure
- Past incident: discount stacking bug shipped in v2.14 due to missing test
for "two active coupons on one order" — always include this case for any
discount-engine change
- Do not re-report already-tracked flaky tests as new findings; check
qa-context/known-flaky.md first
## Output Conventions for CI Reports
- Post a single PR comment, not one comment per finding
- Structure: Summary → Risk-ranked findings → Coverage delta → Open questions
- Tag every finding with a Tier (see qa-context/review-tiers.md)
- Never say "all tests pass, ship it" — QA agent recommends, does not approve
## What NOT to Do
- Do not modify test files outside the PR's diff scope
- Do not auto-merge, auto-approve, or dismiss review comments
- Do not disable or skip a failing test to make the suite pass
- Do not invent acceptance criteria not present in the linked ticket
Điểm mấu chốt của file này không phải là độ dài, mà là mỗi phần trả lời một câu hỏi cụ thể mà agent chắc chắn sẽ cần khi tự lên kế hoạch test. Phần "Risk Weights" đặc biệt quan trọng và hay bị bỏ quên nhất — thiếu nó, agent coi mọi thay đổi code là "quan trọng bằng nhau", dẫn đến việc dồn effort sai chỗ (test kỹ trang banner marketing, lướt qua module thanh toán). Phần "What NOT to Do" cũng quan trọng không kém phần hướng dẫn tích cực — nó giới hạn autonomy (quyền tự quyết) của agent ở đúng ranh giới an toàn.
Lớp 2: Context Files Bổ Sung
CLAUDE.md nên giữ ngắn và tổng quát; chi tiết cụ thể theo từng khu vực chức năng nên tách ra file riêng, để agent chỉ nạp phần liên quan khi cần, và để con người dễ maintain từng phần độc lập. Một loại context file bổ sung rất giá trị cho QA agent là "Page Object Catalog" — tài liệu hoá các Page Object (lớp đại diện cho một trang/màn hình trong test, theo mô hình Page Object Model) đã tồn tại, tránh việc agent tạo trùng lặp hoặc bỏ qua abstraction sẵn có.
Ví dụ file qa-context/page-object-catalog.md:
## CheckoutPage
Location: tests/e2e/pages/CheckoutPage.ts
Covers: /checkout, /checkout/payment, /checkout/confirm
Key methods:
- fillShippingAddress(address: Address)
- selectPaymentMethod(method: 'card' | 'paypal' | 'express')
- submitOrder(): Promise<OrderConfirmation>
Known limitations: does not yet support gift-card redemption flow —
if testing gift cards, interact with selectors directly and flag this
gap in the report instead of extending this class silently.
## CartPage
Location: tests/e2e/pages/CartPage.ts
Covers: /cart
Key methods:
- addItem(sku: string, qty: number)
- applyCoupon(code: string): Promise<CouponResult>
Note: applyCoupon does NOT wait for the discount recalculation
animation — always await page.waitForSelector('[data-testid="cart-total-updated"]')
after calling it, or assertions will read stale totals.
## AccountSettingsPage
Location: tests/e2e/pages/AccountSettingsPage.ts
Covers: /account/settings
Status: DEPRECATED — being replaced by AccountSettingsV2Page
(tests/e2e/pages/AccountSettingsV2Page.ts). Do not extend the old class;
new tests must use V2.
Catalog dạng này giải quyết một vấn đề rất cụ thể: nếu không có nó, agent (hoặc cả con người mới vào team) thường viết Page Object trùng lặp, hoặc quan trọng hơn — bỏ lỡ những "cạm bẫy" đã biết như dòng ghi chú về applyCoupon phía trên. Không có ghi chú đó, agent rất dễ viết test bị flaky (test chạy lúc pass lúc fail do timing, không phải do bug thật) vì đọc giá trị total trước khi UI cập nhật xong, rồi báo cáo sai một "bug" không tồn tại.
Các context file bổ sung khác nên xem xét thêm: danh sách API mock/stub đã có sẵn cho môi trường CI, bảng ánh xạ feature flag đang bật/tắt theo môi trường test, và một file ghi lại các quyết định thiết kế test có chủ đích trông giống bug (ví dụ hành vi oversell trong flash sale đã nêu ở CLAUDE.md) để agent không báo cáo nhầm.
Lớp 3: Repo Map
Repo map là bản đồ định hướng agent tới đúng vị trí trong codebase mà không cần quét toàn bộ repo mỗi lần chạy — điều này vừa tiết kiệm token, vừa giảm khả năng agent "khám phá nhầm" vào những phần code không liên quan tới QA.
Ví dụ qa-context/repo-map.md:
## Source Files of Interest for QA
- apps/storefront/src/features/checkout/ — checkout business logic
- apps/storefront/src/features/pricing/ — discount/pricing engine
- packages/shared-domain/src/order.ts — Order state machine (source of truth)
- apps/api/src/routes/orders/ — order-related REST endpoints
## Test Infrastructure
- tests/e2e/ — Playwright specs, run in CI via test:ci
- tests/api/ — API contract tests
- tests/fixtures/seed-data/ — DB seed scripts used before each CI test run
- docker-compose.qa.yml — spins up isolated test DB + mock payment gateway
## QA Artifacts Location
- qa-context/known-flaky.md — tracked flaky tests, do not re-report
- qa-context/review-tiers.md — output tiering rules (see below)
- qa-reports/ — historical agent-generated reports, one
per PR, named pr-<number>-<date>.md
## CI/CD Configuration
- .github/workflows/agentic-qa-pr.yml — runs on every PR
- .github/workflows/agentic-qa-feature-branch.yml — nightly, longer cycle
- Secrets required: QA_AGENT_API_KEY, MOCK_PAYMENT_GATEWAY_URL
Repo map khác context file bổ sung ở điểm: nó không mô tả quy ước, mà mô tả địa lý — nơi mọi thứ nằm. Với một monorepo lớn, đây là thứ giúp agent tránh lãng phí một lượt gọi tool chỉ để dò tìm file, và quan trọng hơn, tránh agent vô tình sửa nhầm file thuộc một service hoàn toàn không liên quan tới PR đang được review.
Cấu Hình Auto-Loading Context trong CI
Ba lớp context trên chỉ có giá trị nếu agent thực sự đọc chúng ở mỗi lần chạy, một cách tự động, không cần ai remind bằng tay trong prompt. Cách làm phổ biến là để step đầu tiên của workflow (quy trình các job tự động chạy trong CI, ví dụ một GitHub Actions workflow) tổng hợp các context file này thành một payload cố định, gắn kèm vào lệnh gọi agent.
name: Agentic QA on PR
on:
pull_request:
types: [opened, synchronize, ready_for_review]
jobs:
agentic-qa:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Assemble persistent context
run: |
cat CLAUDE.md \
qa-context/repo-map.md \
qa-context/page-object-catalog.md \
qa-context/known-flaky.md \
qa-context/review-tiers.md \
> /tmp/qa-agent-context.md
- name: Run QA agent
uses: anthropic/claude-code-action@v1
with:
context-file: /tmp/qa-agent-context.md
diff-scope: pull-request
prompt: |
Review the diff in this PR using the attached persistent
context. Produce a risk-ranked QA report following the
Output Conventions section of CLAUDE.md.
Điều quan trọng ở đây không phải cú pháp YAML cụ thể (mỗi công cụ agent có cách nạp context khác nhau), mà là nguyên tắc: việc lắp ghép context phải là một bước tường minh, nằm trong workflow, chứ không phải phụ thuộc vào việc ai đó nhớ dán đúng file vào đúng lúc. Nếu context file bị đổi tên hoặc di chuyển mà không cập nhật bước này, agent sẽ chạy với context rỗng hoặc thiếu mà không ai biết — đây là lỗi âm thầm nguy hiểm nhất của mô hình này.
Mẹo: Thêm một bước kiểm tra "context freshness" ngay đầu workflow — fail sớm (fail-fast) nếu bất kỳ file context nào không tồn tại hoặc rỗng, thay vì để agent chạy im lặng với context thiếu và tạo ra báo cáo trông có vẻ hợp lý nhưng thực chất sai lệch.
Làm Thế Nào Để Tự Động Trigger Agentic QA Run trên Pull Request và Feature Branch?
Context bền vững chỉ phát huy giá trị khi nó được nạp đúng lúc, đúng phạm vi. Hai kiểu trigger phổ biến nhất — theo PR và theo feature branch — phục vụ hai mục đích khác nhau, và nhầm lẫn chúng là nguyên nhân phổ biến khiến agent chạy quá lâu trên PR nhỏ, hoặc chạy quá sơ sài trên thay đổi lớn.
Cấu Hình Trigger theo PR
Trigger theo PR nên tối ưu cho tốc độ phản hồi — QA agent cần trả kết quả trong vài phút, tập trung đúng vào diff của PR, không chạy full regression toàn hệ thống mỗi lần push. Đây là nơi risk weight trong CLAUDE.md phát huy tác dụng: agent dùng nó để quyết định độ sâu kiểm tra tương ứng với vùng code bị ảnh hưởng.
name: Agentic QA on PR
on:
pull_request:
types: [opened, synchronize, ready_for_review]
paths-ignore:
- '**.md'
- 'docs/**'
concurrency:
group: agentic-qa-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
agentic-qa:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Determine changed risk areas
id: risk
run: |
git diff --name-only origin/${{ github.base_ref }}...HEAD \
> /tmp/changed-files.txt
- name: Run scoped QA agent
uses: anthropic/claude-code-action@v1
with:
context-file-list: |
CLAUDE.md
qa-context/repo-map.md
qa-context/page-object-catalog.md
changed-files: /tmp/changed-files.txt
prompt: |
Scope your test plan to the changed files only. Cross-reference
Risk Weights in CLAUDE.md — if any changed file falls under a
CRITICAL area, expand scope to include its direct dependents.
Ba chi tiết đáng chú ý: concurrency với cancel-in-progress: true để tránh chồng chất chạy agent khi có nhiều push liên tiếp trong thời gian ngắn (tốn tiền API và làm nhiễu PR với nhiều comment); timeout-minutes để chặn agent "đi lang thang" quá lâu khi gặp context mơ hồ; và bước xác định file thay đổi để giới hạn phạm vi rõ ràng ngay từ đầu, thay vì để agent tự quyết định phạm vi (dễ dẫn tới việc agent tự mở rộng hoặc thu hẹp phạm vi quá tay).
Trigger theo Feature Branch cho Chu Kỳ QA Dài Hơn
Feature branch — nhánh sống lâu hơn PR đơn lẻ, tích lũy nhiều commit qua nhiều ngày/tuần — cần một chu kỳ QA khác: chạy sâu hơn, ít thường xuyên hơn, và không chặn tốc độ merge của các PR nhỏ vào nhánh đó. Thường cấu hình theo lịch (schedule) hoặc theo trigger thủ công, không theo mỗi lần push.
name: Agentic QA — Feature Branch Deep Cycle
on:
schedule:
- cron: '0 2 * * *' # nightly, 02:00 UTC
workflow_dispatch:
inputs:
branch:
description: 'Feature branch to run deep QA against'
required: true
jobs:
deep-agentic-qa:
runs-on: ubuntu-latest
timeout-minutes: 90
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.inputs.branch || 'feature/loyalty-program' }}
fetch-depth: 0
- name: Run full-context deep QA agent
uses: anthropic/claude-code-action@v1
with:
context-file-list: |
CLAUDE.md
qa-context/repo-map.md
qa-context/page-object-catalog.md
qa-context/known-flaky.md
qa-context/review-tiers.md
prompt: |
Run a deep QA pass against the accumulated diff between this
branch and main. Include exploratory scenarios beyond the
explicit diff — reason about integration points across the
entire changed feature, not just line-level changes. Produce
a full report including regression risk on adjacent features.
Sự khác biệt cốt lõi so với trigger PR: chu kỳ này được cho phép "suy luận rộng hơn" (đi ra ngoài diff line-level để xét integration point), và được cấp thời gian dài hơn (timeout-minutes: 90) vì nó không nằm trên đường merge tức thời của bất kỳ ai. Đây cũng là chu kỳ phù hợp để chạy các bài exploratory testing tốn thời gian đã học ở bài trước của module.
Mẹo: Đừng dùng cùng một bộ context file cho cả hai loại trigger mà không cân nhắc — trigger PR nên loại bỏ known-flaky.md và review-tiers.md nếu chúng không ảnh hưởng tới quyết định phạm vi nhanh, để giảm token và tăng tốc; trigger feature branch nên nạp đầy đủ vì có ngân sách thời gian rộng hơn.
Làm Thế Nào Để Review và Hành Động trên Output của Autonomous Agent Xuất Hiện trong CI?
Cho agent quyền tự động chạy trong CI mà không có mô hình review rõ ràng là công thức cho hai thất bại đối lập: hoặc con người bị ngập trong hàng chục comment agent trên mỗi PR (dẫn đến việc bỏ qua tất cả, kể cả cái quan trọng), hoặc con người tin tưởng agent quá mức và bỏ qua review hoàn toàn (dẫn đến rủi ro thật lọt qua). Giải pháp là phân tầng output theo mức độ cần can thiệp của con người.
Mô Hình Review Output Ba Cấp (Three-Tier)
Không phải mọi output của agent đều cần cùng một mức độ chú ý. Chia thành 3 tier, ghi rõ tiêu chí trong qa-context/review-tiers.md để agent tự gắn tag đúng khi tạo báo cáo:
- Tier 1 — Thông tin (Informational). Agent tự tin cao, phát hiện không ảnh hưởng luồng chính (ví dụ: thiếu
data-testidtrên một element phụ, coverage delta tăng nhẹ). Không cần hành động ngay; có thể xem theo lô cuối tuần. - Tier 2 — Cần xác nhận (Needs confirmation). Agent phát hiện điều gì đó có khả năng là vấn đề thật nhưng độ tin cậy trung bình, hoặc nằm ở vùng risk weight MEDIUM (ví dụ: một negative-path case agent nghi ngờ chưa được test, nhưng chưa chắc chắn 100%). Một QA hoặc dev cần đọc và xác nhận trong ngày, không cần chặn merge ngay lập tức.
- Tier 3 — Chặn (Blocking). Agent phát hiện vấn đề trong vùng risk weight CRITICAL/HIGH, hoặc phát hiện hành vi khác biệt rõ ràng với acceptance criteria đã nêu trong ticket liên kết. Đây là tier duy nhất có quyền gắn nhãn "changes requested" hoặc chặn merge tự động — và luôn cần một con người ra quyết định Go/No-Go tường minh trước khi merge.
Việc phân tier phải do chính agent tự gán dựa trên tiêu chí viết sẵn (không để con người tự đoán agent nghĩ gì), và tiêu chí đó phải nằm trong context file — nghĩa là nó cũng là một dạng persistent context, không phải quy tắc bất biến trong đầu người review.
Quy Trình Review cho Output Cấp 3 (Tier 3)
Vì Tier 3 là tier duy nhất có khả năng chặn merge, quy trình review nó cần rõ ràng và nhất quán, không phải tùy hứng theo người review hôm đó rảnh hay bận:
- Đọc report gốc trước khi đọc code. Report của agent nêu rõ vì sao nó coi đây là Tier 3 — luôn đọc lý do trước, tránh xu hướng tự đi kiểm tra code theo cách của riêng mình rồi bỏ lỡ đúng điểm agent đang cảnh báo.
- Verify thủ công tối thiểu một case đại diện. Không merge dựa hoàn toàn vào lời agent nói "sẽ lỗi" — tự chạy lại (hoặc yêu cầu agent trích log/screenshot) ít nhất một trường hợp cụ thể nhất trong danh sách phát hiện. Bước này không phải để "kiểm tra agent có lười không" mà để bắt đúng loại lỗi agent có xu hướng mắc — suy luận sai về ý định nghiệp vụ, vì agent chỉ thấy code, không thấy quyết định nghiệp vụ ngoài code.
- Phân loại nguyên nhân gốc. Vấn đề Tier 3 có ba khả năng: (a) bug thật trong code PR, (b) hiểu sai của agent do context thiếu/lỗi thời, (c) hành vi cố ý nhưng chưa được ghi vào context (giống case oversell trong ví dụ CLAUDE.md ở trên). Nếu là (b) hoặc (c), việc sửa quan trọng không kém sửa bug — cập nhật ngay context file liên quan trong cùng PR hoặc PR theo dõi riêng.
- Ra quyết định Go/No-Go tường minh, ghi lại bằng template cố định (xem phần sau), không chỉ react bằng emoji hay một câu ngắn trên PR.
Mẫu Phản Hồi Go/No-Go
Một template cố định giúp quyết định Go/No-Go có cấu trúc, dễ tra lại sau này, và buộc người review phải trả lời đủ các câu hỏi quan trọng thay vì chỉ gõ "LGTM":
## QA Review Response — PR #482
**Agent Report Reference:** qa-reports/pr-482-2026-07-09.md
**Tier of finding(s) reviewed:** Tier 3
**Reviewer:** dat.hoang@youthdev.net
### Findings Assessed
1. [CRITICAL] Discount stacking not validated for two active coupons
- Verified manually: YES — reproduced with coupon codes SUMMER10 + WELCOME5
- Root cause: (x) Real bug ( ) Agent misunderstanding ( ) Context gap
- Action: Blocking — requires fix before merge
### Decision: NO-GO
**Reasoning:** Confirmed discount-stacking bug matches the historical
incident pattern already logged in CLAUDE.md (v2.14 discount bug). Same
class of defect, same root cause (missing combined-coupon validation).
### Follow-up Actions
- [ ] Fix required in apps/storefront/src/features/pricing/coupon-stack.ts
- [ ] Add regression test: tests/api/pricing/coupon-stacking.spec.ts
- [ ] No context file update needed — existing Historical QA Context entry
was accurate and correctly triggered this finding
### Context Feedback Loop
Did this review surface a persistent-context gap? NO
(If YES, link the PR that updates CLAUDE.md / repo-map.md / page-object-catalog.md)
Phần "Context Feedback Loop" ở cuối template là chi tiết dễ bị bỏ qua nhất nhưng lại quan trọng nhất về lâu dài: nó biến mỗi lần review thành một cơ hội cải thiện persistent context, khép lại đúng vòng lặp đã nói ở đầu bài — context không phải viết một lần rồi để nguyên, mà là tài sản sống, được nuôi dưỡng qua từng lượt agent chạy sai hoặc chạy đúng.
Mẹo: Lưu tất cả file Go/No-Go response vào cùng thư mục với report gốc (qa-reports/) theo cùng quy ước tên file — sau vài tháng, đây trở thành một "sổ tay lịch sử quyết định QA" có thể dùng để huấn luyện lại prompt hoặc chứng minh cho audit rằng mọi merge rủi ro cao đều có người ký duyệt tường minh, không phải agent tự động approve.