| name | robot-bi-dev |
| version | 1.0.0 |
| description | Master skill cho dự án Robot Bi. Kết hợp TDD, diagnosis loop, security audit, git safety, UI prototyping, và session hygiene — tất cả được calibrate cho codebase Python/FastAPI/SQLite/Groq của Robot Bi. Trigger khi: implement feature mới, debug bug, security review, làm UI frontend/robot display, hoặc bắt đầu session dev bất kỳ.
|
Robot Bi — Master Dev Skill
Skill này là bộ quy trình chuẩn cho mọi session phát triển Robot Bi.
Đọc từ đầu đến cuối lần đầu. Sau đó nhảy thẳng vào phần phù hợp với task.
0. Session Start — Bắt buộc mỗi session
Trước khi chạm bất kỳ file nào, thực hiện đủ 3 bước sau:
cat PROJECT.md
cat .claude/handoff.md
python tests/run_tests.py
Nếu baseline không phải 374/374 PASS: dừng lại, báo cho user, fix trước.
1. Implement Feature Mới — TDD Loop
Từ tdd (mattpocock) + diagnose (mattpocock)
Nguyên tắc cốt lõi
- Test verify behavior qua public interface, không test implementation details.
- Vertical slices: một test → một implementation → repeat. Không viết 5 test rồi mới implement.
- Test name phải đọc như spec:
test_homework_marked_when_child_mentions_bai_tap, không phải test_function_x.
Workflow
Bước 1 — Identify seam
Trước khi viết bất kỳ code nào, xác định:
- Public interface mới là gì? (function signature, API endpoint, WebSocket event)
- Behavior nào cần test nhất? (happy path, failure mode, edge case)
- Module nào trong
src/ sẽ bị chạm? Có trong PROTECTED FIXES không?
Bước 2 — Tracer bullet
def test_N_1_[feature]_basic():
from src.[module] import [Class]
obj = [Class]()
result = obj.[method]([input])
assert result == [expected]
test("N.1 [Feature] basic smoke", test_N_1_[feature]_basic)
Chạy: python tests/run_tests.py → phải thấy FAIL rõ ràng.
Bước 3 — Implement minimal
Viết đủ code để test pass. Không thêm feature chưa có test.
Bước 4 — Repeat
Lặp lại cho mỗi behavior. Thêm test → FAIL → implement → PASS.
Bước 5 — Regression check
python tests/run_tests.py
Robot Bi — Patterns thường gặp
def test_endpoint_exists():
from src.api.server import app
paths = [r.path for r in app.routes]
assert "/api/your/endpoint" in paths
def test_import():
from src.module.submodule import ClassName
assert ClassName is not None
def test_behavior():
from src.infrastructure.database.db import init_db
obj = YourClass()
result = obj.do_thing("input")
assert "expected" in result
Quy tắc test Robot Bi
- Không bao giờ dùng
runtime/robot_bi.db trong test — luôn dùng temp DB như run_tests.py đã setup.
- Mỗi group test mới: comment header
# == GROUP N: [Name] === + print("\n[Group N] [Name]").
- Test không được require mic, camera, loa, Ollama, internet — chạy offline hoàn toàn.
- Nếu test cần LLM: mock response hoặc test logic không phụ thuộc LLM output cụ thể.
2. Debug Bug — Diagnosis Loop
Từ diagnose (mattpocock)
Phase 1 — Build feedback loop (đây là kỹ năng chính)
Trước khi đọc bất kỳ dòng code nào, xây dựng signal pass/fail tự động.
Thử theo thứ tự:
- Failing test trong
tests/run_tests.py — preferred vì tích hợp vào CI.
- Script curl/HTTP gọi FastAPI endpoint đang có vấn đề:
curl -X POST https://localhost:8443/api/your/endpoint \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"key": "value"}' -k 2>&1
- Throwaway harness cho audio/STT/TTS bugs:
import asyncio
from src.audio.output.mouth_tts import MouthTTS
tts = MouthTTS()
asyncio.run(tts.speak("test", chunk_index=0))
print("OK")
- Log diff cho non-deterministic bugs (threading, audio queue):
import logging
logger.debug("[DEBUG-a4f2] audio_queue size=%d", audio_queue.qsize())
Nếu không tạo được feedback loop → dừng, báo user, không đoán mò.
Phase 2 — Hypothesise (trước khi test bất kỳ hypothesis nào)
Liệt kê 3-5 hypothesis theo format:
"Nếu [X] là nguyên nhân, thì [thay đổi Y] sẽ làm bug biến mất / [thay đổi Z] sẽ làm bug tệ hơn."
Check PROTECTED FIXES: nếu hypothesis liên quan đến audio mom talk, camera delay, SafetyFilter, RAG threshold, JWT flow → xem kỹ implementation hiện tại trước khi thay đổi.
Phase 3 — Instrument & Fix
- Thay đổi một biến một lần.
- Tag tất cả debug log:
[DEBUG-xxxx] để cleanup dễ sau fix.
- Viết regression test trước fix — nếu có seam phù hợp.
Phase 4 — Cleanup
grep -r "DEBUG-" src/
python tests/run_tests.py
Robot Bi — Bug patterns đã gặp
| Symptom | Nguyên nhân thường gặp | Kiểm tra |
|---|
| Audio bị echo / delay | Thread audio queue không drain | audio_queue.qsize() + pygame.Channel |
| STT không nhận | Mic device không đúng | MIC_DEVICE trong .env |
| API 401 | JWT expired / missing Bearer | verify_access_token() trong auth.py |
| Test fail sau refactor | Import path src_brain.* cũ | grep -r "src_brain" src/ |
| Camera freeze | CAP_PROP_BUFFERSIZE | Thread riêng + queue bridge |
| RAG nhớ sai | family_id filter bị bỏ qua | where={"family_id": fid} trong query |
3. Security Review
Từ security-best-practices (openai/Codex)
Chỉ trigger khi
- User yêu cầu security review rõ ràng.
- Thêm endpoint mới expose ra internet.
- Thay đổi auth flow, JWT, rate limiting.
- Chuẩn bị deploy lên Ubuntu thật (public).
Stack Robot Bi cần kiểm tra
Backend (Python + FastAPI):
- JWT:
create_access_token HS256, secret từ .env — không hardcode, không có default value.
- Argon2id:
verify_password(hash, plaintext) — check thứ tự đúng.
- Rate limiting:
login_attempts table — 5 lần sai → lock 15 phút.
- SQL: tất cả query dùng parameterized, không string format.
- Family isolation: mọi DB query có
family_id filter.
- Logging: không log nội dung hội thoại ở INFO/WARNING — chỉ DEBUG.
Frontend (JavaScript thuần):
Authorization: Bearer <token> attach vào mọi API call.
- Token lưu
localStorage — không expose qua URL.
- WebSocket connect với
?token= query param.
- XSS: không dùng
innerHTML với user input.
Report format
Khi viết security report → lưu vào docs/security_report_YYYY-MM-DD.md:
# Security Review — [Date]
## Executive Summary
[2-3 câu tóm tắt]
## CRITICAL
### [C1] [Tên vấn đề]
**File**: `src/path/file.py`, line [N]
**Impact**: [1 câu impact]
**Fix**: [code snippet]
## HIGH
### [H1] ...
## MEDIUM / LOW
...
Sau khi viết report → fix từng issue một, chạy python tests/run_tests.py sau mỗi fix.
Không report là security issue
- Thiếu TLS trong môi trường dev (Robot Bi dùng self-signed + Cloudflare tunnel).
- PIN auth chạy song song JWT — đây là design có chủ đích.
4. UI / Frontend — Robot Display & Parent App
Từ frontend-design (anthropics) + prototype (mattpocock) + webapp-testing (anthropics)
Khi làm UI mới
Bước 1 — Xác định question trước khi code
- "Logic/state machine có đúng không?" → prototype logic (terminal app nhỏ, throwaway).
- "Giao diện trông thế nào?" → prototype UI (nhiều variants, toggle bằng URL param).
- "Feature đã hoạt động chưa?" → test với Playwright.
Bước 2 — Prototype nếu cần (throwaway)
frontend/robot_display/prototype_[feature].html ← đặt gần nơi sẽ dùng
Rules prototype:
- Một lệnh để chạy:
python -m http.server 8080 rồi mở file.
- Không có DB, không có API call thật — state trong memory.
- Không test, không error handling.
- Xóa sau khi answer câu hỏi, hoặc absorb vào production code.
Bước 3 — Design direction
Trước khi viết production code, commit rõ aesthetic direction:
- Robot Display (
frontend/robot_display/index.html): Playful, futuristic, dành cho trẻ em 5-12 tuổi. Màu sắc sống động. Animation mượt. SVG eyes có expressiveness cao. Không generic "AI dashboard" style.
- Parent App (
frontend/parent_app/index.html): Clean, functional, tin tưởng được. Dành cho phụ huynh. Thông tin rõ ràng. Dark/light mode. Không cluttered.
Tránh: Inter font, purple gradient trên white, uniform rounded corners — đây là "AI slop".
Bước 4 — Test với Playwright
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto(f"file:///path/to/frontend/robot_display/index.html")
page.wait_for_load_state("networkidle")
page.goto("https://localhost:8443")
page.wait_for_load_state("networkidle")
page.screenshot(path="/tmp/debug_ui.png", full_page=True)
page.locator("button#[id]").click()
page.wait_for_selector("[selector]")
assert page.locator("[result_selector]").is_visible()
browser.close()
Robot Display patterns quan trọng:
const MODES = {
your_mode() {
clearAll();
setAccent('#color');
stage.classList.add('your_mode');
registerFaceTimeout(() => setMode('idle'), 3000);
}
};
Animation guidelines Robot Display
- Dùng CSS
@keyframes cho loop animations (idle, breathing, pulse).
- Dùng
registerFaceTimeout() không phải setTimeout() trực tiếp — quản lý cleanup.
- SVG eye:
transform-box: fill-box; transform-origin: center cho scale animations.
- Không dùng physics engine hay heavy library — pure CSS + vanilla JS.
5. Git Safety — Bảo vệ khỏi lệnh nguy hiểm
Từ git-guardrails-claude-code (mattpocock)
Cài đặt (một lần)
mkdir -p .claude/hooks
cat > .claude/hooks/block-dangerous-git.sh << 'EOF'
input=$(cat)
cmd=$(echo "$input" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('tool_input',{}).get('command',''))" 2>/dev/null)
BLOCKED=(
"git push"
"git reset --hard"
"git clean -f"
"git branch -D"
"git checkout ."
"git restore ."
)
for pattern in "${BLOCKED[@]}"; do
if echo "$cmd" | grep -qF "$pattern"; then
echo "[BLOCKED] Lệnh nguy hiểm: $pattern" >&2
echo "Hãy xác nhận với user trước khi chạy lệnh git này." >&2
exit 2
fi
done
exit 0
EOF
chmod +x .claude/hooks/block-dangerous-git.sh
Thêm vào .claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/block-dangerous-git.sh"
}
]
}
]
}
}
Git workflow Robot Bi
python tests/run_tests.py
python sync.py
git commit -m "feat(module): mô tả ngắn
- Thêm: X
- Fix: Y
- Tests: Group N (M tests)"
6. Session End — Bắt buộc trước khi kết thúc
python tests/run_tests.py
python sync.py
7. Quick Reference — Robot Bi Cheat Sheet
Entry points & files quan trọng
| Mục đích | File |
|---|
| Chạy robot | python src/main.py |
| Chạy test | python tests/run_tests.py |
| Sync docs | python sync.py |
| AI engine | src/ai/ai_engine.py — stream_chat(messages) |
| STT | src/audio/input/ear_stt.py |
| TTS | src/audio/output/mouth_tts.py |
| Safety | src/safety/safety_filter.py — luôn post-LLM, pre-TTS |
| API server | src/api/server.py + src/api/routers/ |
| Database | src/infrastructure/database/db.py → runtime/robot_bi.db |
| RAG | src/memory/rag_manager.py → runtime/chroma_db/ |
| Robot UI | frontend/robot_display/index.html |
| Parent App | frontend/parent_app/index.html |
| Nguồn sự thật | PROJECT.md → đọc trước mọi thứ |
LLM stack (không thay đổi trừ khi có lệnh rõ ràng)
- Primary: Groq
llama-3.3-70b-versatile (~400 tok/s)
- Fallback: Gemini
gemini-2.5-flash-lite
- Call qua:
stream_chat(messages) trong src/ai/ai_engine.py
Quy tắc tuyệt đối (không bao giờ vi phạm)
PROJECT.md là nguồn sự thật duy nhất — không sửa CLAUDE.md/AGENTS.md trực tiếp.
python tests/run_tests.py phải PASS 100% sau mỗi thay đổi.
- Không bao giờ hardcode
JWT_SECRET_KEY hay API key.
SafetyFilter phải chạy post-LLM, pre-TTS — không bỏ qua.
- Mọi DB query có
family_id filter — không query toàn bộ data.
- Test không được require hardware (mic, camera, loa).
- Không sửa PROTECTED FIXES mà không đọc kỹ implementation hiện tại.
Lệnh debug nhanh
grep -r "src_brain" src/ tests/
grep -r "DEBUG-" src/
grep -rn "secret\|password\|api_key" src/ --include="*.py" | grep -v ".env" | grep -v "os.getenv"
python -c "from src.api.server import app; [print(r.path) for r in app.routes if hasattr(r,'path')]"
python -c "from src.infrastructure.database.db import init_db; init_db(); print('DB OK')"