refactor(plugin): clarify UserPromptSubmit bootstrap architecture#1388
Merged
Conversation
The plugin uses two distinct hook layers: plugin-local hooks.json for SessionStart/PreToolUse/PostToolUse/Stop, and a SessionStart-driven global install in ~/.claude/settings.json for UserPromptSubmit. Because UserPromptSubmit is absent from hooks.json, contributors auditing the package repeatedly mistake the missing entry for a bug (see #1380), when in fact session-start.py is the deliberate source of truth. Approach A (document + regression-test) was chosen over Approach B (migrate UserPromptSubmit into hooks.json and delete the global install). Rationale: - low risk: no behavior change, only comments + docs + tests - preserves the global-scope semantics for PLAN/ACT/EVAL/AUTO keyword detection (fires in any session, not just CodingBuddy projects) - keeps file footprint separate from #1381 (stale legacy hook cleanup), which must remain parallel-safe until that migration lands - Approach B remains viable as a future follow-up once #1381 is done Changes: - hooks/hooks.json: add top-level $comment field pointing contributors to session-start.py and bootstrap-architecture.md - hooks/session-start.py: expand module docstring to name the bootstrap role and document the two-layer architecture; expand register_hook_in_settings docstring with the why behind global install - docs/bootstrap-architecture.md: new long-form document covering both layers, rationale, source-of-truth cheat sheet, and drift safeguards - tests/test_bootstrap_architecture.py: 18 regression tests locking the invariants (hooks.json shape, $comment presence, session-start docstring, doc existence and contents) so future refactors can't silently drift between the layers Test plan: - yarn workspace codingbuddy-claude-plugin lint|format:check|typecheck - yarn workspace codingbuddy-claude-plugin test:coverage (123 passed) - python3 -m pytest tests/ (766 passed, +18 new bootstrap tests) - yarn workspace codingbuddy-claude-plugin circular|build Closes #1380
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
JeremyDev87
commented
Apr 5, 2026
JeremyDev87
left a comment
Owner
Author
There was a problem hiding this comment.
Review: APPROVE
CI Status: PASS
모든 28개 check 통과 — build, lint, typecheck, test, security, circular, e2e (hooks 3.11/3.12, docker), vercel preview 포함.
Local Verification: PASS
yarn workspace codingbuddy-claude-plugin lint ✅
yarn workspace codingbuddy-claude-plugin typecheck ✅
yarn workspace codingbuddy-claude-plugin test ✅ (123/123)
python3 -m pytest tests/ ✅ (766/766, incl. 18 new)
Severity Findings
- Critical (blocking): 없음
- High (must fix): 없음
- Medium (should fix): 없음
- Low (nice to have): 없음
문서/주석/테스트만 추가하는 순수 non-behavioral 변경이라 런타임 리스크 제로. 코드 품질 이슈 없음 (unused imports/any/dead code/security 모두 clean).
Spec Compliance (#1380 Acceptance Criteria)
-
Bootstrap architecture is clearly documented and testable
docs/bootstrap-architecture.md(신규, 115 lines): TL;DR 표, two-layer 설명, 글로벌 설치 근거, cheat sheet, 드리프트 세이프가드, 미래 단순화 노트까지 포괄- 18개 regression test로 invariant 잠금
-
Contributors can tell where UserPromptSubmit is registered
hooks/hooks.json에 top-level$comment필드로 session-start.py / bootstrap-architecture.md / #1380 포인터 제공hooks/session-start.py모듈 docstring이 bootstrap 역할과 two-layer 구조 명시register_hook_in_settings()docstring에 "왜 글로벌이어야 하는가" 근거(global scope semantics) 포함
-
If simplified, single path is explicit and regression-tested
리뷰어 노트 (정보 공유)
좋은 점:
- 드리프트 양방향 방어: "UserPromptSubmit이 hooks.json에 나타나면 fail" + "session-start.py에서 사라지면 fail" 두 방향 모두 테스트로 잠겨 있어 미래의 silent regression을 확실히 차단
- $comment 컨벤션 일관성: JSON Schema와 동일한 관례를 따르고, 테스트가 그 내용(session-start.py / UserPromptSubmit / bootstrap-architecture 문자열)을 강제해 주석의 의미가 퇴색되는 것도 막음
- 문서의 self-aware 톤: "If you are here because you opened hooks/hooks.json...you are not the first" — 실제 contributor 혼란 포인트를 정면에서 다룸
- Future simplification 섹션: 현 결정이 영구적이지 않음을 명시하고, Approach B로 넘어갈 조건(#1381 머지, Claude Code의 first-class global hook 지원)을 구체적으로 기록
소소한 관찰(블로커 아님, 수정 불필요):
- Python 테스트는 텍스트/구조 invariant만 검증 —
register_hook_in_settings()의 런타임 동작(파일 락, 멱등성)은 다른 파일에서 커버되는 것으로 보임. 이 PR 스코프에서는 적절. - 전체 접근이 "docs-as-code" 패턴을 잘 보여줌 — 향후 유사한 architectural decision에도 재사용할 만함.
Recommendation: APPROVE
스펙 준수 완벽, CI 전체 통과, 로컬 lint/typecheck/test/pytest 전체 통과, 코드 품질 이슈 없음, 회귀 방어 탄탄. 머지 가능.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The plugin uses two distinct hook layers and the split is not self-documenting:
hooks/hooks.json—SessionStart,PreToolUse,PostToolUse,Stophooks/session-start.pywrites aUserPromptSubmitentry into~/.claude/settings.jsonat every session startBecause
UserPromptSubmitis absent fromhooks.json, contributors auditing the package repeatedly mistake the missing entry for a bug. This PR clarifies the architecture without changing behavior.Approach A (document + regression-test) chosen over Approach B (migrate into hooks.json)
Changes
hooks/hooks.json: top-level\$commentfield pointing contributors atsession-start.pyand the new architecture dochooks/session-start.py: module docstring expanded to name the bootstrap role and two-layer architecture;register_hook_in_settingsdocstring expanded with the why behind global installdocs/bootstrap-architecture.md(new): long-form rationale, source-of-truth cheat sheet, drift safeguards, future-simplification notestests/test_bootstrap_architecture.py(new, 18 tests): invariant regression suite coveringhooks.jsonshape,\$commentpresence and contents,session-start.pydocstring, doc existence and required sectionsTest plan
yarn workspace codingbuddy-claude-plugin lintyarn workspace codingbuddy-claude-plugin format:checkyarn workspace codingbuddy-claude-plugin typecheckyarn workspace codingbuddy-claude-plugin test:coverage— 123 passedpython3 -m pytest tests/— 766 passed (incl. 18 new bootstrap tests)yarn workspace codingbuddy-claude-plugin circularyarn workspace codingbuddy-claude-plugin buildyarn workspace codingbuddy npm audit --severity highyarn workspace codingbuddy-claude-plugin npm audit --severity highyarn workspace landing-page npm audit --severity highVerification (RED → GREEN evidence)
Before the changes, 5 bootstrap tests failed + 4 errored (18 total, 9 passing) — confirming the invariants the suite is meant to enforce were not yet in place. After the documentation/comment changes, all 18 pass.
Closes #1380