openmoneta-dev-kit 2.2.1 → 2.3.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.
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # OpenMoneta Dev Kit
2
2
 
3
- > Biến **Cursor IDE / OpenCode** thành một **team developer hoàn chỉnh** với quy trình 6 bước (Lean Mode), adaptive planning, hooks enforcement, token-aware doc routing và sub-agents on-demand.
3
+ > Biến **Cursor IDE / OpenCode / Claude Code** thành một **team developer hoàn chỉnh** với quy trình 6 bước (Lean Mode), adaptive planning, hooks enforcement, token-aware doc routing và sub-agents on-demand.
4
4
 
5
- [![version](https://img.shields.io/badge/version-1.12.0-blue.svg)](./VERSION)
5
+ [![version](https://img.shields.io/badge/version-2.3.0-blue.svg)](./VERSION)
6
6
  [![docs](https://img.shields.io/badge/docs-Vietnamese-green.svg)](./docs/INDEX.md)
7
7
  [![platform](https://img.shields.io/badge/platform-macOS%20|%20Linux%20|%20Windows-lightgrey.svg)]()
8
8
  [![npm](https://img.shields.io/npm/v/openmoneta-dev-kit)](https://www.npmjs.com/package/openmoneta-dev-kit)
@@ -13,16 +13,18 @@
13
13
  npm install -g openmoneta-dev-kit && openmoneta install
14
14
  ```
15
15
 
16
- 1 lệnh cài cho cả Cursor + OpenCode. Sau đó khởi tạo project:
16
+ 1 lệnh cài cho cả Cursor + OpenCode. Dùng Claude Code? Cài thêm `openmoneta install --claude`. Sau đó khởi tạo project:
17
17
 
18
18
  ```bash
19
19
  cd /path/to/project
20
20
  openmoneta init
21
+ openmoneta init --claude # nếu dùng Claude Code (tạo shim CLAUDE.md)
21
22
  ```
22
23
 
23
24
  | Lệnh mới | Tương đương lệnh cũ |
24
25
  |---|---|
25
26
  | `openmoneta install` | `install.sh` + `install-opencode.sh` |
27
+ | `openmoneta install --claude` | `install-claude-code.sh` |
26
28
  | `openmoneta init` | `init-project.sh .` |
27
29
  | `openmoneta check` | `update.sh --check` |
28
30
  | `openmoneta update --yes` | `update.sh --yes` |
@@ -58,13 +60,14 @@ bash ~/OpenMoneta-Dev-Kit/install.sh
58
60
  - **11 skills** (4 core + 1 core conditional + 6 on-demand) — phân tích yêu cầu, thiết kế module, plan, systematic debugging, safe push, test, security, bảo trì docs
59
61
  - **`openmoneta docs`** — audit module README thiếu/lỗi thời (stale) + skill `docs-maintenance` backfill docs cho dự án cũ
60
62
  - **4 sub-agents** — 1 core + 3 on-demand (security-auditor, qa-autonomous, ui-tester)
61
- - **4 hooks + plugin** — enforce token-aware reading, adaptive plan scope, và verify cuối phiên (module README + close plan); OpenCode đạt parity qua plugin guard `session.idle`
63
+ - **4 hooks + plugin + adapter** — enforce token-aware reading, adaptive plan scope, và verify cuối phiên (module README + close plan); OpenCode đạt parity qua plugin guard `session.idle`, Claude Code qua hook adapter mỏng tái dùng bash hooks gốc
62
64
  - **Token Routing** — bảng map keyword → module giúp AI giảm 70-90% token đọc
63
65
  - **npm package** — `npm install -g openmoneta-dev-kit`, không cần git, không cần clone
64
66
  - **Auto-update check** — notify khi có version mới (cache 24h)
65
67
  - **Adaptive Planning** — task nhỏ không cần plan; task lớn/rủi ro tạo plan Draft, user review
66
68
  - **Safe Push** — sync remote trước push, không đè code người khác
67
69
  - **OpenCode Support** — global rules/skills/agents + plugin guard
70
+ - **Claude Code Support** — hook adapter + manifest install vào `~/.claude/` (không đụng skills/agents riêng của user) + shim `CLAUDE.md` → `@AGENTS.md` ([docs/12-claude-code.md](./docs/12-claude-code.md))
68
71
 
69
72
  ## Đóng góp
70
73
 
package/VERSION CHANGED
@@ -1 +1 @@
1
- 2.2.1
1
+ 2.3.1
@@ -0,0 +1,39 @@
1
+ ---
2
+ name: qa-autonomous
3
+ description: ON-DEMAND ONLY. Dùng khi user explicitly yêu cầu viết unit/integration test. KHÔNG tự trigger trong quy trình bình thường.
4
+ ---
5
+
6
+ Bạn là **qa-autonomous** của OpenMoneta Dev Kit trong Claude Code.
7
+
8
+ Chỉ dùng khi user yêu cầu viết test hoặc primary agent cần isolation cho test loop.
9
+
10
+ ## Workflow
11
+
12
+ 1. Đọc plan active và Acceptance Criteria/Test Plan nếu có.
13
+ 2. Đọc skill `test-strategy` nếu available.
14
+ 3. Phát hiện stack qua config (`package.json`, `pyproject.toml`, `go.mod`, ...).
15
+ 4. Viết test focused theo behavior, không skip test.
16
+ 5. Chạy test liên quan, đọc lỗi đầy đủ, fix root cause, retest.
17
+ 6. Dừng sau tối đa 5 vòng nếu không fix được, báo root cause và blocker.
18
+
19
+ ## Quy tắc
20
+
21
+ - Fix code khi code sai; chỉ sửa test khi assertion/test setup sai.
22
+ - Không dùng `.skip`, `xit`, comment-out test để pass.
23
+ - Một lần thay đổi, một lần verify.
24
+
25
+ ## Output
26
+
27
+ ```markdown
28
+ ## QA Result
29
+
30
+ PASS | FAIL
31
+
32
+ - Tool:
33
+ - Attempts:
34
+ - Tests added/changed:
35
+ - AC verified:
36
+ - Blocker nếu fail:
37
+ ```
38
+
39
+ Luôn trả lời bằng tiếng Việt.
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: requirement-analyst
3
+ description: Dùng proactively khi user request mơ hồ, lớn (>5 file ảnh hưởng), hoặc cần explore rộng codebase/tài liệu để hiểu impact trước khi lập plan. Read-only, không code.
4
+ tools: Read, Grep, Glob
5
+ ---
6
+
7
+ Bạn là **requirement-analyst** của OpenMoneta Dev Kit trong Claude Code.
8
+
9
+ ## Vai trò
10
+
11
+ Bạn được gọi khi yêu cầu user **mơ hồ hoặc lớn**, cần đọc nhiều tài liệu/codebase mà không tốn context của parent. Bạn KHÔNG code, KHÔNG edit file. Output là **báo cáo phân tích + danh sách câu hỏi** để parent đem hỏi user.
12
+
13
+ ## Workflow
14
+
15
+ 1. Đọc `docs/INDEX.md` của workspace (nếu có) — luôn ưu tiên đầu tiên.
16
+ 2. Đọc `plans/INDEX.md` để kiểm tra plan active/overlap.
17
+ 3. Đọc module README liên quan qua Token Routing (`docs/modules/<name>/README.md`).
18
+ 4. Đọc source vừa đủ để hiểu impact, KHÔNG scan toàn bộ repo.
19
+ 5. Tóm tắt yêu cầu, giả thuyết, edge cases, rủi ro, impact.
20
+ 6. Đề xuất câu hỏi critical: làm rõ yêu cầu, phân tích mọi trường hợp, phản biện và đề xuất phương án tối ưu hơn nếu có. Mỗi câu có 2-4 options với trade-off; KHÔNG hỏi câu user đã ngầm trả lời.
21
+
22
+ ## Output
23
+
24
+ ```markdown
25
+ # Requirement Analysis Report
26
+
27
+ ## Yêu cầu (diễn đạt lại)
28
+ <1 đoạn>
29
+
30
+ ## Giả thuyết
31
+ - ...
32
+
33
+ ## Edge cases
34
+ - ...
35
+
36
+ ## Rủi ro
37
+ - ...
38
+
39
+ ## Impact
40
+ | File/Module | Mức độ | Ghi chú |
41
+ |---|---|---|
42
+ | ... | High/Med/Low | ... |
43
+
44
+ ## Câu hỏi đề xuất hỏi user
45
+ 1. ...
46
+
47
+ ## Khuyến nghị tiếp theo
48
+ <hỏi user / đủ info để tạo plan / đủ info để code>
49
+ ```
50
+
51
+ Luôn trả lời bằng tiếng Việt, súc tích — parent sẽ đọc và đem đi tiếp, đừng lan man.
@@ -0,0 +1,44 @@
1
+ ---
2
+ name: security-auditor
3
+ description: ON-DEMAND ONLY. Dùng khi user yêu cầu security audit (OWASP, scan secrets, dependency CVE) hoặc task chạm auth/payment/PII cần audit độc lập. Read-only, không sửa file.
4
+ tools: Read, Grep, Glob, Bash
5
+ ---
6
+
7
+ Bạn là **security-auditor** của OpenMoneta Dev Kit trong Claude Code.
8
+
9
+ Chỉ dùng khi user yêu cầu security audit hoặc task chạm auth/payment/PII/admin/permission và primary agent muốn audit độc lập.
10
+
11
+ ## Workflow
12
+
13
+ 1. Xác định scope từ `.cursor/.session-changes.json` nếu có, hoặc từ plan active trong `plans/`.
14
+ 2. Audit OWASP Top 10 trong phạm vi file liên quan.
15
+ 3. Scan secrets bằng công cụ read-only (`rg`, `git ls-files`, audit package manager nếu phù hợp).
16
+ 4. Chỉ report HIGH/CRITICAL dependency CVE nếu có.
17
+ 5. KHÔNG sửa file. Bash chỉ dùng cho lệnh read-only (rg/git/audit).
18
+
19
+ ## Output
20
+
21
+ ```markdown
22
+ # Security Audit Report
23
+
24
+ ## Scope
25
+ - ...
26
+
27
+ ## OWASP Checklist
28
+ - A01 Access Control: Pass/Issue/N/A — ...
29
+ - ...
30
+
31
+ ## Secrets Scan
32
+ - ...
33
+
34
+ ## Dependency CVE
35
+ - ...
36
+
37
+ ## Recommendations
38
+ 1. ...
39
+
40
+ ## Verdict
41
+ PASS | FAIL — <kết luận ngắn>
42
+ ```
43
+
44
+ Luôn trả lời bằng tiếng Việt.
@@ -0,0 +1,40 @@
1
+ ---
2
+ name: ui-tester
3
+ description: ON-DEMAND ONLY. Dùng khi user yêu cầu UI test (Playwright multi-viewport mobile/tablet/desktop, visual regression, fix CSS rồi retest). KHÔNG tự trigger trong quy trình bình thường.
4
+ ---
5
+
6
+ Bạn là **ui-tester** của OpenMoneta Dev Kit trong Claude Code.
7
+
8
+ Chỉ dùng khi user yêu cầu UI test, visual regression, hoặc test-fix giao diện.
9
+
10
+ ## Workflow
11
+
12
+ 1. Đọc plan active hoặc yêu cầu user để xác định AC UI.
13
+ 2. Kiểm tra Playwright đã cài chưa; nếu chưa, hỏi/đề xuất cài.
14
+ 3. Chạy multi-viewport: mobile, tablet, desktop.
15
+ 4. Lưu screenshot vào `tests/screenshots/<slug>/iter-<n>/`.
16
+ 5. Đọc lỗi/screenshot, fix CSS/component, retest.
17
+ 6. Sau mỗi 2 vòng, tóm tắt thay đổi và hỏi user nếu hướng visual chưa chắc chắn.
18
+ 7. Hard limit 5 vòng trước khi escalate.
19
+
20
+ ## Quy tắc
21
+
22
+ - Screenshot thật, không đoán bằng đọc code.
23
+ - Không sửa test để né lỗi visual thật.
24
+ - Cleanup state tạm khi hoàn tất.
25
+
26
+ ## Output
27
+
28
+ ```markdown
29
+ ## UI Test Result
30
+
31
+ PASS | FAIL
32
+
33
+ - Viewports:
34
+ - Screenshots:
35
+ - Attempts:
36
+ - Issues fixed:
37
+ - Blocker nếu fail:
38
+ ```
39
+
40
+ Luôn trả lời bằng tiếng Việt.
@@ -0,0 +1,112 @@
1
+ #!/usr/bin/env bash
2
+ # bash-guard.sh — Claude Code PreToolUse (matcher: Bash).
3
+ # Chặn shell command đọc/search source TRƯỚC khi đọc docs/INDEX.md (và docs/decisions/
4
+ # nếu project có Decision Memory). Port từ openmoneta-guard.ts v1.8.6 (OpenCode).
5
+ #
6
+ # Phạm vi: CHỈ chặn search/read (rg|grep|find|fd|ls|tree|cat|sed|awk|head|tail).
7
+ # Write-qua-shell (tee, redirect, sed -i vào file) là known limitation v1 — xem ADR-0009.
8
+ #
9
+ # Output: deny qua hookSpecificOutput; cho qua = exit 0 KHÔNG output (không auto-approve).
10
+
11
+ set -euo pipefail
12
+
13
+ INPUT_JSON=$(cat 2>/dev/null || echo '{}')
14
+ command -v jq >/dev/null 2>&1 || exit 0
15
+
16
+ TOOL_NAME=$(echo "$INPUT_JSON" | jq -r '.tool_name // ""')
17
+ [[ "$TOOL_NAME" == "Bash" ]] || exit 0
18
+
19
+ CWD=$(echo "$INPUT_JSON" | jq -r '.cwd // ""')
20
+ COMMAND=$(echo "$INPUT_JSON" | jq -r '.tool_input.command // ""')
21
+ [[ -z "$CWD" || -z "$COMMAND" ]] && exit 0
22
+
23
+ # Project không dùng OpenMoneta → bỏ qua.
24
+ INDEX_FILE="$CWD/docs/INDEX.md"
25
+ [[ -f "$INDEX_FILE" ]] || exit 0
26
+
27
+ MARKER="$CWD/.cursor/.docs-index-read"
28
+ DECISIONS_INDEX="$CWD/docs/decisions/INDEX.md"
29
+ DECISIONS_MARKER="$CWD/.cursor/.decisions-read"
30
+
31
+ deny() {
32
+ local msg="$1"
33
+ jq -n --arg msg "$msg" '{
34
+ hookSpecificOutput: {
35
+ hookEventName: "PreToolUse",
36
+ permissionDecision: "deny",
37
+ permissionDecisionReason: $msg
38
+ }
39
+ }'
40
+ exit 0
41
+ }
42
+
43
+ NORMALIZED=$(printf '%s' "$COMMAND" | tr '\n' ' ')
44
+
45
+ # Command tự đọc docs/INDEX.md → set marker, cho qua.
46
+ case "$NORMALIZED" in
47
+ *"docs/INDEX.md"*)
48
+ mkdir -p "$CWD/.cursor"
49
+ touch "$MARKER"
50
+ exit 0
51
+ ;;
52
+ esac
53
+
54
+ # Command đọc docs/decisions/ → set decisions marker, cho qua.
55
+ case "$NORMALIZED" in
56
+ *"docs/decisions"*)
57
+ mkdir -p "$CWD/.cursor"
58
+ touch "$DECISIONS_MARKER"
59
+ exit 0
60
+ ;;
61
+ esac
62
+
63
+ # Không phải lệnh search/read → cho qua (giữ phạm vi hẹp, tránh false positive).
64
+ if ! printf '%s' "$NORMALIZED" | grep -qE '(^|[;&|() ])(rg|grep|find|fd|ls|tree|cat|sed|awk|head|tail)([ ]|$)'; then
65
+ exit 0
66
+ fi
67
+
68
+ # Allowlist (SAFE_READ_HINTS — parity openmoneta-guard.ts): command nhắm vào docs/config → cho qua,
69
+ # TRỪ KHI command cũng chứa source hint (vd `rg foo src/ docs/`).
70
+ HAS_SOURCE_HINT=0
71
+ case "$NORMALIZED" in
72
+ *"apps/"*|*"packages/"*|*"src/"*|*"lib/"*|*"components/"*|*"server/"*|*"modules/"*|*"pages/"*|*"/app/"*)
73
+ HAS_SOURCE_HINT=1
74
+ ;;
75
+ esac
76
+
77
+ if [[ "$HAS_SOURCE_HINT" -eq 0 ]]; then
78
+ case "$NORMALIZED" in
79
+ *"docs/"*|*"plans/"*|*".cursor/"*|*".opencode/"*|*".claude/"*|*".github/"*|*".vscode/"*|*"AGENTS.md"*|*"CLAUDE.md"*|*"README"*|*"CHANGELOG"*|*"LICENSE"*|*"package.json"*|*"tsconfig"*|*"vite.config"*|*"playwright.config"*|*"biome.config"*|*"vitest.config"*|*"astro.config"*|*".gitignore"*|*"Dockerfile"*)
80
+ exit 0
81
+ ;;
82
+ esac
83
+ fi
84
+
85
+ # === Gate 1: docs-first ===
86
+ if [[ ! -f "$MARKER" ]]; then
87
+ deny "Bạn đang chạy shell command đọc/search source code TRƯỚC khi đọc docs/INDEX.md. Vi phạm token-aware reading (skill requirement-analysis Bước 1).
88
+
89
+ Command bị chặn: $COMMAND
90
+
91
+ QUY TRÌNH ĐÚNG (BẮT BUỘC, theo thứ tự):
92
+ 1. Read $CWD/docs/INDEX.md TRƯỚC TIÊN.
93
+ 2. Tìm keyword task trong bảng 'Feature/Keyword → Module' để biết module liên quan.
94
+ 3. Read docs/modules/<matched-module>/README.md cho mỗi module liên quan.
95
+ 4. CHỈ rồi mới search/read source code của module đó.
96
+
97
+ Sau khi đọc docs/INDEX.md, marker .cursor/.docs-index-read được set và mọi command source khác trong session sẽ được cho qua."
98
+ fi
99
+
100
+ # === Gate 2: decisions-read (Decision Memory / chống flip-flop kiến trúc) ===
101
+ if [[ -f "$DECISIONS_INDEX" && ! -f "$DECISIONS_MARKER" ]]; then
102
+ deny "Bạn đang chạy shell command search source code TRƯỚC khi đọc docs/decisions/ (trí nhớ quyết định kiến trúc). Vi phạm Bước 1 (skill requirement-analysis 1.3b).
103
+
104
+ Command bị chặn: $COMMAND
105
+
106
+ HÀNH ĐỘNG NGAY:
107
+ → Read $DECISIONS_INDEX (set marker .cursor/.decisions-read), tìm ADR liên quan tới module bạn sắp đụng, đọc ADR đó nếu định đổi kiến trúc, sau đó retry command.
108
+
109
+ LƯU Ý: Muốn ĐỔI/ĐẢO kiến trúc đã Accepted → phải supersede tường minh (skill decision-recorder), KHÔNG revert lặng lẽ."
110
+ fi
111
+
112
+ exit 0
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env bash
2
+ # posttooluse-adapter.sh — Claude Code PostToolUse (Edit|Write|NotebookEdit) → core/track-changes.sh.
3
+ # Silent track file đã sửa vào <workspace>/.cursor/.session-changes.json (verify-completion dùng).
4
+
5
+ set -euo pipefail
6
+
7
+ INPUT_JSON=$(cat 2>/dev/null || echo '{}')
8
+ command -v jq >/dev/null 2>&1 || exit 0
9
+
10
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
+ CORE_DIR="${OPENMONETA_CORE_HOOKS:-$SCRIPT_DIR/core}"
12
+ CORE_HOOK="$CORE_DIR/track-changes.sh"
13
+ [[ -f "$CORE_HOOK" ]] || exit 0
14
+
15
+ TOOL_NAME=$(echo "$INPUT_JSON" | jq -r '.tool_name // ""')
16
+ CWD=$(echo "$INPUT_JSON" | jq -r '.cwd // ""')
17
+ [[ -z "$TOOL_NAME" || -z "$CWD" ]] && exit 0
18
+
19
+ case "$TOOL_NAME" in
20
+ Write|Edit|NotebookEdit) ;;
21
+ *) exit 0 ;;
22
+ esac
23
+
24
+ case "$TOOL_NAME" in
25
+ Edit) MAPPED_TOOL="StrReplace" ;;
26
+ NotebookEdit) MAPPED_TOOL="EditNotebook" ;;
27
+ *) MAPPED_TOOL="Write" ;;
28
+ esac
29
+
30
+ CURSOR_INPUT=$(echo "$INPUT_JSON" | jq --arg tool "$MAPPED_TOOL" --arg cwd "$CWD" '{
31
+ tool_name: $tool,
32
+ tool_input: ((.tool_input // {}) + (if (.tool_input.notebook_path // "") != "" then {target_notebook: .tool_input.notebook_path} else {} end)),
33
+ workspace_roots: [$cwd]
34
+ }')
35
+
36
+ # Silent — không decision, không message.
37
+ echo "$CURSOR_INPUT" | bash "$CORE_HOOK" >/dev/null 2>&1 || true
38
+ exit 0
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env bash
2
+ # pretooluse-adapter.sh — Claude Code PreToolUse → bash hooks Cursor (single source of truth).
3
+ #
4
+ # Map:
5
+ # Read|Glob|Grep → core/enforce-docs-first.sh
6
+ # Write|Edit|NotebookEdit → core/check-plan-exists.sh (Edit→StrReplace, NotebookEdit→EditNotebook)
7
+ #
8
+ # Ngữ nghĩa permission (QUAN TRỌNG):
9
+ # - Hook gốc trả {"permission":"deny"} → output hookSpecificOutput.permissionDecision="deny".
10
+ # - Hook gốc trả {"permission":"allow"} → exit 0 KHÔNG output. Với Claude Code,
11
+ # permissionDecision="allow" nghĩa là AUTO-APPROVE (bỏ qua permission dialog) —
12
+ # adapter tuyệt đối không được phát "allow" để không vô hiệu hóa permission system.
13
+
14
+ set -euo pipefail
15
+
16
+ INPUT_JSON=$(cat 2>/dev/null || echo '{}')
17
+
18
+ # Không có jq → fail-open giống hooks gốc (không block agent).
19
+ command -v jq >/dev/null 2>&1 || exit 0
20
+
21
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
22
+ CORE_DIR="${OPENMONETA_CORE_HOOKS:-$SCRIPT_DIR/core}"
23
+
24
+ TOOL_NAME=$(echo "$INPUT_JSON" | jq -r '.tool_name // ""')
25
+ CWD=$(echo "$INPUT_JSON" | jq -r '.cwd // ""')
26
+ [[ -z "$TOOL_NAME" || -z "$CWD" ]] && exit 0
27
+
28
+ case "$TOOL_NAME" in
29
+ Read|Glob|Grep)
30
+ CORE_HOOK="$CORE_DIR/enforce-docs-first.sh"
31
+ MAPPED_TOOL="$TOOL_NAME"
32
+ ;;
33
+ Write|Edit|NotebookEdit)
34
+ CORE_HOOK="$CORE_DIR/check-plan-exists.sh"
35
+ case "$TOOL_NAME" in
36
+ Edit) MAPPED_TOOL="StrReplace" ;;
37
+ NotebookEdit) MAPPED_TOOL="EditNotebook" ;;
38
+ *) MAPPED_TOOL="Write" ;;
39
+ esac
40
+ ;;
41
+ *)
42
+ exit 0
43
+ ;;
44
+ esac
45
+
46
+ [[ -f "$CORE_HOOK" ]] || exit 0
47
+
48
+ # Build input Cursor-format. NotebookEdit: notebook_path → target_notebook (field hooks gốc parse).
49
+ CURSOR_INPUT=$(echo "$INPUT_JSON" | jq --arg tool "$MAPPED_TOOL" --arg cwd "$CWD" '{
50
+ tool_name: $tool,
51
+ tool_input: ((.tool_input // {}) + (if (.tool_input.notebook_path // "") != "" then {target_notebook: .tool_input.notebook_path} else {} end)),
52
+ workspace_roots: [$cwd]
53
+ }')
54
+
55
+ CORE_OUTPUT=$(echo "$CURSOR_INPUT" | bash "$CORE_HOOK" 2>/dev/null || echo '{"permission": "allow"}')
56
+
57
+ PERMISSION=$(echo "$CORE_OUTPUT" | jq -r '.permission // "allow"' 2>/dev/null || echo "allow")
58
+
59
+ if [[ "$PERMISSION" == "deny" ]]; then
60
+ echo "$CORE_OUTPUT" | jq '{
61
+ hookSpecificOutput: {
62
+ hookEventName: "PreToolUse",
63
+ permissionDecision: "deny",
64
+ permissionDecisionReason: (.agent_message // "Blocked by OpenMoneta Dev Kit hook.")
65
+ }
66
+ }'
67
+ fi
68
+
69
+ exit 0
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env bash
2
+ # sessionstart-adapter.sh — Claude Code SessionStart → core/inject-process-context.sh.
3
+ #
4
+ # Khác Cursor 2 điểm chủ đích:
5
+ # 1. CHỈ reset markers (.docs-index-read / .decisions-read) khi source = startup|clear.
6
+ # Claude Code còn fire SessionStart ở resume/compact GIỮA phiên làm việc — reset lúc đó
7
+ # sẽ chặn oan agent đang làm dở task.
8
+ # 2. KHÔNG inject lại full quy trình 6 bước (OPENMONETA_SKIP_SUMMARY=1) — project đã nạp
9
+ # quy trình qua CLAUDE.md → @AGENTS.md, inject nữa là nạp đôi tốn token.
10
+ # Chỉ output update notice (nếu có) — stdout của SessionStart được đưa vào context.
11
+
12
+ set -euo pipefail
13
+
14
+ INPUT_JSON=$(cat 2>/dev/null || echo '{}')
15
+ command -v jq >/dev/null 2>&1 || exit 0
16
+
17
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
18
+ CORE_DIR="${OPENMONETA_CORE_HOOKS:-$SCRIPT_DIR/core}"
19
+ CORE_HOOK="$CORE_DIR/inject-process-context.sh"
20
+ [[ -f "$CORE_HOOK" ]] || exit 0
21
+
22
+ CWD=$(echo "$INPUT_JSON" | jq -r '.cwd // ""')
23
+ SOURCE=$(echo "$INPUT_JSON" | jq -r '.source // "startup"')
24
+ [[ -z "$CWD" ]] && exit 0
25
+
26
+ case "$SOURCE" in
27
+ startup|clear) ;;
28
+ *) exit 0 ;; # resume|compact: giữ nguyên markers, không inject gì thêm
29
+ esac
30
+
31
+ CLAUDE_HOME="${OPENMONETA_HOME:-$HOME/.claude}"
32
+
33
+ CURSOR_INPUT=$(jq -n --arg cwd "$CWD" '{workspace_roots: [$cwd]}')
34
+
35
+ # Core hook: reset markers + auto-register registry (~/.claude/.openmoneta-projects)
36
+ # + check update notice (cache 24h). SKIP_SUMMARY để không nạp đôi quy trình.
37
+ CORE_OUTPUT=$(echo "$CURSOR_INPUT" | OPENMONETA_HOME="$CLAUDE_HOME" OPENMONETA_SKIP_SUMMARY=1 bash "$CORE_HOOK" 2>/dev/null || echo '{}')
38
+
39
+ NOTICE=$(echo "$CORE_OUTPUT" | jq -r '.additional_context // ""' 2>/dev/null || echo "")
40
+ if [[ -n "$NOTICE" ]]; then
41
+ printf '%s\n' "$NOTICE"
42
+ fi
43
+
44
+ exit 0
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env bash
2
+ # stop-adapter.sh — Claude Code Stop → core/verify-completion.sh (block cứng như Cursor).
3
+ #
4
+ # verify-completion.sh nhận loop_count từ harness Cursor; Claude Code không có sẵn nên
5
+ # adapter tự đếm qua state file key theo session_id (2 session song song đếm độc lập):
6
+ # <workspace>/.cursor/.claude-stop-loop-<session_id>.json
7
+ # Pass → xóa state. Fail → tăng count; core hook tự graceful escape khi count >= 4.
8
+ #
9
+ # Output khi block: {"decision": "block", "reason": ...} — Claude tiếp tục làm việc.
10
+
11
+ set -euo pipefail
12
+
13
+ INPUT_JSON=$(cat 2>/dev/null || echo '{}')
14
+ command -v jq >/dev/null 2>&1 || exit 0
15
+
16
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
17
+ CORE_DIR="${OPENMONETA_CORE_HOOKS:-$SCRIPT_DIR/core}"
18
+ CORE_HOOK="$CORE_DIR/verify-completion.sh"
19
+ [[ -f "$CORE_HOOK" ]] || exit 0
20
+
21
+ CWD=$(echo "$INPUT_JSON" | jq -r '.cwd // ""')
22
+ SESSION_ID=$(echo "$INPUT_JSON" | jq -r '.session_id // "default"')
23
+ STOP_HOOK_ACTIVE=$(echo "$INPUT_JSON" | jq -r '.stop_hook_active // false')
24
+ [[ -z "$CWD" ]] && exit 0
25
+
26
+ # Sanitize session_id cho tên file.
27
+ SESSION_KEY=$(printf '%s' "$SESSION_ID" | tr -c 'a-zA-Z0-9_-' '_')
28
+ STATE_FILE="$CWD/.cursor/.claude-stop-loop-${SESSION_KEY}.json"
29
+
30
+ LOOP_COUNT=0
31
+ if [[ "$STOP_HOOK_ACTIVE" == "true" && -f "$STATE_FILE" ]]; then
32
+ LOOP_COUNT=$(jq -r '.count // 0' "$STATE_FILE" 2>/dev/null || echo 0)
33
+ fi
34
+
35
+ CURSOR_INPUT=$(jq -n --arg cwd "$CWD" --argjson lc "$LOOP_COUNT" '{
36
+ workspace_roots: [$cwd],
37
+ loop_count: $lc
38
+ }')
39
+
40
+ # OPENMONETA_HOME=~/.claude để core hook tìm scripts/list-affected-modules.sh
41
+ # trong claude home (máy chỉ có Claude Code không có ~/.cursor/scripts).
42
+ CORE_OUTPUT=$(echo "$CURSOR_INPUT" | OPENMONETA_HOME="${OPENMONETA_HOME:-$HOME/.claude}" bash "$CORE_HOOK" 2>/dev/null || echo '{"continue": true}')
43
+
44
+ # Lưu ý: KHÔNG dùng `.continue // true` — toán tử `//` của jq coi `false` như null
45
+ # nên `false // true` ra `true` (mất tín hiệu block).
46
+ CONTINUE=$(echo "$CORE_OUTPUT" | jq -r 'if .continue == false then "false" else "true" end' 2>/dev/null || echo "true")
47
+
48
+ if [[ "$CONTINUE" == "false" ]]; then
49
+ mkdir -p "$CWD/.cursor"
50
+ jq -n --argjson c "$((LOOP_COUNT + 1))" '{count: $c}' > "$STATE_FILE" 2>/dev/null || true
51
+ echo "$CORE_OUTPUT" | jq '{
52
+ decision: "block",
53
+ reason: (.followup_message // "Session chưa hoàn tất theo quy trình OpenMoneta (Bước 5).")
54
+ }'
55
+ exit 0
56
+ fi
57
+
58
+ # Pass → dọn state để session sau đếm lại từ 0.
59
+ rm -f "$STATE_FILE" 2>/dev/null || true
60
+ exit 0
@@ -0,0 +1,55 @@
1
+ {
2
+ "hooks": {
3
+ "SessionStart": [
4
+ {
5
+ "hooks": [
6
+ {
7
+ "type": "command",
8
+ "command": "bash \"$HOME/.claude/hooks/openmoneta/sessionstart-adapter.sh\""
9
+ }
10
+ ]
11
+ }
12
+ ],
13
+ "PreToolUse": [
14
+ {
15
+ "matcher": "Read|Glob|Grep|Write|Edit|NotebookEdit",
16
+ "hooks": [
17
+ {
18
+ "type": "command",
19
+ "command": "bash \"$HOME/.claude/hooks/openmoneta/pretooluse-adapter.sh\""
20
+ }
21
+ ]
22
+ },
23
+ {
24
+ "matcher": "Bash",
25
+ "hooks": [
26
+ {
27
+ "type": "command",
28
+ "command": "bash \"$HOME/.claude/hooks/openmoneta/bash-guard.sh\""
29
+ }
30
+ ]
31
+ }
32
+ ],
33
+ "PostToolUse": [
34
+ {
35
+ "matcher": "Write|Edit|NotebookEdit",
36
+ "hooks": [
37
+ {
38
+ "type": "command",
39
+ "command": "bash \"$HOME/.claude/hooks/openmoneta/posttooluse-adapter.sh\""
40
+ }
41
+ ]
42
+ }
43
+ ],
44
+ "Stop": [
45
+ {
46
+ "hooks": [
47
+ {
48
+ "type": "command",
49
+ "command": "bash \"$HOME/.claude/hooks/openmoneta/stop-adapter.sh\""
50
+ }
51
+ ]
52
+ }
53
+ ]
54
+ }
55
+ }