oh-my-customcode 0.152.0 → 0.154.0
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 +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/templates/.claude/hooks/hooks.json +10 -0
- package/templates/.claude/hooks/scripts/r007-r008-drift-advisor.sh +117 -0
- package/templates/.claude/rules/MUST-intent-transparency.md +19 -0
- package/templates/.claude/rules/SHOULD-memory-integration.md +33 -4
- package/templates/manifest.json +1 -1
package/dist/cli/index.js
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -208,6 +208,16 @@
|
|
|
208
208
|
],
|
|
209
209
|
"description": "Advisory pre-processing of user input \u2014 skill matching hints and intent analysis"
|
|
210
210
|
},
|
|
211
|
+
{
|
|
212
|
+
"matcher": "*",
|
|
213
|
+
"hooks": [
|
|
214
|
+
{
|
|
215
|
+
"type": "command",
|
|
216
|
+
"command": "bash .claude/hooks/scripts/r007-r008-drift-advisor.sh"
|
|
217
|
+
}
|
|
218
|
+
],
|
|
219
|
+
"description": "Proactive R007/R008 drift advisory \u2014 checks last assistant turn for identification omission (#1229)"
|
|
220
|
+
},
|
|
211
221
|
{
|
|
212
222
|
"matcher": "*",
|
|
213
223
|
"hooks": [
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# r007-r008-drift-advisor.sh — UserPromptSubmit hook: PROACTIVE R007/R008 drift advisory (#1229)
|
|
3
|
+
#
|
|
4
|
+
# Inspects the LAST completed assistant turn in the session transcript for R007/R008
|
|
5
|
+
# compliance BEFORE Claude responds. If the previous turn drifted (missing identification
|
|
6
|
+
# header / tool prefix), emits a stderr advisory so the upcoming response self-corrects.
|
|
7
|
+
#
|
|
8
|
+
# This is the PROACTIVE complement to the retroactive session-reflection.sh (Stop hook, #1190).
|
|
9
|
+
# Detection patterns are reused from session-reflection.sh.
|
|
10
|
+
#
|
|
11
|
+
# Advisory-only: ALWAYS exits 0, ALWAYS passes stdin through to stdout, NEVER blocks.
|
|
12
|
+
# Performance: parses ONLY the last assistant turn (not the whole transcript).
|
|
13
|
+
#
|
|
14
|
+
# 환경변수 override (테스트/디버깅용):
|
|
15
|
+
# OMCUSTOM_R007_ADVISOR=off — advisory 완전 비활성화 (pass-through)
|
|
16
|
+
# OMCUSTOM_TRANSCRIPT_BASE — transcript 디렉토리 경로 override
|
|
17
|
+
|
|
18
|
+
set -euo pipefail
|
|
19
|
+
|
|
20
|
+
# ── UserPromptSubmit 프로토콜: stdin을 먼저 읽음 ──
|
|
21
|
+
input=$(cat)
|
|
22
|
+
|
|
23
|
+
# ── Opt-out 체크 ──
|
|
24
|
+
if [ "${OMCUSTOM_R007_ADVISOR:-}" = "off" ]; then
|
|
25
|
+
echo "$input"
|
|
26
|
+
exit 0
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
# ── jq 의존성 체크 ──
|
|
30
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
31
|
+
echo "$input"
|
|
32
|
+
exit 0
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# ── session_id 추출 ──
|
|
36
|
+
session_id=$(echo "$input" | jq -r '.session_id // empty' 2>/dev/null)
|
|
37
|
+
if [ -z "$session_id" ]; then
|
|
38
|
+
echo "$input"
|
|
39
|
+
exit 0
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
# ── 경로 결정 (환경변수 override 지원) ──
|
|
43
|
+
TRANSCRIPT_BASE="${OMCUSTOM_TRANSCRIPT_BASE:-${HOME}/.claude/projects/-Users-sangyi-workspace-projects-oh-my-customcode}"
|
|
44
|
+
TRANSCRIPT_PATH="${TRANSCRIPT_BASE}/${session_id}.jsonl"
|
|
45
|
+
|
|
46
|
+
if [ ! -f "$TRANSCRIPT_PATH" ]; then
|
|
47
|
+
echo "$input"
|
|
48
|
+
exit 0
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
# ── 마지막 assistant 메시지 추출 (성능: 전체 transcript 스캔 회피) ──
|
|
52
|
+
# 파일을 역순으로 읽으며 첫 번째 role=="assistant" 라인을 찾는다.
|
|
53
|
+
last_assistant=""
|
|
54
|
+
while IFS= read -r line; do
|
|
55
|
+
role=$(echo "$line" | jq -r '.role // empty' 2>/dev/null) || continue
|
|
56
|
+
if [ "$role" = "assistant" ]; then
|
|
57
|
+
last_assistant="$line"
|
|
58
|
+
break
|
|
59
|
+
fi
|
|
60
|
+
done < <(tail -r "$TRANSCRIPT_PATH" 2>/dev/null || tac "$TRANSCRIPT_PATH" 2>/dev/null)
|
|
61
|
+
|
|
62
|
+
if [ -z "$last_assistant" ]; then
|
|
63
|
+
echo "$input"
|
|
64
|
+
exit 0
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
# ── content 배열 파싱 ──
|
|
68
|
+
content_raw=$(echo "$last_assistant" | jq -c '.content // []' 2>/dev/null) || content_raw="[]"
|
|
69
|
+
|
|
70
|
+
r007_violations=0
|
|
71
|
+
r008_violations=0
|
|
72
|
+
|
|
73
|
+
# ── R007: 첫 번째 text 블록의 첫 줄 체크 ──
|
|
74
|
+
first_text=$(echo "$content_raw" | jq -r '[.[] | select(.type == "text")][0].text // empty' 2>/dev/null) || first_text=""
|
|
75
|
+
if [ -n "$first_text" ]; then
|
|
76
|
+
first_line=$(printf '%s' "$first_text" | head -1)
|
|
77
|
+
# R007 패턴: '┌─ Agent:' 또는 '[anything]' 단축 형태
|
|
78
|
+
if ! printf '%s' "$first_line" | grep -qE '(^┌─ Agent:|^\[.+\])'; then
|
|
79
|
+
r007_violations=$((r007_violations + 1))
|
|
80
|
+
fi
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
# ── R008: tool_use 블록 직전 text에 prefix 체크 ──
|
|
84
|
+
content_length=$(echo "$content_raw" | jq 'length' 2>/dev/null) || content_length=0
|
|
85
|
+
i=0
|
|
86
|
+
while [ "$i" -lt "$content_length" ]; do
|
|
87
|
+
block_type=$(echo "$content_raw" | jq -r ".[$i].type // empty" 2>/dev/null) || { i=$((i+1)); continue; }
|
|
88
|
+
|
|
89
|
+
if [ "$block_type" = "tool_use" ]; then
|
|
90
|
+
has_prefix=false
|
|
91
|
+
if [ "$i" -gt 0 ]; then
|
|
92
|
+
prev_type=$(echo "$content_raw" | jq -r ".[$(( i - 1 ))].type // empty" 2>/dev/null) || true
|
|
93
|
+
if [ "$prev_type" = "text" ]; then
|
|
94
|
+
prev_text=$(echo "$content_raw" | jq -r ".[$(( i - 1 ))].text // empty" 2>/dev/null) || true
|
|
95
|
+
# R008 패턴: '[agent-name][model] → Tool:' 또는 '→ Target:'
|
|
96
|
+
if printf '%s' "$prev_text" | grep -qE '\[.+\]\[.+\] ?(→|->|—>) ?(Tool|Target):'; then
|
|
97
|
+
has_prefix=true
|
|
98
|
+
fi
|
|
99
|
+
fi
|
|
100
|
+
fi
|
|
101
|
+
if [ "$has_prefix" = "false" ]; then
|
|
102
|
+
r008_violations=$((r008_violations + 1))
|
|
103
|
+
fi
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
i=$((i+1))
|
|
107
|
+
done
|
|
108
|
+
|
|
109
|
+
# ── advisory 출력 (위반 시에만) ──
|
|
110
|
+
if [ "$r007_violations" -gt 0 ] || [ "$r008_violations" -gt 0 ]; then
|
|
111
|
+
printf '[R007/R008 Advisory] 직전 응답에서 식별 누락 감지 (R007 헤더=%d, R008 접두사=%d). 이번 응답은 ┌─ Agent: 헤더로 시작하고, 모든 도구 호출에 [agent][model] → Tool: 접두사를 포함하십시오.\n' \
|
|
112
|
+
"$r007_violations" "$r008_violations" >&2
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
# ── 항상 stdin pass-through 후 exit 0 (advisory는 절대 차단 금지) ──
|
|
116
|
+
echo "$input"
|
|
117
|
+
exit 0
|
|
@@ -103,6 +103,25 @@ Reference issues: #1188 item #4.
|
|
|
103
103
|
|
|
104
104
|
**Why**: 사용자 directive 일관성 — #1208 보고. 같은 세션 내 동일 의도를 반복 차단하면 R015 user directive persistence 위반.
|
|
105
105
|
|
|
106
|
+
### Destructive Operation Approval Persistence (Generalized)
|
|
107
|
+
|
|
108
|
+
The Git Push Continuation pattern (first-time strict / follow-up relaxed, scoped to session + category + target) generalizes to ALL repeated destructive operations within the same session. Examples: `supabase db push`, `terraform apply`, `kubectl delete`, bulk file deletes, database migrations.
|
|
109
|
+
|
|
110
|
+
**Scope**: once the user explicitly approves a destructive operation of category C against target T in a session, follow-up operations of the SAME C + SAME T do NOT require re-confirmation. An advisory warning is still emitted. A different category or different target always requires fresh confirmation.
|
|
111
|
+
|
|
112
|
+
| Scenario | Behavior |
|
|
113
|
+
|----------|----------|
|
|
114
|
+
| 1st explicit approval (category C, target T) | Proceed; advisory warning emitted |
|
|
115
|
+
| Follow-up same session (same C + same T) | No re-confirmation (directive persistence) |
|
|
116
|
+
| Different category or target | Fresh confirmation required |
|
|
117
|
+
| Platform classifier still prompts | Advise user: add `settings.json` permission rule for the specific command |
|
|
118
|
+
|
|
119
|
+
**R001 exclusion (MUST)**: R001-listed catastrophic git operations (`git reset --hard`, `git clean -fd`, `git push --force` to shared branches, `git branch -D` with unmerged commits) are EXCLUDED from this persistence rule — they always require explicit per-invocation approval regardless of prior session approvals.
|
|
120
|
+
|
|
121
|
+
**Boundary / honesty note**: This rule is ADVISORY and governs model behavior only. It CANNOT suppress Claude Code's platform-level auto-mode classifier prompts. For genuine prompt suppression on a repeated destructive command, the user must add a `settings.json` permission allow rule scoped to the specific command (e.g., a specific `supabase db push` invocation). The model SHOULD surface this workaround when the user expresses friction about repeated prompts.
|
|
122
|
+
|
|
123
|
+
Cross-references: R001 (safety — destructive operation pre-checks still apply), R002 (permission tiers). Reference issues: #1230, #1226 (item 2).
|
|
124
|
+
|
|
106
125
|
## Agent Triggers
|
|
107
126
|
|
|
108
127
|
Defined in `.claude/skills/intent-detection/patterns/agent-triggers.yaml`. Each agent has keywords, file patterns, actions, and base confidence.
|
|
@@ -351,7 +351,7 @@ MCP tools (claude-mem, episodic-memory) are **orchestrator-scoped** and not inhe
|
|
|
351
351
|
|
|
352
352
|
### Session-End Self-Check (MANDATORY)
|
|
353
353
|
|
|
354
|
-
(1) sys-memory-keeper updated MEMORY.md? (2) claude-mem save attempted? (3) If `omcustom-feedback` skill is active, prompt user to trigger it
|
|
354
|
+
(1) sys-memory-keeper updated MEMORY.md? (2) claude-mem save attempted? (3) If `omcustom-feedback` skill is active, model MAY draft a retrospective feedback issue for user approval — or prompt user to trigger it manually. All three required before confirming to user. See full self-check via Read tool.
|
|
355
355
|
|
|
356
356
|
<!-- DETAIL: Session-End Self-Check (MANDATORY)
|
|
357
357
|
```
|
|
@@ -367,8 +367,10 @@ MCP tools (claude-mem, episodic-memory) are **orchestrator-scoped** and not inhe
|
|
|
367
367
|
║ NO → ToolSearch + save now ║
|
|
368
368
|
║ ║
|
|
369
369
|
║ 3. Is omcustom-feedback skill available in this project? ║
|
|
370
|
-
║ YES →
|
|
371
|
-
║
|
|
370
|
+
║ YES → If notable friction/learning observed: MODEL DRAFTS ║
|
|
371
|
+
║ retrospective issue → presents via Phase 4A preview ║
|
|
372
|
+
║ gate for user approval. Otherwise: prompt user to ║
|
|
373
|
+
║ trigger manually. Accept skip either way. ║
|
|
372
374
|
║ NO → Skip ║
|
|
373
375
|
║ ║
|
|
374
376
|
║ Note: episodic-memory auto-indexes conversations after session ║
|
|
@@ -381,6 +383,33 @@ MCP tools (claude-mem, episodic-memory) are **orchestrator-scoped** and not inhe
|
|
|
381
383
|
```
|
|
382
384
|
-->
|
|
383
385
|
|
|
386
|
+
### Session-End Retrospective Feedback (Model-Drafted)
|
|
387
|
+
|
|
388
|
+
Since `omcustom-feedback` is now model-invocable (#1227), the model MAY draft a retrospective feedback issue at session end — instead of only prompting the user to compose one manually.
|
|
389
|
+
|
|
390
|
+
**Workflow**
|
|
391
|
+
|
|
392
|
+
1. Model detects notable friction, workarounds, or harness gaps observed during the session.
|
|
393
|
+
2. Model drafts a feedback issue (title + body) using the `omcustom-feedback` skill.
|
|
394
|
+
3. Draft is presented through the skill's **Phase 4A preview + confirmation gate**. The user reviews and approves before any GitHub issue is created.
|
|
395
|
+
4. The model NEVER auto-submits. User approval is always required.
|
|
396
|
+
|
|
397
|
+
**Trigger conditions** (all must be true):
|
|
398
|
+
- Session-end detected
|
|
399
|
+
- Notable friction or learning observed during the session
|
|
400
|
+
- `omcustom-feedback` skill active in this project
|
|
401
|
+
|
|
402
|
+
**Distinction from manual path**
|
|
403
|
+
|
|
404
|
+
| Path | Who drafts | Who approves | When |
|
|
405
|
+
|------|-----------|--------------|------|
|
|
406
|
+
| Manual (existing) | User | User | User chooses to file feedback |
|
|
407
|
+
| Model-drafted (new, #1226 item 3) | Model | User (Phase 4A gate) | Session-end with notable friction |
|
|
408
|
+
|
|
409
|
+
The model-drafted path is an enhancement: it proposes a concrete draft rather than asking the user to compose from scratch. Both paths remain valid; neither replaces the other.
|
|
410
|
+
|
|
411
|
+
References: #1226 (item 3), #1227.
|
|
412
|
+
|
|
384
413
|
### Failure Policy
|
|
385
414
|
|
|
386
415
|
- MCP saves are **non-blocking**: memory failure MUST NOT prevent session from ending
|
|
@@ -418,7 +447,7 @@ Phase 1 COEXIST 기간 중 세션 종료 시:
|
|
|
418
447
|
1. sys-memory-keeper가 MEMORY.md 갱신? → YES: 계속
|
|
419
448
|
2. claude-mem 저장 시도? → YES (기존 항목)
|
|
420
449
|
3. AgentMemory 저장 시도? → YES (COEXIST 추가)
|
|
421
|
-
4. omcustom-feedback
|
|
450
|
+
4. omcustom-feedback 처리? → YES (활성 시, notable friction 있으면 model draft → Phase 4A gate; 없으면 사용자 권유) / 스킵 (비활성 시)
|
|
422
451
|
네 단계 모두 완료 후 사용자에게 확인. 둘 중 하나 실패해도 비차단.
|
|
423
452
|
|
|
424
453
|
### Phase 2 진입 전 필수 조건
|
package/templates/manifest.json
CHANGED