oh-my-customcode 1.1.39 → 1.1.41

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/dist/cli/index.js CHANGED
@@ -241,7 +241,7 @@ var init_package = __esm(() => {
241
241
  workspaces: [
242
242
  "packages/*"
243
243
  ],
244
- version: "1.1.39",
244
+ version: "1.1.41",
245
245
  description: "Batteries-included agent harness for Claude Code",
246
246
  type: "module",
247
247
  bin: {
package/dist/index.js CHANGED
@@ -2031,7 +2031,7 @@ var package_default = {
2031
2031
  workspaces: [
2032
2032
  "packages/*"
2033
2033
  ],
2034
- version: "1.1.39",
2034
+ version: "1.1.41",
2035
2035
  description: "Batteries-included agent harness for Claude Code",
2036
2036
  type: "module",
2037
2037
  bin: {
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "workspaces": [
4
4
  "packages/*"
5
5
  ],
6
- "version": "1.1.39",
6
+ "version": "1.1.41",
7
7
  "description": "Batteries-included agent harness for Claude Code",
8
8
  "type": "module",
9
9
  "bin": {
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bash
2
- # r007-r008-drift-advisor.sh — PROACTIVE R007/R008 drift advisory (#1229, #1545)
2
+ # r007-r008-drift-advisor.sh — PROACTIVE R007/R008 drift advisory (#1229, #1545, #1547)
3
3
  #
4
4
  # Wired to TWO trigger points:
5
5
  # 1. UserPromptSubmit — fires before Claude responds to a user-typed prompt (#1229).
@@ -10,51 +10,71 @@
10
10
  #
11
11
  # Inspects the LAST completed assistant turn in the session transcript for R007/R008
12
12
  # compliance BEFORE Claude responds. If the previous turn drifted (missing identification
13
- # header / tool prefix), emits a stderr advisory so the upcoming response self-corrects.
13
+ # header / tool prefix), delivers an advisory so the upcoming response self-corrects.
14
14
  #
15
15
  # This is the PROACTIVE complement to the retroactive session-reflection.sh (Stop hook, #1190).
16
16
  # Detection patterns are reused from session-reflection.sh.
17
17
  #
18
- # Advisory-only: ALWAYS exits 0, ALWAYS passes stdin through to stdout, NEVER blocks.
18
+ # Advisory-only: ALWAYS exits 0, NEVER blocks.
19
19
  # Performance: parses ONLY the last assistant turn (not the whole transcript).
20
20
  # Input-schema note: session_id/transcript_path are COMMON fields present on both
21
21
  # UserPromptSubmit and SubagentStop hook payloads, so the detection logic below is
22
22
  # event-agnostic and required no functional changes for the SubagentStop wiring.
23
23
  #
24
+ # Delivery mechanism (#1547 fix):
25
+ # Prior to this fix, the advisory was written to stderr with exit 0. Per the official
26
+ # Claude Code hook spec, stderr on exit 0 is NEVER fed into the model's context for ANY
27
+ # hook event (it is only visible in transcript debug mode, i.e. to a human, not Claude) —
28
+ # so #1545's SubagentStop wiring never actually reached the model despite firing correctly.
29
+ # The confirmed non-blocking delivery path for BOTH UserPromptSubmit and SubagentStop is
30
+ # `hookSpecificOutput.additionalContext` in JSON stdout with exit 0:
31
+ # {"hookSpecificOutput": {"hookEventName": "<event>", "additionalContext": "<text>"}}
32
+ # This is NOT the same as `"decision": "block"` — that would force Stop/SubagentStop to
33
+ # block (refuse to stop), which is exactly the blocking behavior R021 (advisory-first
34
+ # enforcement) forbids for this hook. additionalContext alone (no `decision` field) is
35
+ # non-blocking: Claude is allowed to stop/continue normally and simply sees the extra
36
+ # context on its next turn. Exit code MUST stay 0 — exit 2 causes Claude Code to discard
37
+ # any JSON output and treat stderr as a blocking error instead (see Common JSON Fields /
38
+ # Exit Code Behavior in the official hook reference).
39
+ # The stderr line is kept for human-visible audit trail (harmless on exit 0) but is no
40
+ # longer the delivery mechanism.
41
+ #
24
42
  # 환경변수 override (테스트/디버깅용):
25
43
  # OMCUSTOM_R007_ADVISOR=off — advisory 완전 비활성화 (pass-through)
26
44
  # OMCUSTOM_TRANSCRIPT_BASE — transcript 디렉토리 경로 override
27
45
 
28
46
  set -euo pipefail
29
47
 
30
- # ── UserPromptSubmit 프로토콜: stdin을 먼저 읽음 ──
48
+ # ── stdin 읽기 ──
31
49
  input=$(cat)
32
50
 
33
51
  # ── Opt-out 체크 ──
34
52
  if [ "${OMCUSTOM_R007_ADVISOR:-}" = "off" ]; then
35
- echo "$input"
36
53
  exit 0
37
54
  fi
38
55
 
39
56
  # ── jq 의존성 체크 ──
40
57
  if ! command -v jq >/dev/null 2>&1; then
41
- echo "$input"
42
58
  exit 0
43
59
  fi
44
60
 
45
61
  # ── session_id 추출 ──
46
62
  session_id=$(echo "$input" | jq -r '.session_id // empty' 2>/dev/null)
47
63
  if [ -z "$session_id" ]; then
48
- echo "$input"
49
64
  exit 0
50
65
  fi
51
66
 
67
+ # ── hook_event_name 추출 (hookSpecificOutput.hookEventName에 되돌려줄 값) ──
68
+ hook_event_name=$(echo "$input" | jq -r '.hook_event_name // empty' 2>/dev/null)
69
+ if [ -z "$hook_event_name" ]; then
70
+ hook_event_name="UserPromptSubmit"
71
+ fi
72
+
52
73
  # ── 경로 결정 (환경변수 override 지원) ──
53
74
  TRANSCRIPT_BASE="${OMCUSTOM_TRANSCRIPT_BASE:-${HOME}/.claude/projects/-Users-sangyi-workspace-projects-oh-my-customcode}"
54
75
  TRANSCRIPT_PATH="${TRANSCRIPT_BASE}/${session_id}.jsonl"
55
76
 
56
77
  if [ ! -f "$TRANSCRIPT_PATH" ]; then
57
- echo "$input"
58
78
  exit 0
59
79
  fi
60
80
 
@@ -70,7 +90,6 @@ while IFS= read -r line; do
70
90
  done < <(tail -r "$TRANSCRIPT_PATH" 2>/dev/null || tac "$TRANSCRIPT_PATH" 2>/dev/null)
71
91
 
72
92
  if [ -z "$last_assistant" ]; then
73
- echo "$input"
74
93
  exit 0
75
94
  fi
76
95
 
@@ -116,12 +135,21 @@ while [ "$i" -lt "$content_length" ]; do
116
135
  i=$((i+1))
117
136
  done
118
137
 
119
- # ── advisory 출력 (위반 시에만) ──
138
+ # ── advisory 전달 (위반 시에만) ──
120
139
  if [ "$r007_violations" -gt 0 ] || [ "$r008_violations" -gt 0 ]; then
121
- printf '[R007/R008 Advisory] 직전 응답에서 식별 누락 감지 (R007 헤더=%d, R008 접두사=%d). 이번 응답은 ┌─ Agent: 헤더로 시작하고, 모든 도구 호출에 [agent][model] → Tool: 접두사를 포함하십시오.\n' \
122
- "$r007_violations" "$r008_violations" >&2
140
+ advisory_text=$(printf '[R007/R008 Advisory] 직전 응답에서 식별 누락 감지 (R007 헤더=%d, R008 접두사=%d). 이번 응답은 ┌─ Agent: 헤더로 시작하고, 모든 도구 호출에 [agent][model] → Tool: 접두사를 포함하십시오.' \
141
+ "$r007_violations" "$r008_violations")
142
+
143
+ # 사람이 보는 감사 추적용 (exit 0에서는 모델에 전달되지 않음 — #1547 참고)
144
+ printf '%s\n' "$advisory_text" >&2
145
+
146
+ # #1547 fix: hookSpecificOutput.additionalContext로 모델 컨텍스트에 실제 전달.
147
+ # decision 필드는 절대 포함하지 않는다 — "block"을 쓰면 Stop/SubagentStop 정지를
148
+ # 강제로 막아버려 advisory-only 원칙(R021)을 위반하게 된다. exit code는 반드시 0.
149
+ jq -cn --arg event "$hook_event_name" --arg ctx "$advisory_text" \
150
+ '{hookSpecificOutput: {hookEventName: $event, additionalContext: $ctx}}'
123
151
  fi
124
152
 
125
- # ── 항상 stdin pass-through 후 exit 0 (advisory는 절대 차단 금지) ──
126
- echo "$input"
153
+ # ── 위반이 없으면 아무것도 출력하지 않는다 (오탐 방지) ──
154
+ # ── 항상 exit 0 (advisory는 절대 차단 금지) ──
127
155
  exit 0
@@ -14,7 +14,7 @@ oh-my-customcode uses an **advisory-first enforcement model**. Most rules are en
14
14
  | Soft Block | Stop hook prompt | R011 session-end saves | Auto-performs then approves |
15
15
  | Conversation Block | PostToolUse hook + `continueOnBlock` (CC v2.1.139+), exit 2 | stuck-detector, context-budget-advisor, cost-cap-advisor | Feeds rejection reason into conversation; Claude continues with awareness |
16
16
  | Advisory | PostToolUse hooks | R007, R008, R009, R010, R018 | Warns via stderr, never blocks |
17
- | Advisory (proactive) | UserPromptSubmit hook | R007, R008 (`r007-r008-drift-advisor.sh`, #1229) | Reads last assistant turn; emits stderr advisory before next response if header/prefix absent. Complements retroactive Stop-hook (`session-reflection.sh`, #1190). |
17
+ | Advisory (proactive) | UserPromptSubmit + SubagentStop hooks | R007, R008 (`r007-r008-drift-advisor.sh`, #1229 UserPromptSubmit; #1545 added SubagentStop) | Reads last assistant turn; emits stderr advisory if header/prefix absent. SubagentStop wiring (#1545) closes a structural gap: UserPromptSubmit fires only on user input, so long-lived autonomous loops (e.g. `/fsd`) that re-enter via task notifications (no user input) never reached the advisor — measured 2026-07-30: 6 responses / 12 tool calls with missing R007/R008 and zero advisory fires. Complements retroactive Stop-hook (`session-reflection.sh`, #1190). **Delivery gap resolved (#1547, v1.1.40)**: stderr on exit 0 is never injected into model context by any hook event, so #1545's wiring fired without reaching the model. The advisory is now delivered via `hookSpecificOutput.additionalContext` (JSON stdout, exit 0) — the confirmed non-blocking context-injection path for both events; stderr is retained only as a human-visible audit trail. No top-level `decision`/`continue`/`stopReason` field is emitted, so the hook stays advisory (never blocks a Stop/SubagentStop). |
18
18
  | Prompt-based | CLAUDE.md + rules/ + PostCompact | All MUST rules | Behavioral guidance in context |
19
19
 
20
20
  <!--
@@ -34,7 +34,7 @@ oh-my-customcode uses an **advisory-first enforcement model**. Most rules are en
34
34
  3. **Composability**: External skills and internal rules can coexist without deadlocks
35
35
  4. **PostCompact reinforcement**: R007/R008/R009/R010/R018 are re-injected after context compaction
36
36
 
37
- ## Hard Enforcement Candidates — R010 git-delegation-guard (conditional), R007/R008 UserPromptSubmit advisory **implemented** (#1229, proactive) + retroactive Stop-hook (#1190); hard-block variant still candidate if advisory insufficient (#1096). Promoted: rule-deletion-guard.sh (2026-04-08). See details via Read tool.
37
+ ## Hard Enforcement Candidates — R010 git-delegation-guard (conditional), R007/R008 advisory **implemented** (#1229 UserPromptSubmit, proactive) + **#1545 SubagentStop** (closes autonomous-loop gap) + retroactive Stop-hook (#1190); model-context delivery fixed via `hookSpecificOutput.additionalContext` (#1547, v1.1.40); hard-block variant still candidate if advisory insufficient (#1096). Promoted: rule-deletion-guard.sh (2026-04-08). See details via Read tool.
38
38
 
39
39
  <!-- DETAIL: Hard Enforcement Candidates (Future)
40
40
  If advisory enforcement proves insufficient for specific rules, these are candidates for promotion to hard-block:
@@ -42,7 +42,7 @@ If advisory enforcement proves insufficient for specific rules, these are candid
42
42
  | Rule | Candidate Hook | Status | Condition for Promotion |
43
43
  |------|---------------|--------|------------------------|
44
44
  | R010 | git-delegation-guard.sh | Candidate | If orchestrator-direct-write violations exceed 3/session |
45
- | R007/R008 | `r007-r008-drift-advisor.sh` (UserPromptSubmit, #1229) | **Advisory implemented** — proactive pre-response check; retroactive: `session-reflection.sh` (Stop, #1190). Two-layer drift detection: proactive (#1229) + retroactive (#1190). | Promote to hard-block if advisory proves insufficient (#1096) |
45
+ | R007/R008 | `r007-r008-drift-advisor.sh` (UserPromptSubmit #1229 + SubagentStop #1545) | **Advisory implemented** — proactive pre-response check now wired to both UserPromptSubmit and SubagentStop; the SubagentStop leg (#1545) closes the no-user-input autonomous-loop gap (`/fsd` etc.). Retroactive: `session-reflection.sh` (Stop, #1190). Two-layer drift detection: proactive (#1229/#1545) + retroactive (#1190). **Delivery mechanism fixed (#1547, v1.1.40)** — stderr on exit 0 reaches only a human (transcript debug mode), never the model, so wiring alone did not prove advisory reach; the advisory now travels via `hookSpecificOutput.additionalContext` on JSON stdout with exit 0, and emits no top-level `decision`/`continue`/`stopReason` so it remains non-blocking. | Promote to hard-block if advisory proves insufficient (#1096) |
46
46
 
47
47
  Promotion requires: (1) measured violation rate data, (2) user approval, (3) rollback plan.
48
48
 
@@ -5,6 +5,10 @@ on:
5
5
  - cron: "17 7 * * *"
6
6
  workflow_dispatch:
7
7
 
8
+ concurrency:
9
+ group: cc-release-monitor
10
+ cancel-in-progress: false
11
+
8
12
  permissions:
9
13
  issues: write
10
14
  contents: read
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.1.39",
2
+ "version": "1.1.41",
3
3
  "lastUpdated": "2026-07-14T00:00:00.000Z",
4
4
  "omcustomMinClaudeCode": "2.1.121",
5
5
  "omcustomMinClaudeCodeReason": "Sensitive-path direct Write/Edit on .claude/** under bypassPermissions (R010 deprecation, #1101)",