@htechcs/harness-kit 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,43 +1,44 @@
1
- # Subagents — quy tắc viết đúng (Mức 2)
1
+ # Subagents — how to write a good one (Level 2)
2
2
 
3
- Subagent **đòn bẩy chính của Mức 2**: đẩy việc nặng (đọc nhiều file, refactor lớn,
4
- chạy thử lặp) sang một **context riêng**, để context chính chỉ nhận *kết luận* — không bị ngập.
3
+ A subagent is **Level 2's main lever**: push heavy work (reading many files, big refactors,
4
+ repeated test runs) into a **separate context**, so the main context receives only *conclusions*
5
+ it doesn't flood.
5
6
 
6
- ## Cài đặt
7
+ ## Install
7
8
 
8
- Mỗi subagent một file `.md` trong `.claude/agents/` (cấp repo) hoặc `~/.claude/agents/` (cấp user).
9
- Copy file mẫu vào đó Claude Code tự nhận:
9
+ Each subagent is a `.md` file in `.claude/agents/` (repo-level) or `~/.claude/agents/` (user-level).
10
+ Copy the sample file there and Claude Code picks it up automatically:
10
11
 
11
12
  ```bash
12
13
  mkdir -p .claude/agents
13
14
  cp repo-explorer.md .claude/agents/
14
15
  ```
15
16
 
16
- ## Cấu trúc file
17
+ ## File structure
17
18
 
18
19
  ```md
19
20
  ---
20
21
  name: <kebab-case>
21
- description: <KHI NÀO dùng — Claude đọc dòng này để tự quyết gọi agent này không>
22
- tools: Read, Grep, Glob # (tuỳ chọn) chỉ trang bị tool agent CẦN, để gọn
22
+ description: <WHEN to use it — Claude reads this line to decide whether to call this agent>
23
+ tools: Read, Grep, Glob # (optional) give it only the tools it NEEDS, to keep it focused
23
24
  ---
24
- <system prompt: vai trò + cách làm + ĐẶC BIỆT cách TRẢ VỀ>
25
+ <system prompt: role + how to work + ESPECIALLY how to RETURN>
25
26
  ```
26
27
 
27
- ## 4 quy tắc không được quên
28
+ ## 4 rules you can't forget
28
29
 
29
- 1. **`description` viết theo "khi nào dùng", không phải " ".** Đây thứ agent chính
30
- đọc để quyết định có ủy thác hay không. hồ không bao giờ được gọi.
31
- 2. **Subagent phải trả về *kết luận chắt lọc*, không phải nhật ký.** Cả do tồn tại của
32
- subagent để context chính KHÔNG phải nuốt thứ đọc. Trả raw dump = phá mục tiêu.
33
- 3. **`tools` chỉ liệt cái thật cần.** Đây KHÔNG phải guardrail an toàn (đó Mức 3) —
34
- để agent gọn, tập trung. Agent đọc-hiểu chỉ cần `Read, Grep, Glob`.
35
- 4. **Một subagent = một việc rõ.** Đừng gộp "đọc + sửa + test" vào một agent. Việc nặng
36
- khác nhaucontext riêng khác nhau.
30
+ 1. **Write `description` as "when to use", not "what it is".** This is what the main agent reads
31
+ to decide whether to delegate. Vagueit never gets called.
32
+ 2. **A subagent must return a *distilled conclusion*, not a log.** The whole reason a subagent
33
+ exists is so the main context does NOT have to swallow what it read. A raw dump defeats the purpose.
34
+ 3. **`tools` lists only what's truly needed.** This is NOT a safety guardrail (that's Level 3) —
35
+ it keeps the agent lean and focused. A comprehension agent only needs `Read, Grep, Glob`.
36
+ 4. **One subagent = one clear job.** Don't merge "read + edit + test" into one agent. Different
37
+ heavy jobsdifferent separate contexts.
37
38
 
38
- ## Khi nào KHÔNG cần viết subagent mới
39
+ ## When you DON'T need a new subagent
39
40
 
40
- Claude Code đã sẵn `Explore` (quét read-only), `Plan` (thiết kế), `general-purpose`.
41
- Chúng lo phần lớn nhu cầu lập context rồi. **Chỉ viết subagent riêng khi** bạn một
42
- việc lặp lại, đặc thù domain built-in không nắm được đừng đẻ bản generic trùng lặp,
43
- chính tool thừa cái nhiễu context Mức 2 dạy phải tránh.
41
+ Claude Code already ships `Explore` (read-only sweeps), `Plan` (design), and `general-purpose`.
42
+ They cover most context-isolation needs already. **Only write your own subagent when** you have a
43
+ recurring, domain-specific job the built-ins don't handledon't spawn a redundant generic copy,
44
+ because surplus tools are exactly the context noise Level 2 teaches you to avoid.
@@ -1,27 +1,27 @@
1
1
  ---
2
2
  name: repo-explorer
3
- description: Đọc nhiều file để trả lời câu hỏi "cái nằm ở đâu / luồng này chạy ra sao" KHÔNG làm ngập context chính. Dùng khi cần quét rộng codebase chỉ cần kết luận, không cần nội dung từng file. Read-only.
3
+ description: Read many files to answer "where is X / how does this flow work" WITHOUT flooding the main context. Use when you need a broad sweep of the codebase and only need conclusions, not the contents of each file. Read-only.
4
4
  tools: Read, Grep, Glob
5
5
  ---
6
6
 
7
- Bạn agent **đọc-hiểu codebase**. Việc của bạn quét nhiều file rồi trả về
8
- một **kết luận chắt lọc** cho agent chính — agent chính KHÔNG thấy được những
9
- bạn đọc, chỉ thấy phần bạn trả về. Vì vậy:
7
+ You are a **codebase-comprehension** agent. Your job is to scan many files and return a
8
+ **distilled conclusion** to the main agent — the main agent CANNOT see what you read, only what
9
+ you return. Therefore:
10
10
 
11
- ## Cách làm
11
+ ## How to work
12
12
 
13
- 1. Bám sát đúng câu hỏi được giao. Đừng mở rộng phạm vi.
14
- 2. Dùng `Grep`/`Glob` để khoanh vùng trước, chỉ `Read` file thật sự liên quan.
15
- 3. Đọc *đủ để kết luận*, không đọc cho hết.
13
+ 1. Stick to the exact question you were given. Don't widen the scope.
14
+ 2. Use `Grep`/`Glob` to narrow down first; only `Read` files that are genuinely relevant.
15
+ 3. Read *enough to conclude*, not everything.
16
16
 
17
- ## Cách trả về (quan trọng nhất)
17
+ ## How to return (the most important part)
18
18
 
19
- Trả về **kết luận, không phải nhật ký**. Cụ thể:
19
+ Return **a conclusion, not a log**. Specifically:
20
20
 
21
- - Câu trả lời trực tiếp cho câu hỏi, lên đầu.
22
- - Các con trỏ `đường-dẫn/file.ts:dòng` cho mỗi điểm quan trọng (để agent chính tự mở khi cần).
23
- - TUYỆT ĐỐI không dán nguyên nội dung file dài vào câu trả lời đó chính là cái
24
- làm ngập context mà subagent này sinh ra để tránh.
25
- - Nếu không tìm thấy, nói thẳng "không tìm thấy X", đừng đoán.
21
+ - The direct answer to the question, up top.
22
+ - Pointers `path/file.ts:line` for each important spot (so the main agent can open them itself when needed).
23
+ - NEVER paste long file contents into your answer that is exactly the context flooding this
24
+ subagent exists to prevent.
25
+ - If you can't find it, say plainly "couldn't find X", don't guess.
26
26
 
27
- Mục tiêu: agent chính đọc 15 dòng của bạn là hiểu, thay phải tự đọc 50 file.
27
+ Goal: the main agent reads your 15 lines and understands, instead of having to read 50 files itself.
@@ -1,51 +1,55 @@
1
- # Evals & Observability — đo agent làm đúng không (Mức 5)
1
+ # Evals & Observability — measure whether the agent does the right thing (Level 5)
2
2
 
3
- Mức 1–4 *dựng* harness. Mức 5 **vòng phản hồi**: làm sao biết khi bạn sửa CLAUDE.md /
4
- settings / skill thì agent **tốt lên hay tệ đi**? Không Mức 5, mọi thay đổi harness chỉ là đoán.
3
+ Levels 1–4 *build* the harness. Level 5 is the **feedback loop**: how do you know whether changing
4
+ CLAUDE.md / settings / a skill made the agent **better or worse**? Without Level 5, every harness
5
+ change is a guess.
5
6
 
6
- ## Hai nửa
7
+ ## Two halves
7
8
 
8
- | Nửa | Trả lời | File |
9
- |-----|---------|------|
10
- | **Evals** | "Agent ra kết quả *đúng* không?" (pass/fail đo được) | [`cases/`](./cases/) |
11
- | **Observability** | "Agent đã *làm gì*, sao hỏng?" | [`observability.md`](./observability.md) |
9
+ | Half | Answers | File |
10
+ |------|---------|------|
11
+ | **Evals** | "Does the agent produce the *right* result?" (measurable pass/fail) | [`cases/`](./cases/) |
12
+ | **Observability** | "What did the agent *do*, and why did it fail?" | [`observability.md`](./observability.md) |
12
13
 
13
- Evals nói **đúng/sai**. Observability nói **tại sao** — thường lộ bệnh mức thấp hơn
14
- (đọc lại file hoài = context bẩn Mức 2; hỏi quyền liên tục chỉnh `allow` ở Mức 3).
14
+ Evals tell you **right/wrong**. Observability tells you **why**and often reveals a problem at a
15
+ lower level (re-reading files endlessly = dirty context → Level 2; constant permission promptsfix
16
+ `allow` at Level 3).
15
17
 
16
- ## Vòng lặp (đây mới cốt lõi, không phải file)
18
+ ## The loop (this is the core, not the files)
17
19
 
18
20
  ```
19
- define → run → read → fix → (chạy lại)
20
- golden cho đọc sửa
21
+ define → run → read → fix → (re-run)
22
+ golden the the the
21
23
  task agent trace harness
22
- chạy / kết (CLAUDE.md,
23
- quả settings, skill)
24
+ /result (CLAUDE.md,
25
+ settings, skill)
24
26
  ```
25
27
 
26
- Đòn bẩy thật: bộ golden task **lưới chống regression cho chính harness**. Sửa CLAUDE.md xong,
27
- chạy lại bộ case — case trước đậu giờ rớt gần như chắc chắn do thay đổi của mình (xác nhận
28
- bằng cách chạy lại vài lần để loại nhiễu), không phải đoán.
28
+ The real lever: the golden-task set is a **regression net for the harness itself**. After you change
29
+ CLAUDE.md, re-run the seta case that used to pass and now fails almost certainly your change
30
+ (confirm by re-running a few times to rule out noise), not a guess.
29
31
 
30
- ## Sự thật: Mức 5 ít "gói thành file" nhất
32
+ ## The truth: Level 5 is the least file-able
31
33
 
32
- Eval *thật* thì **đặc thù domain** — không kit nào ship sẵn "agent của bạn làm đúng chưa".
33
- Kit này chỉ cho **khung + kỷ luật**:
34
+ A *real* eval is **domain-specific** — no kit ships "is your agent correct yet" out of the box. This
35
+ kit only gives you the **scaffold + discipline**:
34
36
 
35
- - File: cấu trúc thư mục + template golden-task + guide observability.
36
- - 🧠 Discipline (phần lớn): *định nghĩa* "đúng" cho task của bạn, dựng bộ case, đọc trace,
37
- **đóng vòng lặp** (eval phát hiện regression → sửa harness → chạy lại).
37
+ - **File:** the folder structure + a golden-task template + an observability guide.
38
+ - **Discipline (most of it):** *define* what "correct" means for your task, build the case set, read
39
+ traces, **close the loop** (eval finds a regression → fix the harness → re-run).
38
40
 
39
- Kit cố ý **không** ship runner code — runner đặc thù repo, giả vờ generic sẽ thành rác.
41
+ The kit deliberately ships **no** runner code — a runner is repo-specific, and faking a generic one
42
+ would just be junk.
40
43
 
41
- ## Bắt đầu
44
+ ## Getting started
42
45
 
43
- 1. Copy `cases/example-task.md` thành một case thật, điền done-criteria *khách quan*.
44
- 2. Gom 3–5 task **đại diện** (việc agent làm thường xuyên nhất) — không cần nhiều, cần đúng.
45
- 3. **Lấy baseline "không harness" TRƯỚC.** Chạy bộ case một lần trạng thái chưa áp harness
46
- (CLAUDE.md trống / trước khi cài Mức 1–4) ghi điểm. Đây cái **định lượng ROI của harness**:
47
- chạy lại sau khi đã áp harness rồi so delta — chính luận điểm mở đầu của ngành (đổi harness
48
- làm điểm nhảy; xem `docs/harness-engineering-tutorial.md`). *Khác* với regression ở bước sau.
49
- 4. Sau đó, trước/sau **mỗi lần sửa** harness, chạy lại bộ case và đối chiếu (chạy vài lần để loại
50
- nhiễu trước khi kết luận nhân-quả).
51
- 5. Khi một case rớt, mở [`observability.md`](./observability.md) để truy *vì sao*.
46
+ 1. Copy `cases/example-task.md` into a real case and fill in *objective* done-criteria.
47
+ 2. Gather 3–5 **representative** tasks (what the agent does most often) — you don't need many, you need the right ones.
48
+ 3. **Take a "no-harness" baseline FIRST.** Run the set once with the harness not yet applied (empty
49
+ CLAUDE.md / before installing Levels 1–4) and record the score. This is what **quantifies the
50
+ harness's ROI**: re-run after applying the harness and compare the delta — exactly the field's
51
+ opening thesis (changing the harness moves the score; see `docs/harness-engineering-tutorial.md`).
52
+ This is *different* from the regression check below.
53
+ 4. After that, before/after **each change** to the harness, re-run the set and compare (run it a few
54
+ times to rule out noise before concluding cause).
55
+ 5. When a case fails, open [`observability.md`](./observability.md) to trace *why*.
@@ -1,33 +1,33 @@
1
1
  <!--
2
- Một "golden task" = một việc đại diện + tiêu chí đậu KHÁCH QUAN, để chạy lại được sau mỗi
3
- lần sửa harness. Copy file này cho mỗi case. Đặt tên theo việc: add-endpoint.md, fix-flaky-test.md...
2
+ A "golden task" = one representative job + OBJECTIVE pass criteria, so it can be re-run after every
3
+ harness change. Copy this file per case. Name it after the job: add-endpoint.md, fix-flaky-test.md...
4
4
 
5
- Nguyên tắc: done-criteria phải đo được bằng MÁY nếu thể (lệnh chạy ra pass/fail), chỉ rớt
6
- xuống chấm bằng người khi bất khả kháng. "Trông có vẻ đúng" KHÔNG phải tiêu chí.
7
- Xoá comment này khi dùng thật.
5
+ Principle: done-criteria must be MACHINE-checkable where possible (a command that returns pass/fail);
6
+ fall back to human grading only when unavoidable. "Looks right" is NOT a criterion.
7
+ Delete this comment when you use it for real.
8
8
  -->
9
9
 
10
- # Case: <tên việcvd "thêm endpoint GET /users/:id">
10
+ # Case: <the jobe.g. "add endpoint GET /users/:id">
11
11
 
12
- ## Task (đưa nguyên văn cho agent)
13
- <Lời nhắc y như bạn sẽ cho agent. Càng giống thực tế càng tốt.>
12
+ ## Task (give this verbatim to the agent)
13
+ <The exact prompt you'd type to the agent. The closer to reality, the better.>
14
14
 
15
- ## Setup (repo phải trạng thái nào trước khi chạy)
16
- <Branch/commit nền, dữ liệu seed, biến môi trường. Để case lặp lại được giống nhau mỗi lần.>
15
+ ## Setup (what state the repo must be in before running)
16
+ <Base branch/commit, seed data, env vars. So the case repeats identically every time.>
17
17
  - Base: <commit/branch>
18
18
  -
19
19
 
20
- ## Done-criteria (KHÁCH QUAN đậu/rớt rõ ràng)
21
- <Cái PHẢI đúng sau khi agent xong. Ưu tiên lệnh chạy ra pass/fail.>
22
- - [ ] `<lệnh test>` xanh
23
- - [ ] `<lệnh lint / typecheck>` sạch
24
- - [ ] <thay đổi cụ thể tồn tại vd "route mới trả 200 với id hợp lệ, 404 nếu không">
25
- - [ ] KHÔNG đụng <file/đường ngoài phạm vi>
20
+ ## Done-criteria (OBJECTIVEclear pass/fail)
21
+ <What MUST be true after the agent finishes. Prefer commands that return pass/fail.>
22
+ - [ ] `<test command>` green
23
+ - [ ] `<lint / typecheck command>` clean
24
+ - [ ] <a concrete change existse.g. "new route returns 200 for a valid id, 404 otherwise">
25
+ - [ ] Did NOT touch <out-of-scope file/path>
26
26
 
27
- ## Cách chấm
28
- <Tự động được thì ghi đúng lệnh. Phải chấm tay thì ghi rubric ngắn, đừng để "tự hiểu".>
29
- - Tự động: `<lệnh trả exit code>`
30
- - Tay (nếu cần): <1–2 câu rubric>
27
+ ## How to grade
28
+ <If automatable, write the exact command. If it must be manual, write a short rubric; don't leave it "implied".>
29
+ - Automated: `<command that returns an exit code>`
30
+ - Manual (if needed): <1–2 sentence rubric>
31
31
 
32
- ## Tham chiếu (tùy chọn)
33
- <Commit/PR "đúng" để so, nếu có. Giúp thấy agent lệch đâu.>
32
+ ## Reference (optional)
33
+ <A "correct" commit/PR to compare against, if any. Helps see where the agent diverged.>
@@ -1,42 +1,43 @@
1
- # Observability — thấy agent đã làm (Mức 5)
2
-
3
- Khi một eval rớthoặc agent "làm đó lạ" — bạn cần *nhìn* được đã làm gì, không đoán.
4
- Đây các chỗ mà nhìn, từ rẻ tới sâu.
5
-
6
- ## Chỗ nào mà nhìn
7
-
8
- 1. **Transcript phiên** — bản ghi *mọi* tool call agent đã gọi (đọc file nào, chạy lệnh gì,
9
- sửa gì). Đây nguồn sự thật số một khi truy "vì sao làm vậy". Claude Code lưu transcript
10
- mỗi session dưới thư mục project trong `~/.claude/`.
11
- 2. **`/cost`** — token & chi phí của phiên. Tăng vọt bất thường = dấu hiệu context phình
12
- (đọc lại file thừa, MCP nhồi tool) → kéo về Mức 2.
13
- 3. **Telemetry (cho cả team / chạy nền)** — Claude Code xuất được metrics/logs qua OpenTelemetry:
14
- bật bằng biến môi trường `CLAUDE_CODE_ENABLE_TELEMETRY` rồi trỏ OTLP exporter sang backend
15
- của bạn (Grafana, Honeycomb, Datadog…). Dùng khi cần theo dõi nhiều phiên/agent, không chỉ một.
16
- Tra cấu hình chính xác trong docs Claude Code mục *monitoring / telemetry*.
17
- 4. **Log hook (audit chủ động)** — gắn `PostToolUse` hook ghi mỗi tool call ra file (xem
18
- [guardrails/README.md](../guardrails/README.md) mục Hooks). Hữu ích khi chạy nền muốn xem lại sau.
19
-
20
- ## Dấu hiệu bệnh & chỉ về mức nào
21
-
22
- Observability không chỉ để debug một phiên **lộ ra lỗ hổng harness**:
23
-
24
- | Thấy trong trace | Bệnh | Sửa mức |
25
- |---------------------|------|-----------|
26
- | Đọc đi đọc lại cùng file; token leo thang | context bẩn | **Mức 2** (subagent / `/clear` / cắt MCP) |
27
- | Bị hỏi quyền liên tục cho lệnh an toàn | allowlist thiếu | **Mức 3** (thêm vào `allow`) |
28
- | Suýt chạy lệnh phá hoại | thiếu chốt | **Mức 3** (thêm vào `deny`/`ask`) |
29
- | Mất ngữ cảnh giữa phiên dài, làm lại từ đầu | không checkpoint | **Mức 4** (`TASK.md`) |
30
- | Làm sai không ai biết tới lúc muộn | thiếu eval | **Mức 5** (thêm golden task) |
31
- | hồ "build/test chạy sao" | chỉ dẫn thiếu | **Mức 1** (CLAUDE.md) |
32
- | Lặp đi lặp lại cùng một lỗi qua nhiều phiên | luật chưa được ghi | **Mức 1** (thêm 1 dòng vào CLAUDE.md) |
33
-
34
- **Đóng vòng về Mức 1 — `CLAUDE.md` tài liệu sống.** Khi trace cho thấy agent **lặp lại** một
35
- lỗi Z (vd quên chạy migration, sửa nhầm file generated), đừng chỉ sửa tay lần này: thêm **một dòng**
36
- guardrail/quy ước vào `CLAUDE.md` để chặn lần sau, rồi **chạy lại golden task** xác nhận hết
37
- regression. Đó cách `CLAUDE.md` lớn lên *từ lỗi thật*, thay phình theo phỏng đoán.
38
-
39
- ## Nguyên tắc
40
-
41
- > Đừng cải thiện harness bằng cảm giác. **Đọc trace, để nó chỉ đúng mức cần sửa**, sửa, rồi
42
- > chạy lại golden task để xác nhận tốt lên thật. Đó toàn bộ vòng lặp Mức 5.
1
+ # Observability — see what the agent did (Level 5)
2
+
3
+ When an eval failsor the agent "does something weird" — you need to *see* what it did, not guess.
4
+ Here's where to look, cheapest to deepest.
5
+
6
+ ## Where to look
7
+
8
+ 1. **The session transcript** — a record of *every* tool call the agent made (which files it read,
9
+ which commands it ran, what it edited). This is the number-one source of truth for "why did it do
10
+ that". Claude Code stores a per-session transcript under the project folder in `~/.claude/`.
11
+ 2. **`/cost`** — the session's tokens & cost. An unusual spike = a sign of context bloat (re-reading
12
+ surplus files, MCP tool stuffing) → pull it back to Level 2.
13
+ 3. **Telemetry (for a whole team / background runs)** — Claude Code can export metrics/logs via
14
+ OpenTelemetry: enable it with the `CLAUDE_CODE_ENABLE_TELEMETRY` env var, then point an OTLP
15
+ exporter at your backend (Grafana, Honeycomb, Datadog…). Use it when you need to watch many
16
+ sessions/agents, not just one. Find the exact config in the Claude Code docs under *monitoring / telemetry*.
17
+ 4. **A log hook (proactive audit)** — attach a `PostToolUse` hook that writes each tool call to a file
18
+ (see [guardrails/README.md](../guardrails/README.md), the Hooks section). Handy for background runs you want to review later.
19
+
20
+ ## Symptoms & which level they point to
21
+
22
+ Observability isn't just for debugging one sessionit **surfaces harness gaps**:
23
+
24
+ | What you see in the trace | Problem | Fix at level |
25
+ |---------------------------|---------|--------------|
26
+ | Re-reading the same files; tokens climbing | dirty context | **Level 2** (subagent / `/clear` / prune MCP) |
27
+ | Constant permission prompts for safe commands | missing allowlist | **Level 3** (add to `allow`) |
28
+ | Nearly ran a destructive command | missing guard | **Level 3** (add to `deny`/`ask`) |
29
+ | Loses context mid-long-session, starts over | no checkpoint | **Level 4** (`TASK.md`) |
30
+ | Does it wrong and nobody notices until late | missing eval | **Level 5** (add a golden task) |
31
+ | Vague about "how do build/test run" | missing guidance | **Level 1** (CLAUDE.md) |
32
+ | Repeats the same mistake across sessions | rule never written down | **Level 1** (add one line to CLAUDE.md) |
33
+
34
+ **Closing the loop back to Level 1 — `CLAUDE.md` is a living document.** When the trace shows the agent
35
+ **repeating** a mistake Z (e.g. forgetting to run a migration, editing a generated file), don't just
36
+ fix it by hand this time: add **one line** of guardrail/convention to `CLAUDE.md` to prevent it next
37
+ time, then **re-run the golden task** to confirm the regression is gone. That's how `CLAUDE.md` grows
38
+ *from real mistakes*, instead of bloating on speculation.
39
+
40
+ ## Principle
41
+
42
+ > Don't improve the harness on vibes. **Read the trace, let it point to the exact level to fix**, fix
43
+ > it, then re-run the golden task to confirm it actually got better. That's the whole Level 5 loop.
@@ -1,88 +1,90 @@
1
- # Guardrails — permission baseline (Mức 3)
1
+ # Guardrails — permission baseline (Level 3)
2
2
 
3
- Mức 3 kiểm soát agent **được phép làm gì**ranh giới an toàn. Khác Mức 2 (context *sạch*),
4
- Mức 3 lo hành động *an toàn*: chặn lệnh phá hoại, hỏi trước việc rủi ro, cho việc an toàn chạy thẳng.
3
+ Level 3 controls **what the agent is allowed to do**the safety boundary. Unlike Level 2 (a *clean*
4
+ context), Level 3 is about *safe* actions: block destructive commands, ask before risky ones, let
5
+ safe ones run straight through.
5
6
 
6
- ## Cài đặt
7
+ ## Install
7
8
 
8
- Copy `settings.json` vào `.claude/` của repo:
9
+ Copy `settings.json` into the repo's `.claude/`:
9
10
 
10
11
  ```bash
11
12
  mkdir -p .claude
12
13
  cp settings.json .claude/settings.json
13
14
  ```
14
15
 
15
- ** sao là `.claude/settings.json` (không phải `settings.local.json`):** file này **check vào repo**,
16
- nên cả team clone về **tự thừa hưởng cùng một bộ guardrail**. Còn `settings.local.json`
17
- ghi đè cá nhân (đã gitignore) — để dành cho tinh chỉnh riêng máy bạn, không ép lên team.
16
+ **Why `.claude/settings.json` (not `settings.local.json`):** this file is **checked into the repo**,
17
+ so everyone who clones it **inherits the same guardrails automatically**. `settings.local.json` is a
18
+ personal override (gitignored) — use it for machine-specific tweaks, not to impose on the team.
18
19
 
19
- > **Việc ĐẦU TIÊN sau khi copythêm lệnh test/lint/build vào `allow`.** Baseline cố ý chỉ
20
- > allow git read-only. Nếu không thêm vòng feedback của repo, Claude sẽ hỏi quyền *mỗi lần* chạy
21
- > test bạn rơi đúng thói quen "bấm yes cho xong" mục *Insight* bên dưới gọi nguy hiểm nhất.
22
- > Mở `.claude/settings.json`, thêm vào `allow` đúng lệnh của stack bạn:
20
+ > **The FIRST thing to do after copying add test/lint/build commands to `allow`.** The baseline
21
+ > deliberately only allows read-only git. Without your repo's feedback loop, Claude asks permission
22
+ > *every time* it runs tests you fall into the "click yes to get it over with" habit the *Insight*
23
+ > section below calls the real danger. Open `.claude/settings.json` and add your stack's commands to `allow`:
23
24
  >
24
25
  > - **Node:** `"Bash(npm run test:*)"`, `"Bash(npm run lint:*)"`, `"Bash(npm run build:*)"`
25
26
  > - **Python:** `"Bash(pytest:*)"`, `"Bash(ruff:*)"`, `"Bash(mypy:*)"`
26
27
  > - **Go:** `"Bash(go test:*)"`, `"Bash(go build:*)"`, `"Bash(go vet:*)"`
27
28
  >
28
- > Đây **bắt buộc**, không phải tuỳ chọn vòng feedback nhanh tinh tuý xuyên suốt cả kit.
29
+ > This is **mandatory, not optional** a fast feedback loop is the thread running through the whole kit.
29
30
 
30
- ## hình 3 rổ
31
+ ## The 3-bucket model
31
32
 
32
- Mọi hành động (chạy bash, đọc/sửa file) rơi vào 1 trong 3 rổ:
33
+ Every action (run bash, read/edit a file) falls into one of 3 buckets:
33
34
 
34
- | Rổ | Nghĩa | dụ trong baseline |
35
- |----|-------|----------------------|
36
- | **deny** | cấm tuyệt đối, agent không gọi được | `rm -rf`, đọc `.env`/`secrets/**`, đọc key `*.pem` |
37
- | **ask** | dừng lại hỏi bạn trước | `git push`, `git reset --hard`, `git clean`, `rm` |
38
- | **allow** | chạy thẳng, không hỏi | `git status`, `git diff`, `git log`, `git branch` |
35
+ | Bucket | Meaning | Examples in the baseline |
36
+ |--------|---------|--------------------------|
37
+ | **deny** | absolutely forbidden, the agent can't call it | `rm -rf`, read `.env`/`secrets/**`, read `*.pem` keys |
38
+ | **ask** | stop and ask you first | `git push`, `git reset --hard`, `git clean`, `rm` |
39
+ | **allow** | run straight through, no prompt | `git status`, `git diff`, `git log`, `git branch` |
39
40
 
40
- pháp rule: `Tool(specifier)`.
41
- - Bash khớp theo **tiền tố**: `Bash(npm run test:*)` khớp mọi lệnh bắt đầu bằng `npm run test`.
42
- - File theo kiểu **gitignore**: `Read(./secrets/**)`, `Edit(./dist/**)`.
41
+ Rule syntax: `Tool(specifier)`.
42
+ - Bash matches by **prefix**: `Bash(npm run test:*)` matches any command starting with `npm run test`.
43
+ - Files match **gitignore-style**: `Read(./secrets/**)`, `Edit(./dist/**)`.
43
44
 
44
- ## Cách mở rộng cho repo của bạn
45
+ ## Extend it for your repo
45
46
 
46
- Baseline cố ý **tối giản universal**. Hãy thêm cái đặc thù repo:
47
+ The baseline is deliberately **minimal and universal**. Add what's specific to your repo:
47
48
 
48
- - **Vào `allow`** — lệnh chạy hằng ngày, an toàn, để khỏi bị hỏi liên tục:
49
+ - **Into `allow`** — safe, daily commands so you aren't asked constantly:
49
50
  `Bash(npm run test:*)`, `Bash(npm run lint:*)`, `Bash(pytest:*)`, `Bash(make:*)`.
50
- - **Vào `ask`** — việc đặc thù repo mà *hệ quả lớn*:
51
- chạy migration (`Bash(npm run migrate:*)`), deploy, `Bash(docker compose down:*)`.
52
- - **Vào `deny`** — path không bao giờ được sửa/đọc:
51
+ - **Into `ask`** — repo-specific actions with *big consequences*:
52
+ running a migration (`Bash(npm run migrate:*)`), deploys, `Bash(docker compose down:*)`.
53
+ - **Into `deny`** — paths that must never be edited/read:
53
54
  `Edit(./dist/**)`, `Edit(./vendor/**)`, `Read(./**/*.key)`.
54
55
 
55
- > Mẹo: đừng nhồi `allow` quá rộng. Mỗi lần Claude hỏi một lần bạn *review* — nhồi allow
56
- > nhiều quá tự bỏ chốt review của chính mình.
56
+ > Tip: don't over-stuff `allow`. Every time Claude asks is a chance for you to *review* — over-stuffing
57
+ > `allow` throws away your own review checkpoint.
57
58
 
58
- ## Insight: deny ≠ bảo mật kín kẽ
59
+ ## Insight: deny ≠ airtight security
59
60
 
60
- Deny-list **không** chống được kẻ địch (agent thể lách: viết `rm` qua script, base64…).
61
- **lưới an toàn + giảm ma sát**:
62
- - `deny`/`ask` chặn **tai nạn** (xoá nhầm, push nhầm) — phòng *lỗi*, không phòng *tấn công*.
63
- - `allow` cho lệnh an toàn chạy thẳngbạn đỡ thói quen "bấm yes cho xong" (thói quen đó mới
64
- cái nguy hiểm thật).
61
+ A deny-list **doesn't** stop an adversary (an agent can route around it: write `rm` via a script,
62
+ base64…). It's a **safety net + friction reducer**:
63
+ - `deny`/`ask` block **accidents** (deleting/pushing by mistake) — they guard against *errors*, not *attacks*.
64
+ - `allow` lets safe commands run straight throughyou avoid the "click yes to get it over with"
65
+ habit (that habit is the real danger).
65
66
 
66
- **An toàn thật sự** vẫn là **review diff + plan mode** trước khi cho agent hành động đó
67
- kỷ luật runtime, không gói thành file được.
67
+ **Real safety** is still **reviewing diffs + plan mode** before letting the agent actthat's runtime
68
+ discipline, not something you can package into a file.
68
69
 
69
- ## Nội dung ngoài & prompt injection
70
+ ## External content & prompt injection
70
71
 
71
- `deny`/`ask` trên chặn *tai nạn*, **không** chặn được prompt injection. Nội dung agent đọc từ
72
- web, issue, PR, log **dữ liệu không phải lệnh**, nhưng kẻ xấu thể giấu chỉ thị trong đó
73
- để lái agent. Đây **kỷ luật runtime** (nên kit không nhồi hook/CI-scan sẵn), vài chốt thực dụng:
72
+ The `deny`/`ask` rules above block *accidents*; they **don't** stop prompt injection. Content the agent
73
+ reads from the web, issues, PRs, logsis **datanot commands**, but an attacker can hide instructions
74
+ in it to steer the agent. This is **runtime discipline** (so the kit ships no pre-baked hook/CI-scan), a
75
+ few practical guards:
74
76
 
75
- - Đọc nội dung ngoài (web/issue/PR) trong **plan mode** — agent *đề xuất* trước khi *hành động*.
76
- - KHÔNG cho agent tự chạy lệnh / `curl` lấy ra từ nội dung vừa fetch về.
77
- - Input không tin cậy tách **session riêng**, đừng trộn vào session đang có quyền cao.
77
+ - Read external content (web/issue/PR) in **plan mode** — the agent *proposes* before it *acts*.
78
+ - DON'T let the agent auto-run a command / `curl` pulled out of content it just fetched.
79
+ - Untrusted input split into a **separate session**; don't mix it into a high-privilege session.
78
80
 
79
- Quét tự động ở CI phần nền sâu hơn: xem `docs/harness-engineering-tutorial.md` (link **Lurkr**
80
- cho CI-scan, **OpenHands — mitigating prompt injection** cho nền tảng).
81
+ Automated CI scanning and deeper background: see `docs/harness-engineering-tutorial.md` (the **Lurkr**
82
+ link for CI-scan, **OpenHands — mitigating prompt injection** for the background).
81
83
 
82
- ## Nâng cao (tùy chọn): Hooks
84
+ ## Advanced (optional): Hooks
83
85
 
84
- Khi cần *logic* phức tạp hơn allow/deny tĩnh vd "chặn mọi edit vào path bảo vệ", "tự chạy
85
- lint sau mỗi lần sửa" — dùng **hook**: một script chạy *trước/sau* mỗi tool call. Khai báo trong
86
+ When you need *logic* beyond static allow/deny — e.g. "block every edit to a protected path", "auto-run
87
+ lint after each edit" — use a **hook**: a script that runs *before/after* every tool call. Declare it in
86
88
  `settings.json`:
87
89
 
88
90
  ```json
@@ -95,12 +97,12 @@ lint sau mỗi lần sửa" — dùng **hook**: một script chạy *trước/sa
95
97
  }
96
98
  ```
97
99
 
98
- Script đọc JSON tool-call từ stdin; **exit code 2 = chặn**, kèm message ra stderr. Vì hook chặn
99
- script đặc thù từng repo, kit này **không nhồi sẵn** — chỉ chỉ đường. Viết khi bạn thật sự có
100
- một quy tắc lặp lại allow/deny tĩnh không diễn đạt nổi.
100
+ The script reads the tool-call JSON from stdin; **exit code 2 = block**, with a message on stderr.
101
+ Because a blocking hook is repo-specific, the kit **ships none** — it just points the way. Write one
102
+ when you genuinely have a recurring rule that static allow/deny can't express.
101
103
 
102
- **Audit-log (`PostToolUse`)** — ghi lại *mọi* tool call để xem lại sau. Đây thứ
103
- `evals/observability.md` (Mức 5) trỏ tới; hook này **generic, không đặc thù repo**:
104
+ **Audit-log (`PostToolUse`)** — record *every* tool call to review later. This is what
105
+ `evals/observability.md` (Level 5) points to; this hook is **generic, not repo-specific**:
104
106
 
105
107
  ```json
106
108
  {
@@ -112,7 +114,7 @@ một quy tắc lặp lại mà allow/deny tĩnh không diễn đạt nổi.
112
114
  }
113
115
  ```
114
116
 
115
- `audit-log.sh` chỉ cần nối payload stdin vào một file — mỗi dòng là JSON một tool call:
117
+ `audit-log.sh` just appends the stdin payload to a file — one JSON tool-call per line:
116
118
 
117
119
  ```bash
118
120
  #!/usr/bin/env bash