Files
CASAN/optimize-docs/CASAN_SELF_SCORING_GUIDE.md
T
2026-07-02 22:17:03 +09:00

309 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CASAN — Hướng dẫn Tự Chấm Điểm (Self-Scoring) Step-by-Step
> **Mục tiêu:** Tự tay chạy lại toàn bộ harness CASAN và **tự chấm điểm 7 harness (H1–H7)** bằng bằng chứng chạy thật, không trích số.
> **Kịch bản của bạn:** chạy từ **máy Mac**, model `ornith:9b` nằm trên **Linux server ở nhà** (đã cài Ollama).
> **Nguyên tắc vàng CASAN:** *"điểm = thứ chứng minh được bằng tấn công, không phải thứ khai báo"* và *"harness thấp nhất quyết định trần"*.
---
## 0. Tổng quan luồng
```
┌─────────────┐ SSH tunnel (-L 11434) ┌──────────────────────────┐
│ Mac (bạn) │ ───────────────────────────► │ Linux server @ nhà │
│ repo casan5│ 127.0.0.1:11434 ⇄ :11434 │ Ollama + model ornith:9b │
└─────────────┘ └──────────────────────────┘
│
├─ chạy .specify/tests/*.sh + scripts/bash/*.sh
└─ đọc verdict → điền bảng điểm H1–H7
```
Harness **bắt buộc** gọi Ollama qua đúng `127.0.0.1:11434` (allowlist bảo mật trong `model-call.py`). Vì model ở server nhà, ta **SSH tunnel** cổng đó về Mac. Không có tunnel → các test model sẽ **SKIP** (không phải FAIL — thiết kế non-blocking), điểm vẫn tính được nhưng recall model để trống.
---
## 0b. Checklist "FULL-GREEN" — và vai trò thật của AI local
> **Tất cả nội dung mục này là KẾT QUẢ THẬT tôi đã tự chạy trong Docker `node:24-slim` + WSL Ubuntu 26.04 ngày 2026-07-02 — KHÔNG bịa, KHÔNG suy diễn.** Mục nào chưa tự đo được thì ghi rõ "chưa đo".
### Câu hỏi lớn: cần gì để chạy full, KHÔNG bị block ở bất kỳ bước nào?
**Trả lời thẳng: KHÔNG cần API key OpenAI/Anthropic.** Ollama `ornith:9b` ở nhà đã đảm nhiệm đúng vai trò model. Cloud key chỉ là **phương án thay thế / nâng recall**, không phải điều kiện để hết block.
| # | Điều kiện để 0 SKIP / 0 block | Trạng thái của bạn | Nếu thiếu thì chặn gì | Bằng chứng |
|---|---|---|---|---|
| 1 | **Live model** (Ollama **HOẶC** cloud key) | ✅ có Ollama ornith:9b | A3 semantic, A8 recall, C2 judge, `phase3-*` | tôi đã chạy judge-gate `PASS=3` khi model OFF (SKIP=2, non-blocking) |
| 2 | **node + python + openssl** | ✅ (Docker node:24-slim) | harness/vitest/audit | tôi tự chạy 35/35 + 43/43 + vitest 16/16 |
| 3 | **Chạy trong git repo thật** | ⚠️ bản copy chưa `git init` | `secrets-scan` in `not a git repository` (vẫn PASS=6) | tôi thấy warning này khi chạy offline |
| 4 | **1 lần chạy pipeline thật ≥3 step** | ❌ chưa chạy | **H6 cost-spike** = `COST_SPIKE_NO_DATA records=2` | tôi tự đo `records=2 (need >=3)` |
| 5 | (tuỳ chọn) Vault/KMS | — | KHÔNG block: `sign-audit-head` fallback local, verify vẫn qua | tôi thấy `SIGN_AUDIT_HEAD_SKIP` nhưng chain vẫn `VALID` |
→ **Thứ còn "thiếu/block" thật sự KHÔNG phải model** mà là (3) chạy trong git repo để secrets-scan sạch, và (4) một lần chạy pipeline để H6 có dữ liệu telemetry.
### Vai trò của AI local (ornith:9b) — đo thật, không suy diễn
**Trọng tâm thi = H4 · H5 · H6.** Chỉ H4 và H6 chạm tới model; H5 hoàn toàn deterministic. Phần lớn control chạy xanh **không cần model**:
| Harness | Chạy KHÔNG cần model (tôi đã tự chạy xanh) | Phần CẦN AI local | Vai trò AI local |
|---|---|---|---|
| **H4 Security** | A1/A4/A5/A6/A7: injection block, leetspeak, artifact-scan, secret, PII — **tất cả rc=2 OFFLINE** | **A3** (paraphrase mới), **A8** (recall) | **Quyết định** cho "semantic > regex" |
| **H5 Governance** | B1–B5: hash-chain, tamper→`HASH_MISMATCH`, RSA, secrets-scan, no-bypass — **100% OFFLINE** | — không có — | **≈0 vai trò** (toàn crypto) |
| **H6 AgentOps** | D1 cost-spike `COST_SPIKE_DETECTED exit=2`, D2 no-spike `exit=0`, D3 drift `DRIFT_WARN` — **logic deterministic, OFFLINE với data seed** | **D4** telemetry token thật | **Nguồn dữ liệu**: mỗi lời gọi model ghi `provider-usage.jsonl` (token thật) để cost-spike/agent-metrics đo |
**Con số recall THẬT (không bịa):**
- Regex thuần trên paraphrase mới: **recall = 0.00** — *tôi tự chạy, câu paraphrase → `exit=0` lọt*.
- Frontier model (tôi, làm judge trên 30 mẫu corpus): **recall = 1.00 (20/20)** — *tôi tự chấm trong phiên này*.
- Ollama `ornith:9b`: **recall ≈ 0.85** — **con số này do casan5 tự báo, TÔI CHƯA tự đo** (chưa bật Ollama). Khi bạn chạy ở nhà, `phase3-redteam-metrics.sh` sẽ in recall thật của 9B → điền vào đây.
**Kết luận trung thực về AI local (theo trọng tâm H4·H5·H6):**
1. AI local đóng **2 vai đo được thật**: (a) **tầng inferential** cho H4 (semantic recall, thắng regex 0.00); (b) **nguồn telemetry token thật** cho H6 (để cost-spike/agent-metrics có dữ liệu — tôi đã tự chứng logic cost-spike bằng data seed: `COST_SPIKE_DETECTED exit=2`).
2. **H5 không phụ thuộc model** — mạnh sẵn nhờ mật mã (đã tự chứng bằng tamper test). **Logic H6 cũng deterministic** — AI local chỉ *cấp dữ liệu*, không quyết định.
3. Giá trị lớn nhất của AI local **không nằm ở điểm số** mà ở **tự chủ dữ liệu** (red-team corpus/spec/audit/telemetry không rời máy) và **tái lập offline** (giám khảo replay không cần API key/mạng) — đúng trụ cột "Sovereign AI / Harness tự chủ" của FPT CASAN.
4. `ornith:9b` là **sàn, không phải trần**: đủ để **thắng regex (0.00)** và cấp telemetry thật, nhưng recall thua frontier — **hãy nói thẳng điều này khi thi** để đúng tinh thần "honest scope".
---
macOS dùng BSD tools; harness cần vài công cụ GNU + `python` (không phải `python3`). Cài qua Homebrew:
```bash
# 1.1 Công cụ nền
brew install bash coreutils gnu-sed grep openssl@3 node git jq
# 1.2 Đưa GNU coreutils/sed/grep lên đầu PATH cho phiên chấm điểm
# (coreutils cung cấp sha256sum, timeout; gnu-sed/grep cung cấp sed/grep GNU)
export PATH="$(brew --prefix coreutils)/libexec/gnubin:$(brew --prefix gnu-sed)/libexec/gnubin:$(brew --prefix grep)/libexec/gnubin:$PATH"
# 1.3 Shim `python` -> `python3` (nhiều script gọi `python`)
mkdir -p ~/bin
printf '#!/usr/bin/env bash\nexec python3 "$@"\n' > ~/bin/python
chmod +x ~/bin/python
export PATH="$HOME/bin:$PATH"
# 1.4 Kiểm tra
for t in bash node python python3 openssl sha256sum timeout git jq; do
printf "%-10s " "$t"; command -v "$t" >/dev/null && "$t" --version 2>/dev/null | head -1 || echo MISSING
done
```
> **Vì sao cần bước này:** trên môi trường thiếu `python`/`sha256sum`/`timeout`, harness sẽ FAIL **giả** (lỗi môi trường, không phải control hỏng). Đây là bẫy phổ biến nhất khi tự chấm.
**Tuỳ chọn — dùng Docker cho toolchain sạch (khỏi lo BSD):**
```bash
docker run --rm -it --network host -v "$PWD":/work -w /work/casan5/AINative_OKR_CASAN5 node:24-slim bash -lc '
apt-get update -qq && apt-get install -y -qq python3 openssl git curl jq >/dev/null
ln -sf "$(command -v python3)" /usr/local/bin/python
bash # vào shell rồi chạy các bước Mục 4–6
'
```
*(`--network host` để container thấy `127.0.0.1:11434` của tunnel. Trên Docker Desktop macOS, thay bằng `--add-host=host.docker.internal:host-gateway` và đặt `OLLAMA` qua host.docker.internal — xem Mục 3.3.)*
---
## 2. Lấy source về Mac
```bash
# Copy/clone thư mục casan5 về Mac, rồi:
cd <đường-dẫn>/casan5/AINative_OKR_CASAN5
ls .specify/tests/ # phải thấy run-casan4-harness-tests.sh, adversarial-harness-tests.sh, phase3-*.sh
```
---
## 3. Kết nối tới Ollama ở nhà
### 3.1. Trên Linux server (một lần) — xác nhận model & Ollama lắng nghe
```bash
ollama list # phải thấy dòng "ornith:9b"
curl -s 127.0.0.1:11434/api/tags # trả JSON danh sách model
# Nếu chưa có model, tạo/pull theo cách bạn đã dùng ở nhà (vd: ollama create ornith:9b -f Modelfile)
```
### 3.2. Từ Mac — mở SSH tunnel (giữ terminal này chạy)
```bash
ssh -N -L 11434:127.0.0.1:11434 <user>@<home-linux-server>
```
### 3.3. Từ Mac — kiểm tra tunnel (terminal khác)
```bash
curl -s 127.0.0.1:11434/api/tags | jq '.models[].name' # phải liệt kê ornith:9b
```
> Nếu bạn dùng tên model khác, xuất biến trước khi chạy gate:
> ```bash
> export CASAN_MODEL_PRIMARY="ollama:ornith:9b" # mặc định đã là giá trị này
> ```
---
## 4. Chạy các harness cốt lõi (không cần model)
Các bước này chứng minh H1/H2/H3(rule)/H4(regex)/H5/H6/H7 — chạy được **không cần Ollama**.
```bash
cd casan5/AINative_OKR_CASAN5
# 4.1 Harness chính (CASAN Level 4) — kỳ vọng: 35 PASS / 0 FAIL, exit 0
bash .specify/tests/run-casan4-harness-tests.sh; echo "exit=$?"
# 4.2 Bộ adversarial (tấn công đối kháng) — kỳ vọng: 43–44 PASS / 0 FAIL, exit 0
bash .specify/tests/adversarial-harness-tests.sh; echo "exit=$?"
# 4.3 Chuỗi audit ký + toàn vẹn (H5) — kỳ vọng: AUDIT_CHAIN_VALID
bash .specify/scripts/bash/sign-audit-head.sh
bash .specify/scripts/bash/verify-audit-chain.sh
bash .specify/scripts/bash/verify-tool-audit.sh # kỳ vọng: TOOL_AUDIT_VALID
```
> **Lưu ý quan trọng:** `run-casan4-harness-tests.sh` **tự `rm -rf .specify/logs`** khi khởi động (reset trạng thái) rồi tự sinh lại. Đừng hoảng nếu thấy log cũ biến mất — đó là hành vi thiết kế.
**Bài test tự kiểm chứng H5 (tùy chọn, rất thuyết phục):** cố tình sửa 1 record rồi verify lại — phải thấy `AUDIT_HASH_MISMATCH`:
```bash
cp .specify/logs/audit/audit.jsonl /tmp/audit.bak
sed -i '1s/high/LOW/' .specify/logs/audit/audit.jsonl
bash .specify/scripts/bash/verify-audit-chain.sh # kỳ vọng: AUDIT_HASH_MISMATCH line=1
cp /tmp/audit.bak .specify/logs/audit/audit.jsonl # khôi phục
```
---
## 5. Chạy các harness cần model (H3 judge + H4 semantic) — với ornith:9b
Đảm bảo tunnel Mục 3 đang chạy (`curl 127.0.0.1:11434/api/tags` OK).
```bash
export CASAN_MODEL_PRIMARY="ollama:ornith:9b"
# 5.1 Model router hoạt động (classify/judge trả đúng 1 từ, fail-closed)
bash .specify/tests/phase3-model-router-tests.sh; echo "exit=$?"
# 5.2 Red-team metrics — precision/recall regex vs model trên 30 mẫu
# Gate PASS khi: model_recall >= 0.8 VÀ model_recall > regex_recall
bash .specify/tests/phase3-redteam-metrics.sh; echo "exit=$?"
# 5.3 Judge-gate (H3): rule REJECT không gọi model; rule-pass thì tới model judge
# Kỳ vọng với Ollama live: PASS=5 / FAIL=0 (không còn SKIP)
bash .specify/tests/phase3-judge-gate-tests.sh; echo "exit=$?"
```
> Nếu tunnel **tắt**, các script trên in `BLOCKED: Ollama tunnel down` và **SKIP** (không FAIL). Điểm H3/H4 khi đó dựa trên phần rule + regex; recall model để trống.
---
## 6. Chạy test sản phẩm (frontend + backend)
```bash
# 6.1 Frontend — kỳ vọng: 16 passed
cd casan5/AINative_OKR_CASAN5
npm install --prefix frontend # lần đầu
npm test -w frontend # vitest run -> 16/16
# 6.2 Backend (unit + e2e + LLM-judge). LLM-judge SKIP nếu không có API key/Ollama.
npm ci
npm run db:setup && npx prisma db seed -w backend 2>/dev/null || true
node --import tsx --test-concurrency=1 --test "backend/test/**/*.test.ts"
```
---
## 7. Chấm điểm một phát bằng cổng tổng hợp
```bash
# Chạy TẤT CẢ gate bảo mật + model + frontend, in verdict tổng
bash .specify/scripts/bash/security-gate.sh
# Kỳ vọng khi tunnel + node đủ: == verdict: PASS=10 FAIL=0 SKIP=0 ==
# Nếu tunnel tắt: SKIP tăng (model gate), vẫn PASS phần còn lại.
```
Đây là lệnh chốt: **PASS=10 FAIL=0 SKIP=0** nghĩa là toàn bộ control xanh với model live.
---
## 8. Bảng tự chấm điểm 7 harness (điền sau khi chạy)
Cách đọc: mỗi harness lấy điểm từ **bằng chứng chạy thật** ở Mục 4–7. Ngưỡng CASAN Level 4 = mọi harness ≥ 80; trung bình mục tiêu ~84.
| Harness | Bằng chứng (lệnh) | Kỳ vọng | Điểm bạn đo | Ghi chú |
|---|---|---|:--:|---|
| **H1 Context** | `context-validate.sh` → `CONTEXT_VALID checked=N` | ~85 | ____ | artifact path đưa đúng agent |
| **H2 Tool** | `verify-tool-audit.sh` → `TOOL_AUDIT_VALID`; rate-limit + JSON-schema trong adversarial | ~84 | ____ | least-privilege + timeout |
| **H3 Evaluation** | `phase3-judge-gate-tests.sh` (PASS=5) + `npm test -w frontend` (16) | ~78–82 | ____ | rule AND model; fail-before |
| **H4 Security** | `phase3-redteam-metrics.sh` (model_recall ≥ 0.8 > regex) + `security-check.sh` chặn injection | ~86 | ____ | semantic > regex |
| **H5 Governance** | `verify-audit-chain.sh` → `AUDIT_CHAIN_VALID`; tamper → `HASH_MISMATCH` | ~83–85 | ____ | ký RSA, tách khoá |
| **H6 AgentOps** | `metrics.jsonl` có `cost_source=provider_telemetry`; `cost-spike-detect.sh` | ~84 | ____ | đo token thật |
| **H7 Orchestration** | adversarial: rollback checkpoint→restore (before==after); `drift-detect.sh` | ~86–87 | ____ | rollback thật |
| | **Trung bình** | **~84** | ____ | mọi harness phải ≥ 80 |
**Quy tắc chấm trung thực:**
- Một harness chỉ được điểm cao nếu **chặn được một tấn công thật** (vd tamper → HASH_MISMATCH), không phải "có file cấu hình".
- **SKIP ≠ FAIL:** test model SKIP khi thiếu Ollama là **non-blocking**; nhưng nếu bạn *có* Ollama mà vẫn FAIL → đó là vấn đề thật, trừ điểm.
- Nếu harness thấp nhất < 80 → **cả pipeline chưa đạt Level 4 thật** (dù các harness khác cao).
---
## 9. Phân biệt FAIL thật vs FAIL môi trường (checklist khi gặp đỏ)
| Triệu chứng | Nguyên nhân môi trường (KHÔNG trừ điểm) | Cách xử lý |
|---|---|---|
| `python: command not found` | script gọi `python`, Mac chỉ có `python3` | tạo shim Mục 1.3 |
| `grep: character class syntax is [[:space:]]` | dùng BSD grep | đưa GNU grep lên PATH (Mục 1.2) |
| `sha256sum: command not found` / `timeout: not found` | thiếu coreutils | `brew install coreutils` + gnubin PATH |
| `AUDIT_CHAIN_MISSING` | harness vừa `rm -rf logs`, chưa sinh lại | chạy lại Mục 4.1 rồi 4.3 |
| `BLOCKED: Ollama tunnel down` | tunnel chưa mở | kiểm tra Mục 3.2/3.3 |
| `dofork ... 0xC000013A` | chỉ xảy ra trên Git Bash/Windows (fork msys) | chạy trên Mac/Linux/Docker là hết |
> **Nguyên tắc:** trước khi kết luận "control hỏng", loại trừ hết 6 nguyên nhân môi trường ở trên. Đa số "FAIL" ban đầu là môi trường.
---
## 10. Script tự chấm một lệnh (tùy chọn — dán vào `selfscore.sh`)
```bash
#!/usr/bin/env bash
# Chạy: bash selfscore.sh (từ trong casan5/AINative_OKR_CASAN5)
set -uo pipefail
export PATH="$HOME/bin:$(brew --prefix coreutils)/libexec/gnubin:$(brew --prefix gnu-sed)/libexec/gnubin:$(brew --prefix grep)/libexec/gnubin:$PATH"
export CASAN_MODEL_PRIMARY="ollama:ornith:9b"
hr(){ printf '\n===== %s =====\n' "$1"; }
ollama_up(){ curl -sS -m 5 http://127.0.0.1:11434/api/tags >/dev/null 2>&1; }
hr "Ollama tunnel"; ollama_up && echo "UP (ornith:9b)" || echo "DOWN -> model tests will SKIP"
hr "casan4 harness"; bash .specify/tests/run-casan4-harness-tests.sh >/tmp/c4.log 2>&1; echo "PASS=$(grep -c '^PASS' /tmp/c4.log) FAIL=$(grep -c '^FAIL' /tmp/c4.log) exit=$?"
hr "adversarial"; bash .specify/tests/adversarial-harness-tests.sh >/tmp/adv.log 2>&1; echo "PASS=$(grep -c '^PASS' /tmp/adv.log) FAIL=$(grep -c '^FAIL' /tmp/adv.log) exit=$?"
hr "audit chain"; bash .specify/scripts/bash/sign-audit-head.sh >/dev/null 2>&1; bash .specify/scripts/bash/verify-audit-chain.sh; bash .specify/scripts/bash/verify-tool-audit.sh
if ollama_up; then
hr "model router"; bash .specify/tests/phase3-model-router-tests.sh 2>&1 | tail -2
hr "red-team metrics"; bash .specify/tests/phase3-redteam-metrics.sh 2>&1 | tail -4
hr "judge gate"; bash .specify/tests/phase3-judge-gate-tests.sh 2>&1 | tail -2
fi
hr "frontend vitest"; (npm test -w frontend 2>&1 | tail -4)
hr "SECURITY GATE"; bash .specify/scripts/bash/security-gate.sh 2>&1 | tail -20
```
---
## 11. Tiêu chí "đạt" cuối cùng (để tuyên bố Level 4 thật)
Bạn được quyền tuyên bố **casan5 = CASAN Level 4 chứng minh được** khi, trên máy có Ollama ornith:9b:
- [ ] `run-casan4-harness-tests.sh` → **35 PASS / 0 FAIL**
- [ ] `adversarial-harness-tests.sh` → **44 PASS / 0 FAIL**
- [ ] `verify-audit-chain.sh` → **AUDIT_CHAIN_VALID** và tamper → **HASH_MISMATCH**
- [ ] `verify-tool-audit.sh` → **TOOL_AUDIT_VALID**
- [ ] `phase3-redteam-metrics.sh` → **model_recall ≥ 0.8 và > regex_recall**
- [ ] `phase3-judge-gate-tests.sh` → **PASS=5 / FAIL=0**
- [ ] `npm test -w frontend` → **16 passed**
- [ ] `security-gate.sh` → **PASS=10 FAIL=0 SKIP=0**
- [ ] Mọi harness H1–H7 ≥ 80; trung bình ~84
> Khi tất cả ô trên xanh, điểm không còn là "tự khai" — nó là **thứ bạn tái lập được bằng lệnh**, đúng tinh thần CASAN.
---
## 12. Ghi chú đối chiếu với báo cáo đánh giá
- Tài liệu này là quy trình để **tự tái lập** phần **Phụ lục A + B** của `CASAN_OLD_vs_CASAN5_Executive_Assessment.md`.
- Điểm số tham chiếu (~84, H1–H7) lấy từ `docs/output/casan/phase3-final-rescore.md` của dự án; mục 8 để bạn **điền số bạn tự đo** cạnh số tham chiếu → tự đối chứng.
- Nếu muốn so **casan-old vs casan5**, chạy y hệt Mục 4–7 trong cả hai thư mục và điền hai cột. (Lưu ý: casan-old có bug `[:space:]` trong `security-check.sh` sẽ fail-open trên grep GNU — đây là khác biệt thật, không phải lỗi môi trường của bạn.)
```