Skip to content

refactor(plugin): clarify UserPromptSubmit bootstrap architecture#1388

Merged
JeremyDev87 merged 1 commit into
masterfrom
taskmaestro/1775394949/pane-2
Apr 5, 2026
Merged

refactor(plugin): clarify UserPromptSubmit bootstrap architecture#1388
JeremyDev87 merged 1 commit into
masterfrom
taskmaestro/1775394949/pane-2

Conversation

@JeremyDev87

Copy link
Copy Markdown
Owner

Summary

The plugin uses two distinct hook layers and the split is not self-documenting:

  1. plugin-local hooks/hooks.jsonSessionStart, PreToolUse, PostToolUse, Stop
  2. global installhooks/session-start.py writes a UserPromptSubmit entry into ~/.claude/settings.json at every session start

Because UserPromptSubmit is absent from hooks.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 \$comment field pointing contributors at session-start.py and the new architecture doc
  • hooks/session-start.py: module docstring expanded to name the bootstrap role and two-layer architecture; register_hook_in_settings docstring expanded with the why behind global install
  • docs/bootstrap-architecture.md (new): long-form rationale, source-of-truth cheat sheet, drift safeguards, future-simplification notes
  • tests/test_bootstrap_architecture.py (new, 18 tests): invariant regression suite covering hooks.json shape, \$comment presence and contents, session-start.py docstring, doc existence and required sections

Test plan

  • yarn workspace codingbuddy-claude-plugin lint
  • yarn workspace codingbuddy-claude-plugin format:check
  • yarn workspace codingbuddy-claude-plugin typecheck
  • yarn workspace codingbuddy-claude-plugin test:coverage — 123 passed
  • python3 -m pytest tests/ — 766 passed (incl. 18 new bootstrap tests)
  • yarn workspace codingbuddy-claude-plugin circular
  • yarn workspace codingbuddy-claude-plugin build
  • yarn workspace codingbuddy npm audit --severity high
  • yarn workspace codingbuddy-claude-plugin npm audit --severity high
  • yarn workspace landing-page npm audit --severity high

Verification (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

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
@JeremyDev87 JeremyDev87 added documentation Improvements or additions to documentation refactor plugin packages/claude-code-plugin labels Apr 5, 2026
@vercel

vercel Bot commented Apr 5, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
codingbuddy-landing Ready Ready Preview, Comment Apr 5, 2026 1:41pm

@JeremyDev87 JeremyDev87 left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

    • PR은 Approach A (문서 + 회귀 테스트) 채택 — 의도적으로 현 아키텍처 유지
    • 근거: global scope semantics 보존, #1381 stale cleanup과 병렬 충돌 방지, 저위험
    • Approach B(단일 경로 마이그레이션)는 #1381 머지 이후 follow-up으로 명시적 연기
    • 선택된 two-layer 상태가 18개 테스트로 잠겨 있어 양방향 드리프트(하나에서 사라지거나 양쪽에 중복) 모두 감지

리뷰어 노트 (정보 공유)

좋은 점:

  • 드리프트 양방향 방어: "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 전체 통과, 코드 품질 이슈 없음, 회귀 방어 탄탄. 머지 가능.

@JeremyDev87 JeremyDev87 merged commit e9480ee into master Apr 5, 2026
29 checks passed
@JeremyDev87 JeremyDev87 deleted the taskmaestro/1775394949/pane-2 branch April 5, 2026 13:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation plugin packages/claude-code-plugin refactor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor(plugin): clarify or simplify the UserPromptSubmit bootstrap architecture

1 participant