oh-my-customcode 1.1.43 → 1.1.44

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.43",
244
+ version: "1.1.44",
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.43",
2034
+ version: "1.1.44",
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.43",
6
+ "version": "1.1.44",
7
7
  "description": "Batteries-included agent harness for Claude Code",
8
8
  "type": "module",
9
9
  "bin": {
@@ -227,6 +227,16 @@
227
227
  }
228
228
  ],
229
229
  "description": "Inject session auto-fix findings into first user prompt (#838)"
230
+ },
231
+ {
232
+ "matcher": "*",
233
+ "hooks": [
234
+ {
235
+ "type": "command",
236
+ "command": "bash .claude/hooks/scripts/fail-axis-cause-advisor.sh"
237
+ }
238
+ ],
239
+ "description": "Advisory on cause-free progress nudges when this session has logged tool failures \u2014 delivers via hookSpecificOutput.additionalContext (#1561)"
230
240
  }
231
241
  ],
232
242
  "SubagentStart": [
@@ -621,6 +631,18 @@
621
631
  ],
622
632
  "description": "Print auto-dev token spend summary on session end (Issue #1057, advisory)"
623
633
  }
634
+ ],
635
+ "PostToolUseFailure": [
636
+ {
637
+ "matcher": "*",
638
+ "hooks": [
639
+ {
640
+ "type": "command",
641
+ "command": "bash .claude/hooks/scripts/failure-ledger.sh"
642
+ }
643
+ ],
644
+ "description": "FAIL-axis instrumentation \u2014 append tool failures to the error ledger (JSONL). Never blocks; feeds fail-axis-cause-advisor.sh (#1561)"
645
+ }
624
646
  ]
625
647
  }
626
648
  }
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/env bash
2
+ # fail-axis-cause-advisor.sh — UserPromptSubmit: 원인 없는 재촉 발화 감지 (FAIL 축)
3
+ #
4
+ # 배경:
5
+ # 8주 세션 실측에서 사용자 발화 216턴 중 원인 분석 표현이 0건(error_cause_ratio = 0.000)이었다.
6
+ # 반면 "계속해"(14) / "ㄱㄱ"(5) / "계속 진행해"(5) 등 원인 진술 없는 진행 지시가 24건,
7
+ # 전체 발화의 11%를 차지했다. 도구 실패가 세션당 1.72건 발생하는데도 원인을 묻지 않고
8
+ # 재촉으로 통과시키는 패턴이다.
9
+ #
10
+ # 역할:
11
+ # (1) 짧은 진행 지시이고 (2) 원인 언급이 없으며 (3) 이 세션에 기록된 도구 실패가 있을 때,
12
+ # Claude에게 "진행 전에 사용자에게 원인 가설 한 줄을 되물어라"는 advisory를 전달한다.
13
+ #
14
+ # 왜 사용자가 아니라 Claude에게 전달하는가:
15
+ # hookSpecificOutput.additionalContext는 모델 컨텍스트로만 들어간다(사용자에게 표시되지 않음).
16
+ # 따라서 Claude가 사용자에게 되묻게 만들고, 사용자의 답변이 대화 로그에 사용자 발화로
17
+ # 남게 하는 우회 경로를 택한다. 이렇게 해야 실제 진단 행동과 계측 지표가 함께 개선된다.
18
+ #
19
+ # 왜 차단하지 않는가:
20
+ # decision:"block"을 쓰면 프롬프트 자체가 거부되어 자율 루프(/fsd)가 멈춘다.
21
+ # R021 advisory-first 원칙에 따라 절대 차단하지 않고 exit 0을 유지한다.
22
+ #
23
+ # 의존:
24
+ # failure-ledger.sh(PostToolUseFailure)가 기록한 원장을 발동 조건으로 읽는다.
25
+ # 원장이 없으면 조용히 통과한다 — 훅 단독으로도 안전하게 동작한다.
26
+ #
27
+ # 환경변수 override:
28
+ # OMCUSTOM_FAIL_ADVISOR=off — advisory 완전 비활성화
29
+ # OMCUSTOM_ERROR_LEDGER=<path> — 원장 경로 override
30
+
31
+ set -euo pipefail
32
+
33
+ input=$(cat)
34
+
35
+ # ── Opt-out 체크 ──
36
+ if [ "${OMCUSTOM_FAIL_ADVISOR:-}" = "off" ]; then
37
+ exit 0
38
+ fi
39
+
40
+ if ! command -v jq >/dev/null 2>&1; then
41
+ exit 0
42
+ fi
43
+
44
+ prompt=$(printf '%s' "$input" | jq -r '.prompt // empty' 2>/dev/null) || exit 0
45
+ session=$(printf '%s' "$input" | jq -r '.session_id // empty' 2>/dev/null) || exit 0
46
+
47
+ if [ -z "$prompt" ] || [ -z "$session" ]; then
48
+ exit 0
49
+ fi
50
+
51
+ # ── 조건 1: 짧은 발화만 대상 (긴 발화는 이미 맥락을 담고 있다고 본다) ──
52
+ # 실측 p75가 27자이므로 40자를 상한으로 둔다.
53
+ if [ "${#prompt}" -gt 40 ]; then
54
+ exit 0
55
+ fi
56
+
57
+ # ── 조건 2: 진행/재촉 패턴인가 ──
58
+ if ! printf '%s' "$prompt" \
59
+ | grep -qiE '(계속|이어서|진행해|재개|다음|ㄱㄱ|고고|가자|continue|keep going|go on|resume|proceed|next)'; then
60
+ exit 0
61
+ fi
62
+
63
+ # ── 조건 3: 이미 원인/이유를 언급했다면 개입하지 않는다 (오탐 방지) ──
64
+ if printf '%s' "$prompt" \
65
+ | grep -qiE '(원인|이유|왜|때문|에러|오류|error|fail|because|cause)'; then
66
+ exit 0
67
+ fi
68
+
69
+ # ── 조건 4: 이 세션에 기록된 도구 실패가 있는가 ──
70
+ LEDGER="${OMCUSTOM_ERROR_LEDGER:-${HOME}/.claude/error-ledger.jsonl}"
71
+ if [ ! -f "$LEDGER" ]; then
72
+ exit 0
73
+ fi
74
+
75
+ # 원장 꼬리만 스캔한다 (전체 파일 스캔 회피).
76
+ # interrupt == true 는 사용자가 직접 중단시킨 것이므로 진단 대상 실패가 아니다 — 제외한다.
77
+ # (제외하지 않으면 사용자가 스스로 끊은 도구까지 "원인을 대라"고 되묻는 오탐이 된다.)
78
+ fail_count=$(tail -n 300 "$LEDGER" 2>/dev/null \
79
+ | jq -r --arg s "$session" 'select(.session == $s and .interrupt != true) | .tool' 2>/dev/null \
80
+ | wc -l | tr -d ' ') || fail_count=0
81
+
82
+ if [ -z "$fail_count" ] || [ "$fail_count" -eq 0 ] 2>/dev/null; then
83
+ exit 0
84
+ fi
85
+
86
+ # 최근 실패 도구 요약 (최대 3종)
87
+ fail_tools=$(tail -n 300 "$LEDGER" 2>/dev/null \
88
+ | jq -r --arg s "$session" 'select(.session == $s and .interrupt != true) | .tool' 2>/dev/null \
89
+ | sort | uniq -c | sort -rn | head -3 \
90
+ | awk '{printf "%s(%s) ", $2, $1}') || fail_tools=""
91
+
92
+ advisory_text=$(printf '[FAIL Advisory] 이 세션에 도구 실패 %s건이 기록되어 있습니다 (%s). 방금 입력은 원인 언급이 없는 진행 지시입니다. 곧바로 재시도하지 말고, 먼저 직전 실패의 원인 가설을 한 줄로 제시한 뒤 사용자에게 "이 진단이 맞는지 / 다른 원인이 짚이는지" 짧게 한 번만 확인하십시오. 사용자가 답하면 그대로 진행합니다. 이 확인은 한 턴을 넘기지 마십시오.' \
93
+ "$fail_count" "${fail_tools:-unknown}")
94
+
95
+ # 사람이 보는 감사 추적용 (exit 0에서 stderr는 모델에 전달되지 않음)
96
+ printf '%s\n' "$advisory_text" >&2
97
+
98
+ # 실제 전달 경로: additionalContext. decision 필드는 절대 포함하지 않는다.
99
+ jq -cn --arg ctx "$advisory_text" \
100
+ '{hookSpecificOutput: {hookEventName: "UserPromptSubmit", additionalContext: $ctx}}'
101
+
102
+ exit 0
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env bash
2
+ # failure-ledger.sh — PostToolUseFailure 에러 원장 기록 (FAIL 축 계측)
3
+ #
4
+ # 배경:
5
+ # hooks.json은 성공 경로(PreToolUse 12 / PostToolUse 16 / Stop 7)에는 촘촘히 배선되어
6
+ # 있으나 실패 경로에는 훅이 하나도 없었다. 그 결과 도구 실패가 세션당 평균 1.72건
7
+ # 발생함에도 아무 데이터도 남지 않아, R023 검증 래더의 상위 tier(에러 패턴 인식,
8
+ # post-mortem)를 측정할 근거 자체가 없는 상태였다.
9
+ #
10
+ # 역할:
11
+ # 도구 호출 실패 시 한 줄 JSONL을 원장에 append 한다. 이 원장은
12
+ # (1) recovery 성공률 산출, (2) 반복 실패 도구/명령 식별,
13
+ # (3) fail-axis-cause-advisor.sh(UserPromptSubmit)의 발동 조건으로 쓰인다.
14
+ #
15
+ # 설계 원칙:
16
+ # - 순수 append-only. 기존 파일을 읽거나 수정하지 않는다.
17
+ # - 네트워크 호출 없음. 외부 명령은 jq/date만 사용.
18
+ # - 어떤 실패에도 exit 0 — 원장 기록 실패가 본 작업을 막아서는 안 된다 (R021 advisory-first).
19
+ # - 명령/에러 문자열은 절단하여 기록한다 (원장 비대화 방지).
20
+ #
21
+ # 환경변수 override:
22
+ # OMCUSTOM_FAILURE_LEDGER=off — 기록 완전 비활성화
23
+ # OMCUSTOM_ERROR_LEDGER=<path> — 원장 경로 override (기본: ~/.claude/error-ledger.jsonl)
24
+
25
+ set -euo pipefail
26
+
27
+ input=$(cat)
28
+
29
+ # ── Opt-out 체크 ──
30
+ if [ "${OMCUSTOM_FAILURE_LEDGER:-}" = "off" ]; then
31
+ exit 0
32
+ fi
33
+
34
+ # ── jq 의존성 체크 (없으면 조용히 통과) ──
35
+ if ! command -v jq >/dev/null 2>&1; then
36
+ exit 0
37
+ fi
38
+
39
+ LEDGER="${OMCUSTOM_ERROR_LEDGER:-${HOME}/.claude/error-ledger.jsonl}"
40
+
41
+ if ! mkdir -p "$(dirname "$LEDGER")" 2>/dev/null; then
42
+ exit 0
43
+ fi
44
+
45
+ ts=$(date -u +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || echo "")
46
+
47
+ # ── 한 줄 JSONL append ──
48
+ # 에러 필드 위치 (공식 문서 실측, code.claude.com/docs/en/hooks "PostToolUseFailure input"):
49
+ # PostToolUseFailure는 PostToolUse와 달리 tool_response를 보내지 않는다. 에러는
50
+ # **최상위 `error`** 문자열로 오고, 부수적으로 `is_interrupt` / `duration_ms`가 따라온다.
51
+ # 초판이 `.tool_response.error`를 읽어 err가 항상 빈 문자열이 되던 결함을 교정한 것이다
52
+ # (r007-r008-drift-advisor.sh의 `.role` vs `.message.role`과 동일 계열).
53
+ # .tool_error / .tool_response.* fallback은 스키마 변화에 대한 방어로만 남긴다 —
54
+ # tool_response가 문자열인 경우 인덱싱 에러로 레코드가 통째로 유실되므로 type 검사로 감싼다.
55
+ #
56
+ # 단일 라인(<1KB) append 이므로 O_APPEND 원자성에 기대어 병렬 에이전트 환경에서도 안전.
57
+ printf '%s' "$input" \
58
+ | jq -c --arg ts "$ts" --arg cwd "$PWD" '
59
+ {
60
+ ts: $ts,
61
+ session: (.session_id // ""),
62
+ cwd: $cwd,
63
+ tool: (.tool_name // "unknown"),
64
+ target: ((.tool_input.command // .tool_input.file_path // "") | tostring | .[0:160]),
65
+ interrupt: (.is_interrupt == true),
66
+ err: ((.error
67
+ // .tool_error
68
+ // (if (.tool_response | type) == "object"
69
+ then (.tool_response.error // .tool_response.stderr)
70
+ else .tool_response end)
71
+ // "")
72
+ | tostring | gsub("\\s+"; " ") | .[0:320])
73
+ }' >> "$LEDGER" 2>/dev/null || true
74
+
75
+ exit 0
@@ -46,7 +46,35 @@
46
46
  # with `tool_result` content blocks. Only a genuine prompt (string content, or an array
47
47
  # with no tool_result block) ends a turn.
48
48
  # * `thinking` blocks are interleaved with text/tool_use and never carry an R008 prefix;
49
- # they are filtered out before adjacency analysis.
49
+ # they are filtered out before analysis.
50
+ #
51
+ # ── R008 verdict: TURN-LEVEL COUNTING, not block adjacency (#1563 찐빠 #1) ─────────────
52
+ # R008 (`.claude/rules/MUST-tool-identification.md`) says, verbatim:
53
+ # "For parallel calls: list ALL identifications BEFORE the tool calls."
54
+ # The rule therefore requires the announce lines of a parallel BATCH to be grouped ahead of
55
+ # the batch — it does NOT require a text block wedged immediately before every single
56
+ # tool_use. The previous implementation tested block ADJACENCY (`$blocks[i-1]` is a text
57
+ # block matching the prefix), so in a compliant parallel batch `[text, tool_use, tool_use]`
58
+ # every tool_use after the first had a `tool_use` predecessor and was counted as a violation
59
+ # — R009 MANDATES those batches, so the advisor fired against rule-compliant behavior
60
+ # (measured: 212 bytes on a compliant live turn, 348 on a synthetic fixture; both must be 0).
61
+ #
62
+ # The verdict is now a per-turn count comparison:
63
+ # violations = max(0, tool_use_blocks − announce_lines)
64
+ #
65
+ # Announce lines counted (over ALL text blocks of the turn, split into lines):
66
+ # * `[agent][model] → Tool: X` — the Core Rule form; ONE per tool call.
67
+ # * `→ Target:` is NOT counted. It is the COMPANION line of `→ Tool:` (Core Rule prints the
68
+ # pair), so counting it would score 2 per tool and silently mask real omissions.
69
+ # * Spawn notation from R008 §"Parallel Spawn Prefix Rule", which documents parallel Agent
70
+ # calls as a `[agent][model] → Spawning:` header followed by one indented
71
+ # `[N] subagent_type:model → description` line per agent — with NO `→ Tool: Agent` line.
72
+ # The per-agent unit is the numbered line, so those are counted when present; the bare
73
+ # `→ Spawning:` header counts only when no numbered line exists (single-agent spawn, which
74
+ # R008 explicitly exempts from the `[N]` prefix). Excluding this notation would recreate
75
+ # exactly the false positive this fix removes (N Agent tool_use blocks, 0 `Tool:` lines).
76
+ #
77
+ # R007 detection (first line of the turn's first text block) is unchanged.
50
78
  #
51
79
  # ── Performance ───────────────────────────────────────────────────────────────────────
52
80
  # The previous implementation forked jq once PER LINE inside a `while read` loop (measured
@@ -149,11 +177,13 @@ split("\n")
149
177
  | (if ($ftext | length) == 0 then 0
150
178
  elif ($fline | test("^┌─ Agent:")) or ($fline | test("^\\[.+\\]")) then 0
151
179
  else 1 end) as $r007
152
- | ([ range(0; ($blocks | length))
153
- | select($blocks[.].type? == "tool_use")
154
- | select( (. == 0)
155
- or ($blocks[. - 1].type? != "text")
156
- or (((($blocks[. - 1].text?) // "") | test("\\[.+\\]\\[.+\\] ?(→|->|—>) ?(Tool|Target):")) | not) ) ] | length) as $r008
180
+ | ([ $blocks[] | select(.type? == "text") | (.text? // "") ] | join("\n") | split("\n")) as $lines
181
+ | ([ $lines[] | select(test("\\[.+\\]\\[.+\\] ?(→|->|—>) ?Tool:")) ] | length) as $an_tool
182
+ | ([ $lines[] | select(test("^[[:space:]]*\\[[0-9]+\\][[:space:]].*(→|->|—>)")) ] | length) as $an_spawn_item
183
+ | ([ $lines[] | select(test("\\[.+\\]\\[.+\\] ?(→|->|—>) ?Spawning:")) ] | length) as $an_spawn_hdr
184
+ | ($an_tool + (if $an_spawn_item > 0 then $an_spawn_item else $an_spawn_hdr end)) as $announce
185
+ | ([ $blocks[] | select(.type? == "tool_use") ] | length) as $ntools
186
+ | (if $ntools > $announce then $ntools - $announce else 0 end) as $r008
157
187
  | [$tuuid, ($r007 | tostring), ($r008 | tostring)] | @tsv
158
188
  end
159
189
  '
@@ -89,11 +89,23 @@ ISO8601="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
89
89
  # 없다. 실제 경로는 `.message.role` / `.message.content`다. 종전 구현은 `.role`을 읽어 항상 빈 값을
90
90
  # 얻었고, 그 결과 assistant 라인이 하나도 매칭되지 않아 이 분석기는 사실상 0계층 탐지였다.
91
91
  #
92
- # 그리고 content 블록은 라인당 1개다 — 한 assistant 턴이 여러 줄에 걸친다. 따라서 라인 단위로
93
- # R008 인접성(직전 블록이 text인지)을 보면 모든 tool_use가 영구 위반으로 집계된다. 턴을 먼저
94
- # 복원한 뒤 블록 인접성을 본다. 턴 경계는 "진짜 user 프롬프트"(문자열 content 또는 tool_result가
95
- # 없는 배열)이며, tool_result user 라인은 경계가 아니다. `isSidechain: true`(서브에이전트 턴)은
96
- # 제외한다. `thinking` 블록은 R008 접두사를 가질 수 없으므로 인접성 판정 전에 제거한다.
92
+ # 그리고 content 블록은 라인당 1개다 — 한 assistant 턴이 여러 줄에 걸친다. 따라서 턴을 먼저
93
+ # 복원한 뒤 판정한다. 턴 경계는 "진짜 user 프롬프트"(문자열 content 또는 tool_result가 없는
94
+ # 배열)이며, tool_result user 라인은 경계가 아니다. `isSidechain: true`(서브에이전트 턴)은
95
+ # 제외한다. `thinking` 블록은 R008 접두사를 가질 수 없으므로 판정 전에 제거한다.
96
+ #
97
+ # R008 판정은 블록 인접성이 아니라 **턴 단위 개수 비교**다 (#1563 찐빠 #1). R008 원문은
98
+ # "For parallel calls: list ALL identifications BEFORE the tool calls." 즉 병렬 배치의 식별을
99
+ # 배치 앞에 모아 나열하라는 규칙이지, 매 tool_use 직전에 text 블록을 끼우라는 요구가 아니다.
100
+ # 인접성 판정은 R009가 MUST로 요구하는 병렬 배치 `[text, tool_use, tool_use]`에서 2번째 이후
101
+ # tool_use를 무조건 위반으로 집계했다. 새 판정: violations = max(0, tool_use 수 − announce 수).
102
+ # announce 인정 범위: `[agent][model] → Tool:` 라인(도구당 1개). `→ Target:`은 `→ Tool:`의
103
+ # 동반 라인이라 중복 계수 금지(도구당 2로 세어 누락을 놓침). R008 §"Parallel Spawn Prefix Rule"이
104
+ # 규정한 spawn 표기(`→ Spawning:` 헤더 + 에이전트당 `[N] type:model → desc` 라인, `→ Tool: Agent`
105
+ # 없음)도 포함 — 에이전트당 단위는 번호 라인이고, 번호 라인이 없을 때만(단일 spawn) 헤더를 1로 센다.
106
+ # 위반 샘플은 announce가 모자란 만큼 턴의 마지막 tool_use들을 보고한다(결손 개수 기준).
107
+ #
108
+ # 이 판정은 r007-r008-drift-advisor.sh와 공유된다 — 한쪽만 고치면 재오염된다.
97
109
  #
98
110
  # 성능: 줄마다 jq를 포크하던 구조를 jq 1회 포크로 교체.
99
111
  JQ_REFLECT='
@@ -120,12 +132,17 @@ split("\n")
120
132
  and ((($fline | test("^┌─ Agent:")) or ($fline | test("^\\[.+\\]"))) | not)
121
133
  then [ {k: "R007", turn: ($ti + 1), s: ($fline[0:120])} ]
122
134
  else [] end )
123
- + [ range(0; ($blocks | length))
124
- | select($blocks[.].type? == "tool_use")
125
- | select( (. == 0)
126
- or ($blocks[. - 1].type? != "text")
127
- or (((($blocks[. - 1].text?) // "") | test("\\[.+\\]\\[.+\\] ?(→|->|—>) ?(Tool|Target):")) | not) )
128
- | {k: "R008", turn: ($ti + 1), s: ($blocks[.].name? // "")} ]
135
+ + ( ([ $blocks[] | select(.type? == "text") | (.text? // "") ] | join("\n") | split("\n")) as $lines
136
+ | ([ $lines[] | select(test("\\[.+\\]\\[.+\\] ?(→|->|—>) ?Tool:")) ] | length) as $an_tool
137
+ | ([ $lines[] | select(test("^[[:space:]]*\\[[0-9]+\\][[:space:]].*(→|->|—>)")) ] | length) as $an_spawn_item
138
+ | ([ $lines[] | select(test("\\[.+\\]\\[.+\\] ?(→|->|—>) ?Spawning:")) ] | length) as $an_spawn_hdr
139
+ | ($an_tool + (if $an_spawn_item > 0 then $an_spawn_item else $an_spawn_hdr end)) as $announce
140
+ | ([ $blocks[] | select(.type? == "tool_use") ]) as $tus
141
+ | (if ($tus | length) > $announce then ($tus | length) - $announce else 0 end) as $r008n
142
+ | if $r008n > 0
143
+ then [ $tus[(($tus | length) - $r008n):][]
144
+ | {k: "R008", turn: ($ti + 1), s: (.name? // "")} ]
145
+ else [] end )
129
146
  ]
130
147
  | flatten
131
148
  | . as $viol
@@ -32,12 +32,14 @@
32
32
  > **v2.1.206+**: `/doctor`에 checked-in CLAUDE.md에서 코드베이스로부터 파생 가능한 내용을 잘라내도록 제안하는 체크가 추가되었습니다 — R005 "Context Optimization via HTML Comments"의 컨텍스트 절감 원칙과 정합(모델 불필요 메타데이터 축소).
33
33
  -->
34
34
 
35
- > **v2.1.208+**: Fixed several tool-reliability bugs: env vars like `CLAUDE_CODE_MAX_OUTPUT_TOKENS` silently used only the mantissa of scientific-notation values (`1e6` became `1`); Edit now succeeds on a file modified after being read, as long as the target text still matches uniquely; Read no longer misreports empty files as "shorter than offset"; Grep no longer silently returns "No files found" for invalid regex, no longer under-reports paginated count-mode totals; and Glob no longer crashes on a null byte in pattern/path/cwd.
35
+ <!-- RETIRED (은퇴 릴리즈 v1.1.44, 보존 기준 v2.1.212 미만): > **v2.1.208+**: Fixed several tool-reliability bugs: env vars like `CLAUDE_CODE_MAX_OUTPUT_TOKENS` silently used only the mantissa of scientific-notation values (`1e6` became `1`); Edit now succeeds on a file modified after being read, as long as the target text still matches uniquely; Read no longer misreports empty files as "shorter than offset"; Grep no longer silently returns "No files found" for invalid regex, no longer under-reports paginated count-mode totals; and Glob no longer crashes on a null byte in pattern/path/cwd. -->
36
36
 
37
37
  > **v2.1.210+**: Bash/PowerShell 명령이 timeout으로 auto-background될 때의 메시지가 개선되어 모델이 hang과 명시적 background 요청을 구분할 수 있으며, auto-background된 명령 내 `cd`는 적용되지 않고 tool result가 working directory 불변을 명시합니다 — auto-background 이후 cwd 의존 후속 명령은 절대 경로로 수행합니다. 또한 Grep content mode가 결과 끝을 지난 페이지네이션에서 "No matches found"를 반환하던 문제가 수정되었습니다(v2.1.208 Grep 페이지네이션 수정의 연장) — 구버전에서 이 응답은 "패턴 미존재"가 아니라 "페이지 끝"일 수 있습니다.
38
38
 
39
39
  > **v2.1.212+**: MCP 도구 호출이 2분(기본값, `CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS`로 임계값 조정·비활성) 초과 시 자동으로 백그라운드로 이동해 세션이 계속 사용 가능해집니다 — 위 v2.1.210 Bash/PowerShell auto-background의 MCP 도구 확장. 느린 MCP 호출(ontology-rag `rebuild_ontology`, code-review-graph 인덱싱 등)을 hang으로 오판하지 말고, 2분 초과 시 백그라운드 전환을 전제로 후속 작업을 진행합니다.
40
40
 
41
+ > **v2.1.224+**: mid-turn에 연결된 MCP 도구가 **이름 고지 없이** tool search로 deferred되던 결함이 수정되었습니다. 구버전에서는 세션 도중 붙은 MCP 서버의 도구가 이름조차 노출되지 않아 "그런 도구 없음"으로 오판할 수 있었으므로, 위 tool-availability 주의(`command -v` 사전 확인과 동류)를 MCP 도구에도 적용합니다 — 도구 부재 결론 전에 `ToolSearch`로 실측합니다.
42
+
41
43
  ### Capability-Aware Tool Scheduling
42
44
 
43
45
  When dispatching parallel tool calls, consider per-tool capabilities to optimize scheduling:
@@ -64,6 +64,10 @@ Skill/rule text instructing "spawn with `model: opus`" refers to this tier — a
64
64
 
65
65
  > **v2.1.222+**: **org-restricted 환경에서** `model: opus` 계열 subagent/teammate의 family alias가 parent model로 떨어지던 문제가 수정되어, 이제 해당 family 내에서 org가 허용한 **최신 모델로 step-down**합니다. 이는 Tier 1의 "CC resolves these, not this project" 원칙을 강화하는 사례입니다 — Tier-1 alias 해석에는 **org 제한이라는 추가 변수**가 있어 프로젝트가 pin할 수 없으므로, 특정 모델을 확정하려면 frontmatter에 **Tier-2 full ID**를 씁니다. Agent 도구 spawn 파라미터(Tier 3)는 full ID를 받지 않으므로 이 경로에서는 alias 해석이 org 설정에 좌우됩니다. (본 저장소의 org 제한 여부는 미실측 — 위 조건절이 적용 범위입니다.)
66
66
 
67
+ > **v2.1.223+**: workflow agent · forked skill · slash command · 재개된 background agent가 **요청한 subagent 모델이 제한되어 parent model로 실행될 때 경고가 표시**됩니다. 위 v2.1.222 org step-down 노트의 직접 연장선으로, 이전에는 이 강등이 **무음**이었습니다 — 즉 "`model: opus`로 스폰했다"는 기록이 실제 실행 모델의 증거가 아니었습니다. 특정 모델을 확정하려면 frontmatter Tier-2 full ID를 쓰고, 실행 모델은 경고 표시 유무로 확인합니다(R020 "attempt ≠ outcome"의 모델 선택 각도).
68
+
69
+ > **v2.1.223+**: `CLAUDE_CODE_DISABLE_1M_CONTEXT`가 **native 1M 창을 가진 모든 Claude 모델**을 auto-compaction으로 200K에 유지하도록 확대되었습니다(이전에는 고정 모델 목록). 미인식 model ID도 가정 컨텍스트 창 내로 유지되며 `CLAUDE_CODE_DISABLE_UNKNOWN_MODEL_WINDOW_ENFORCEMENT=1`로 복원할 수 있습니다. 위 Tier-2 표의 `claude-sonnet-5`/`claude-opus-5`(native 1M)와 `[1m]` 접미사는 이 env가 설정된 환경에서 **실효 200K로 동작**하므로, 1M 전제의 대용량 컨텍스트 위임 전에 env 설정 여부를 확인합니다(cross-ref R013 context budget).
70
+
67
71
  > **Claude Fable 5 (access via CC v2.1.170+)**: Mythos-class model, GA on the Claude API and positioned as a tier above Opus — its capabilities exceed any previously GA model. CC v2.1.170 is the client version that adds access (the model's GA is an API/platform property, not a CC-release milestone). Available via frontmatter full ID `claude-fable-5` (Tier 2) or Agent tool `model: fable` (Tier 3) — NOT via a Tier-1 frontmatter alias. Reserve for the most complex reasoning where its capability premium is warranted; `sonnet` remains the default for general tasks and `opus` for architecture (cost/latency awareness, R005). CC v2.1.170 also fixes session transcripts not saving (and not appearing in `--resume`) when launched from a VS Code integrated terminal or any shell inheriting Claude Code env vars — relevant to transcript-dependent skills (`homework`, `episodic-memory`). Closes #1352.
68
72
 
69
73
  <!-- ARCHIVED CC version notes (historical):
@@ -40,6 +40,8 @@ Available when `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` or TeamCreate/SendMessag
40
40
 
41
41
  These are distinct mechanisms. Agent Teams `SendMessage` requires `TeamCreate` and operates within a single Claude Code session. claude-peers-mcp `send_message` operates across separate Claude Code processes via a localhost broker.
42
42
 
43
+ > **v2.1.224/225+**: CC 네이티브 `SendMessage`가 **cross-session으로 확장**되었습니다(다른 머신 포함, macOS/Linux) — `ListAgents`로 대상을 열거하고 `crossSessionInbound` / `dialogExpiry` 설정으로 수신·만료를 제어합니다. 위 표의 "Cross-session = claude-peers-mcp 전용" 구분은 이제 **유일한 수단이 아니며**, 브로커 없이 네이티브 경로를 쓸 수 있습니다. 다만 위 Cross-Session Relay Authority Hardening(v2.1.166)의 권한 비전파 원칙은 네이티브 경로에도 동일하게 적용됩니다 — cross-session 메시지는 조율 신호이지 승인 채널이 아닙니다. (225) cross-session 메시지가 headless 세션·기동 중에 **고지도 만료도 없이 대기**하던 결함이 수정되었으므로, 구버전에서 "응답 없음"은 미수신이 아니라 무기한 대기였을 수 있습니다.
44
+
43
45
  ### Cross-Session Relay Authority Hardening (CC v2.1.166+)
44
46
 
45
47
  <!-- ARCHIVED CC version note (historical):
@@ -381,6 +383,8 @@ Agent Teams member completion MUST be verified by deterministic ground-truth —
381
383
 
382
384
  Cross-reference: R020 ("actual outcome ≠ attempt" — verifying that a command ran is not the same as verifying it succeeded).
383
385
 
386
+ > **v2.1.224+**: `SendMessage`가 **teammate inbox 쓰기에 실패해도 "Message sent"로 보고**하던 결함이 수정되어, 이제 실패가 오류로 보고됩니다. 위 표의 "SendMessage report = Low reliability"가 **전송 자체에도** 해당했다는 실증입니다 — 구버전에서는 "Message sent"가 수신은커녕 기록 성공조차 보장하지 않았습니다. 수정 후에도 전송 성공은 **수신자가 작업을 수행했다는 증거가 아니므로**, 위 표의 결정론적 ground-truth 확인은 그대로 유지합니다.
387
+
384
388
  > **v2.1.222+**: `SendMessage`가 긴 summary를 문자 수 제한으로 거부하던 동작이 **절단(truncate)**으로 변경되어 전송이 실패하지 않습니다. 전송 실패가 사라진 대신 **조용한 절단**이라는 새 실패 모드가 생겼으므로, 위 표의 "SendMessage report = Low reliability" 원칙이 오히려 강화됩니다. 긴 보고가 필요하면 SendMessage 본문 대신 아티팩트 파일 경로 전달(R006 Artifact Channel Protocol)로 대체합니다.
385
389
 
386
390
  <!-- ARCHIVED CC version note (historical):
@@ -99,6 +99,17 @@ R016의 승격 루프(위반 지적 → 규칙 조항 추가)는 코퍼스의 **
99
99
  - 그 이하 버전노트는 HTML-comment화(무손실 중간 단계) 하거나 `guides/claude-code/15-version-compatibility.md`로 이관한다.
100
100
  - `claude-native` 스킬이 생성하는 버전 추적 이슈를 규칙에 반영할 때, 최신만 visible로 두고 구버전은 즉시 은닉한다.
101
101
 
102
+ #### 보존 기준 변경 = 전 룰 파일 스윕 (같은 릴리즈 내 필수)
103
+
104
+ 보존 기준선을 상향하면 **같은 릴리즈에서 23개 룰 파일 전수를 스윕**해 기준 미만 노트를 HTML-comment화한다. 기준만 올리고 적용을 다음 릴리즈로 이월하면 코퍼스가 기준과 불일치한 상태로 남고, 그 불일치는 다음 회고에서 "잔존 N건" 부채로 재발견될 때까지 보이지 않는다. 스윕 범위는 `.claude/rules/**`와 `templates/.claude/rules/**` 양쪽이며, 잔존 여부는 **HTML 주석 안/밖을 구분해** 실측한다 — 단순 `grep`은 이미 은퇴한 주석 내부 노트까지 세어 판정을 왜곡한다.
105
+
106
+ | Anti-pattern | Required |
107
+ |--------------|----------|
108
+ | 보존 기준선만 상향하고 기존 노트 스윕을 다음 릴리즈로 이월 | 기준 상향과 전 룰 파일 스윕을 같은 릴리즈에서 완료 |
109
+ | `grep -c` 히트 수로 잔존 판정 | 주석 안/밖을 구분해 **visible 잔존**만 계수 |
110
+
111
+ Origin: #1563 찐빠 #4 — R016이 보존 기준을 v2.1.212로 규정했으나 R001/R005/R012에 visible v2.1.208 노트 3건이 잔존해 v1.1.44에서 뒤늦게 은퇴. Cross-reference: R005(HTML-comment 컨텍스트 최적화), R017(Count Sync — 전수 grep + 의미 판별).
112
+
102
113
  ### Cross-References
103
114
 
104
115
  R005(HTML-comment 컨텍스트 최적화), R023(Deprecated-Platform-Feature Staleness Check — 폐기 참조를 결정론적으로 탐지하여 은퇴 후보를 조기 발굴), Origin #1473.
@@ -258,6 +258,8 @@ When a subagent trips the safety classifier (R001/R002) **2 times**, the orchest
258
258
  | 2nd trip | STOP the agent — do NOT re-run. Redesign: decompose by domain (R009) and re-delegate narrower units |
259
259
  | 3+ trips | Hard anti-pattern — indicates lost control; abort and report to user |
260
260
 
261
+ > **v2.1.225+**: auto mode가 **자기 권한 검사에 대한 safety-filter refusal**을 consecutive-block 한도에 계상하던 결함이 수정되었습니다 — 동작은 여전히 거부되나 모델에는 재시도 대신 진행하라고 지시됩니다. 이 표의 trip 계수는 **서브에이전트가 실제 작업에서 유발한 classifier trip**만을 대상으로 하며, 플랫폼 내부 권한 검사에서 발생한 refusal은 계수 대상이 아닙니다 — 구버전에서 이 둘이 섞여 계상되었으므로, 과거 세션의 trip 횟수를 근거로 STOP 판정을 소급하지 않습니다.
262
+
261
263
  ### Pre-Decomposition Mandate
262
264
 
263
265
  Broad single-task scopes (e.g. "migrate + backfill") MUST be pre-decomposed by domain before delegation, so an agent cannot silently expand from its named task into adjacent privileged domains (secret rotation, tunnel creation, infra deletion, dashboard changes). See R009 (pre-decomposition) and R018 (domain-split).
@@ -299,6 +301,16 @@ Cross-reference: the Subagent Scope-Creep STOP Protocol (reactive halt after tri
299
301
 
300
302
  > Origin: #1556 — 승인 인용을 포함한 위임은 mgr-gitnerd가 2회 거부했고, 동일 에이전트에 허용/금지 작업만 열거한 위임은 거부 없이 완주했다(2026-08-05 v1.1.43 세션, 대조 실증). Cross-ref: R015 (User Directive Persistence — `settings.json` allow 규칙이 실제 prompt 억제 수단이라는 동일 결론의 선례), R002 (permission tiers).
301
303
 
304
+ ### Delegation Prompt Command Examples — 실측 확인 또는 예시 명시
305
+
306
+ 위임 프롬프트에 구체적 명령·플래그를 적을 때는 **실측으로 확인한 것만 적거나**, 확인하지 않았다면 "예시이며 실제 플래그는 확인 후 사용"을 명시한다. 미확인 플래그를 확정형으로 적으면 서브에이전트가 실행 중 `unknown flag`를 만나 복구 왕복을 소비하고, 복구에 실패하면 잘못된 대체 경로를 택한다. 확인 수단은 `--help` 또는 `command -v` 한 줄이면 충분하다.
307
+
308
+ | Anti-pattern | Required |
309
+ |--------------|----------|
310
+ | 미확인 플래그를 확정형으로 위임 프롬프트에 기재 (`gh issue edit <N> --assignee @me`) | 실행 전 `--help`로 실측 후 기재, 또는 "예시 — 실제 플래그는 확인 후 사용" 명시 |
311
+
312
+ Origin: #1563 찐빠 #3 — `gh issue edit --assignee`가 gh 2.86.0에 없는 플래그였고(정답 `--add-assignee`) 에이전트가 실행 중 자체 복구했다. Cross-reference: R005(도구 플래그·기본 동작 실측 함정 사례집), 위 Agent Capability Pre-Check(위임 전 존재성 확인의 도구·경로 각도).
313
+
302
314
  ### Parallel Delegation — Sibling-Agent Disclosure
303
315
 
304
316
  2개 이상의 서브에이전트를 같은 메시지에서 병렬 스폰할 때, 각 위임 프롬프트는 **형제 에이전트의 존재와 각자의 담당 범위**를 고지해야 한다. 서브에이전트는 격리된 컨텍스트에서 실행되어 형제를 인지할 수 없으므로, 고지가 없으면 `git status` 같은 **저장소 전역 공유 뷰**의 출력을 자기 변경분으로 오독하거나 경합 원인을 "외부 세션/프로세스"로 오귀속한다.
@@ -395,6 +407,8 @@ Before spawning any agent:
395
407
 
396
408
  > **v2.1.212+**: CC가 Task(=Agent) 도구의 `mode` 파라미터를 deprecated(이제 무시)했습니다 — subagent는 기본적으로 **부모(오케스트레이터) 세션의 permission mode를 상속**합니다. 따라서 이 섹션이 요구하는 per-call `mode: "bypassPermissions"`는 v2.1.212+에서 no-op이며, 무인 위임이 프롬프트 없이 돌게 하는 통제점은 per-call 파라미터가 아니라 **부모 세션의 permission mode**입니다(안전 완화 아님 — 부모가 bypassPermissions면 subagent도 상속). 단 CC < v2.1.212에서는 여전히 per-call `mode` 명시가 필요하므로(위 History #926/#947/#955) 하위 호환을 위해 계속 포함하되, 신버전에서 프롬프트 발생 시 진단은 위 Self-Check("mode 있는지 확인")가 아니라 **부모 세션 모드**를 확인합니다. cross-ref R002/R006(이 섹션을 canonical source로 참조).
397
409
 
410
+ > **v2.1.223+**: agent definition의 `bypassPermissions` 모드가 org의 bypass-permissions 비활성 정책을 무시하던 권한 공백이 수정되었습니다. 즉 구버전에서는 **에이전트 정의 파일이 org 정책보다 우선**해 org가 끈 bypass를 되살릴 수 있었습니다. 이 저장소는 위 v2.1.212+ 서술대로 부모 세션 mode 상속을 통제점으로 삼으므로 실질 변화는 없으나, org 정책이 걸린 환경에서는 frontmatter `permissionMode: bypassPermissions`가 더 이상 무인 실행을 보장하지 않습니다 — 프롬프트 발생 시 부모 세션 mode와 **org 정책** 두 축을 확인합니다(cross-ref R002).
411
+
398
412
  > **v2.1.221+**: background session이 작업 보존을 위해 commit·push를 수행하고, draft PR은 작업이 요구할 때만 열며, 사용자의 CLAUDE.md git 지침을 따르고, 항상 작업 위치를 보고하며 종료하도록 변경되었습니다. 이 저장소의 R010은 모든 git 작업을 mgr-gitnerd 위임으로 요구하므로 background session은 그 지침을 읽고 동작하지만, **R020 기준 ground-truth(`git log` / `gh pr view`) 실측 없이 background session의 커밋/푸시 완료 보고를 신뢰하지 않습니다**. 또한 v2.1.221에서 `/status`가 세션 종류(interactive / background attached / background unattended)를 표시하므로 무인 실행 여부를 결정론적으로 확인할 수 있습니다.
399
413
 
400
414
  ## Agent Capability Pre-Check
@@ -106,6 +106,8 @@ Reference: #1320 (fix), #1321 (session 113 retrospective 찐빠 #1), `feedback_l
106
106
  | Instance independence | Isolated context, no shared state |
107
107
  | Large tasks (>3 min) | MUST split into parallel sub-tasks |
108
108
 
109
+ > **v2.1.224+**: **세션당 200 subagent spawn cap이 제거**되어 장기 세션이 신규 에이전트를 거부하지 않습니다(동시성 제한과 depth 제한은 유지). 위 표의 "Max instances 5 concurrent"는 **동시성** 제한이므로 그대로 유효합니다 — 제거된 것은 세션 누적 총량 cap입니다. `/fsd` 등 장기 무인 루프에서 후반 반복의 스폰 실패를 더 이상 누적 cap으로 진단하지 않습니다.
110
+
109
111
  > **Fable 5 long-lived subagent reuse (Origin: #1435)**: Fable 5는 long-lived subagent 재사용(단일 subagent가 여러 단계를 이어서 수행)에 강함 — 현행 R009 병렬 실행 원칙과 상충하지 않으며, Fable 5 실행 시 short-lived 병렬 다수 대신 long-lived 재사용도 유효한 선택지. 상세는 `guides/claude-code/16-fable5-prompting.md`.
110
112
 
111
113
  ## Adaptive Parallel Splitting
@@ -80,6 +80,8 @@ Use a `"*"` deny rule in `settings.json` to enforce a deny-by-default posture, t
80
80
  > 2. **(v2.1.221) auto mode 병렬 권한 검사 최적화** — 병렬 tool call의 권한 검사가 cache-efficient해지고 캐시된 대화 prefix 재사용으로 비용이 감소했습니다(R009 병렬 배치의 부담 완화). 검사 대기 중 모드를 전환하면 stale 결과를 적용하지 않고 재프롬프트합니다.
81
81
  > 3. **(v2.1.222) Remote Control auto-start 스코프 축소** — repo-local 설정(`.claude/settings.json` / `.claude/settings.local.json`)으로는 **켤 수 없고**(끄는 것은 가능), 활성화는 user scope `/config`에서만 가능합니다.
82
82
 
83
+ > **v2.1.223/225+**: 두 건이 Tier-4 Bash 권한 검사와 세션 인증에 영향을 줍니다. (223) 조작된 명령이 **자기 일부를 권한 검사에서 숨기던** 결함이 수정되었습니다 — v2.1.221 zsh `[[ ]]` 우회 수정의 연장선이며, 검사 대상 문자열과 실행 문자열이 다를 수 있었다는 뜻입니다(표시 측 결함은 R001). (225) 일시적 401이 장수명 `CLAUDE_CODE_OAUTH_TOKEN`을 저장된 단수명 토큰으로 교체해 headless 세션을 재시작 전까지 망가뜨리던 결함이 수정되었습니다 — 구버전 무인 실행에서 401 이후의 연쇄 인증 실패는 토큰 설정 오류가 아니라 이 교체 버그일 수 있으므로 진단 시 구분합니다. agent definition의 `bypassPermissions`가 org 정책을 무시하던 공백(223)은 R010 "Universal bypassPermissions"가 canonical.
84
+
83
85
  ## Agent Tool Permission Mode
84
86
 
85
87
  > Canonical source: R010 (MUST-orchestrator-coordination.md) "Universal bypassPermissions" owns the full requirement, rationale, self-check, and version history. Core rule: always pass `mode: "bypassPermissions"` explicitly on every Agent tool call — the Agent tool's default `mode` (`acceptEdits`) overrides agent frontmatter `permissionMode` and causes prompts during unattended execution. Skills that spawn agents MUST include this in their Agent tool call instructions. See R010 for details.
@@ -29,7 +29,9 @@ The following git commands have caused working tree loss in past sessions (#1146
29
29
  > **v2.1.183+**: Auto mode now BLOCKS destructive git commands at the platform level — `git reset --hard`, `git checkout -- .`, `git clean -fd`, and `git stash drop` are blocked when you did not ask to discard local work; `git commit --amend` is blocked when the commit was not made by the agent this session; and `terraform destroy` / `pulumi destroy` / `cdk destroy` are blocked unless you asked for the specific stack. This is the PLATFORM-level complement to this section's (advisory) per-invocation approval requirement and the Pre-Delegation Blast-Radius Enumeration below: the model still enumerates discard targets and requests approval (model-level), and CC now also hard-blocks the destructive command itself in auto mode (platform-level) — defense-in-depth. The advisory approval requirement remains because the platform block gates the COMMAND, not the blast-radius enumeration the user needs for an informed decision.
30
30
  -->
31
31
 
32
- > **v2.1.208+**: Catastrophic removals (e.g. `rm -rf ~`) wrapped in `$(…)`/backticks/`<(…)` now trigger the same prompt as the plain form in `--dangerously-skip-permissions` and auto mode — closes a subshell-obfuscation gap in the v2.1.183 platform-level destructive-command block above.
32
+ <!-- RETIRED (은퇴 릴리즈 v1.1.44, 보존 기준 v2.1.212 미만): > **v2.1.208+**: Catastrophic removals (e.g. `rm -rf ~`) wrapped in `$(…)`/backticks/`<(…)` now trigger the same prompt as the plain form in `--dangerously-skip-permissions` and auto mode — closes a subshell-obfuscation gap in the v2.1.183 platform-level destructive-command block above. -->
33
+
34
+ > **v2.1.223/224+**: 승인 다이얼로그·샌드박스 경계의 표시 무결성 결함 두 건이 수정되었습니다. (223) 탭·비가시 유니코드로 패딩한 명령이 승인 다이얼로그에서 자기 일부를 숨길 수 있던 결함 — 사용자가 **본 것과 승인한 것이 달랐다**는 뜻이므로, 위 Pre-Delegation Blast-Radius Enumeration(모델이 파괴 대상을 별도로 열거)이 플랫폼 다이얼로그로 대체될 수 없음을 재확인시킵니다. (224) sandbox filesystem deny 항목의 후행 슬래시(`denyRead: "~/.aws/"`)가 조용히 우회 가능하던 결함, 그리고 sandbox 위반 상세가 Bash 도구 결과에 전혀 나타나지 않던 결함 — 후자는 위반이 **관측 불가**했다는 의미이므로, 구버전에서 "sandbox 위반 없음"은 위반 부재의 증거가 아닙니다. credential deny 규칙 작성 시 후행 슬래시를 제거합니다(cross-ref R002).
33
35
 
34
36
  > **v2.1.221/222+**: v2.1.222에서 worktree-isolated 세션과 그 subagent가 main checkout에 대해 파괴적 git 명령을 실행할 수 있던 문제가 수정되어, isolation이 모든 세션 타입의 file edit과 Bash에 적용됩니다. v2.1.221에서는 `/fork` 세션이 원본 세션 checkout이 아니라 자체 worktree를 생성하도록 변경되었습니다. **완화 아님**: 위 Destructive Git Commands 표의 per-invocation 승인 요구와 아래 Pre-Delegation Blast-Radius Enumeration은 그대로 유지됩니다. 플랫폼 isolation은 격리 경계를 강화할 뿐, 사용자가 판단하는 데 필요한 blast-radius 열거를 대체하지 않습니다(v2.1.183/208 플랫폼 블록과 동일한 defense-in-depth 관계).
35
37
 
@@ -86,6 +86,8 @@ Active removal of irrelevant retrieved content from agent context. Complements o
86
86
 
87
87
  ## Context Budget Management — Task-type-aware thresholds (research 40%, implementation 50%, review 60%, management 70%, general 80%). See full spec via Read tool.
88
88
 
89
+ > **v2.1.223+**: `CLAUDE_CODE_DISABLE_1M_CONTEXT`가 native 1M 창을 가진 **모든** Claude 모델을 auto-compaction으로 200K에 유지하도록 확대되었고(이전에는 고정 모델 목록), 미인식 model ID도 가정 컨텍스트 창 내로 유지됩니다(`CLAUDE_CODE_DISABLE_UNKNOWN_MODEL_WINDOW_ENFORCEMENT=1`로 복원). 위 임계값은 **창 대비 백분율**이므로 절대 토큰량은 이 env 설정에 따라 5배까지 달라집니다 — 1M 전제로 예산을 잡기 전 env 설정 여부를 확인합니다(cross-ref R006).
90
+
89
91
  <!-- DETAIL: Context Budget Management
90
92
 
91
93
  Task-type-aware context thresholds that trigger ecomode earlier for context-heavy operations.
@@ -37,7 +37,7 @@ Format: `─── [Spawn] {subagent_type}:{model} | {description} ───`
37
37
  > **v2.1.202+**: workflow-spawned agent 텔레메트리에 `workflow.run_id`/`workflow.name` OTel 속성이 추가되어 workflow run 활동을 OTel 데이터로 재구성할 수 있습니다. R012 관측성 확장(monitoring-setup 스킬).
38
38
  -->
39
39
 
40
- > **v2.1.208+**: Fixed `/release-notes` "Show all" injecting the entire changelog into the model's context (cross-ref R013 context budget). Fixed the context window (and auto-compact indicator) briefly resetting to 200k after CLI auto-update, causing a false "100% context used" on resumed long-context sessions — relevant to the CTX% statusline segment below. Completed background agents now stay listed in `/tasks` until cleanup instead of vanishing on completion — extends the v2.1.198 background-notification observability above.
40
+ <!-- RETIRED (은퇴 릴리즈 v1.1.44, 보존 기준 v2.1.212 미만): > **v2.1.208+**: Fixed `/release-notes` "Show all" injecting the entire changelog into the model's context (cross-ref R013 context budget). Fixed the context window (and auto-compact indicator) briefly resetting to 200k after CLI auto-update, causing a false "100% context used" on resumed long-context sessions — relevant to the CTX% statusline segment below. Completed background agents now stay listed in `/tasks` until cleanup instead of vanishing on completion — extends the v2.1.198 background-notification observability above. -->
41
41
 
42
42
  <!-- DETAIL: HUD Events full spec
43
43
  ### When to Display: Multi-step tasks, parallel execution, long-running operations. Skip for single brief operations.
@@ -373,6 +373,16 @@ Session-end saves lose context: by the time the session ends, multiple discoveri
373
373
  Related records from session v0.87.2~v0.88.0 (issue #869). The originating memory files were later consolidated/removed; no live equivalents remain as of this writing.
374
374
  -->
375
375
 
376
+ ## Procedure-Summary Scope Tagging
377
+
378
+ 절차·순서를 메모리에 압축 요약할 때는 **적용 스코프를 함께 표기**한다. 압축은 문맥 경계를 가장 먼저 버리므로, 하위 단계 내부의 순서가 파이프라인 전체 순서로 읽히는 오독이 발생한다. 스코프 표기는 괄호 한 마디면 충분하다 — "(릴리즈 단계 내부 순서)", "(구현 커밋에는 미적용)"처럼 **무엇에 적용되지 않는지**까지 적으면 오독 여지가 사라진다.
379
+
380
+ | Anti-pattern | Required |
381
+ |--------------|----------|
382
+ | `release 브랜치 선생성 → 버전범프 → PR` (스코프 미표기 → 전체 파이프라인 순서로 오독) | `릴리즈 단계 내부 순서: release 브랜치 선생성 → 버전범프 → PR (구현 커밋은 develop 직행)` |
383
+
384
+ Origin: #1563 찐빠 #5 — 위 요약이 릴리즈 단계 내부 순서인데 전체 파이프라인 순서로 오독되었다. Cross-reference: R013(Compact Output — 압축이 버리는 것을 인지), 위 Mid-Session Immediate Save(트리거 문맥 보존).
385
+
376
386
  ## Safety-Related Feedback Memory Framing
377
387
 
378
388
  > Origin: #1307 찐빠 #2 (Medium) — a sys-memory-keeper delegation prompt framed a learning as "오탐으로 판단하고 진행한다" (conclude it's a false positive and proceed), tripping the memory-poisoning safety classifier and requiring a rewrite.
@@ -103,6 +103,16 @@ staleness/audit 검증은 model ID·placeholder·TBD뿐 아니라 **폐기된
103
103
 
104
104
  Origin: #1455 #1 (Session 127 회고 찐빠 #1) — cc-release-monitor PR #1449 머지 후 workflow_dispatch 실검증에서 issue_body의 `<details>`·릴리즈 요약에 12칸 리터럴 들여쓰기 발견 → PR #1451 재작업. 첫 위임이 문법 검증만 지시하고 샘플 값 출력 조립 검증을 누락. `textwrap.dedent` + 멀티라인 변수 함정이 문법 검증만으로는 미노출. R020(문법 통과 ≠ 출력 정상)과 정합.
105
105
 
106
+ ## Conditional-Output Verification — Positive/Negative Pair Mandate (Origin: #1563 #2)
107
+
108
+ 조건부로만 출력하는 대상(advisory 훅, 가드, 경고 emitter)의 동작을 검증하도록 위임할 때, 완료 기준은 **"출력이 나와야 하는 입력"과 "나오면 안 되는 입력"을 짝으로** 지정해야 한다. "stdout ≠ 0바이트" 같은 단일 프록시는 검증이 아니다 — 침묵이 정답인 입력에서도 통과를 요구하게 되어 기준 자체가 틀리고, 반대로 오탐(준수 턴에서 발화)을 통과시킨다.
109
+
110
+ | Anti-pattern | Required |
111
+ |--------------|----------|
112
+ | "지정 입력에서 stdout ≠ 0바이트"를 단일 완료 기준으로 위임 | 양성 케이스(발화해야 함)와 음성 케이스(침묵해야 함)를 짝으로 명시 |
113
+
114
+ Origin: #1563 찐빠 #2 — R007/R008 advisor 발화 검증에 단일 "0바이트 아님" 프록시를 제시했으나, advisor는 준수 턴에서 침묵하는 것이 정상 동작이라 기준이 성립하지 않았다. Cross-reference: R020(Proxy Signal vs Canonical Ground-Truth — 프록시로 상태를 특성화하지 말 것), 위 Detection Guard Delegation Standard(positive-match vs negative-context 구분의 가드 설계 각도).
115
+
106
116
  ## Detection Guard Delegation Standard (Origin: #1438 #3)
107
117
 
108
118
  Tier-1 shift-left 검출 가드(예: deprecated-pattern grep 가드)의 설계·수정을 서브에이전트에 위임할 때, 위임 프롬프트는 **positive-match(genuine defect mandate — `MUST`/`MANDATORY` 인접 문맥)와 negative-context(deprecation note — "no longer"/"deprecated"/"불필요"/"폐기됨" 설명 문구)를 구분**하도록 명시해야 한다. 이를 누락하면 올바르게 수정된 파일의 폐기-설명 문구까지 과잉매칭하여 자기모순 BLOCK을 유발한다.
@@ -146,6 +156,8 @@ Before invoking a Workflow script, deterministically verify:
146
156
  | 프롬프트 문자열 내 셸 변수 `${...}`(`$?`, `${PIPESTATUS[0]}`, `$(...)` 등)가 `\${...}`로 이스케이프되어 있는지 사전 grep 확인 | JS 템플릿 리터럴 안의 이스케이프 안 된 셸 `${...}`를 JS가 JS 표현식으로 평가 → 런타임 `ReferenceError`(예: `PIPESTATUS is not defined`). `node --check`는 문법만 검사하여 이 런타임 오류를 못 잡으므로 별도 결정론 grep 검사가 필요함 |
147
157
  | Workflow `args`를 사용하는 스크립트가 `typeof args === 'string' ? JSON.parse(args) : args` 방어를 거친 뒤 필드에 접근하는지 확인 | 하니스가 객체 args를 문자열로 인코딩해 전달하면 `args.<field>`가 undefined가 되어 스크립트가 즉시 런타임 실패(0 agents 실행). `node --check`는 문법만 검사하므로 위 셸 `${...}` 이스케이프 항목과 동일한 런타임 계열을 잡지 못함 |
148
158
 
159
+ > **v2.1.223+**: workflow script가 동적 `import()`로 workflow 샌드박스 **밖의 코드를 실행**할 수 있던 결함이 수정되었습니다. 위 표의 체크는 프롬프트 조립·문법·런타임 계열을 다루지만 **샌드박스 탈출은 다루지 않았고**, 구버전에서는 `node --check` 통과 + 프롬프트 정상 조립 상태에서도 스크립트가 경계 밖 코드를 끌어올 수 있었습니다. 외부에서 받은 workflow script를 실행하기 전 동적 `import()` 사용 여부를 grep으로 확인합니다(Tier-1 결정론 검사).
160
+
149
161
  #### Common Violation (#1271)
150
162
  Session 106 follow-up to #1266 ③: a Workflow authoring error recurred — the guardrail fact-sheet was concatenated onto the agent's RETURN VALUE instead of the prompt string, and a placeholder/assembly slip went uncaught because no pre-run sanity check existed. This check is the deterministic Tier-1 guard that catches such slips before the expensive run.
151
163
 
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.1.43",
2
+ "version": "1.1.44",
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)",