oh-my-customcode 1.1.67 → 1.1.68

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
@@ -217,7 +217,7 @@ var init_package = __esm(() => {
217
217
  workspaces: [
218
218
  "packages/*"
219
219
  ],
220
- version: "1.1.67",
220
+ version: "1.1.68",
221
221
  description: "Batteries-included agent harness for Claude Code",
222
222
  type: "module",
223
223
  bin: {
package/dist/index.js CHANGED
@@ -2326,7 +2326,7 @@ var package_default = {
2326
2326
  workspaces: [
2327
2327
  "packages/*"
2328
2328
  ],
2329
- version: "1.1.67",
2329
+ version: "1.1.68",
2330
2330
  description: "Batteries-included agent harness for Claude Code",
2331
2331
  type: "module",
2332
2332
  bin: {
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "workspaces": [
4
4
  "packages/*"
5
5
  ],
6
- "version": "1.1.67",
6
+ "version": "1.1.68",
7
7
  "description": "Batteries-included agent harness for Claude Code",
8
8
  "type": "module",
9
9
  "bin": {
@@ -298,6 +298,10 @@ split("\n")
298
298
  # 미announce Read — 은 새로 발화한다(의도된 동작, v1.1.62 적대적 리뷰 재현 C1/C2).
299
299
  | ($an_tool + (if $an_spawn > $an_tool_agent then $an_spawn - $an_tool_agent else 0 end)) as $announce
300
300
  | ([ $blocks[] | select((.type? == "tool_use") and ((.name? // "") != "Skill")) ] | length) as $ntools
301
+ # 미접두 도구 이름 (#1687): $ntools와 동일한 필터(non-Skill tool_use)로 순서를 보존한 이름
302
+ # 목록을 뽑는다. $r008(누락 건수)이 어떤 도구인지 shell에서 드러내기 위한 부가 필드 —
303
+ # 판정식($r008 산출) 자체는 건드리지 않는다.
304
+ | ([ $blocks[] | select((.type? == "tool_use") and ((.name? // "") != "Skill")) | (.name? // "") ]) as $tool_names_list
301
305
  # 전체 tool_use(Skill 포함)가 0건인 턴은 forward 판정을 무조건 0으로 고정한다(#1625
302
306
  # 찐빠 #3, 이슈 제안 그대로). $ntools(Skill 제외) 기반 산식은 정상 입력에서는 이미
303
307
  # 0을 내지만, 명시 가드로 불변식을 코드에 못박아 향후 산식 변경이 이 보장을 조용히
@@ -322,7 +326,7 @@ split("\n")
322
326
  | ([ $lines[] | select(test("^\\[[^\\]]+\\]\\[[^\\]]+\\] ?(→|->|—>) ?Tool:")) ] | length) as $an_anchored
323
327
  # $nall_tools는 위 forward r008 가드에서 이미 바인딩됨 — 재바인딩하지 않고 재사용한다.
324
328
  | (if $nall_tools == 0 and $an_anchored > 0 then $an_anchored else 0 end) as $r008rev
325
- | [$tuuid, ($r007 | tostring), ($r008 | tostring), ($r008rev | tostring)] | @tsv
329
+ | [$tuuid, ($r007 | tostring), ($r008 | tostring), ($r008rev | tostring), ($tool_names_list | join(","))] | @tsv
326
330
  )
327
331
  end
328
332
  end
@@ -346,6 +350,8 @@ turn_uuid=$(printf '%s' "$result" | cut -f1)
346
350
  r007_violations=$(printf '%s' "$result" | cut -f2)
347
351
  r008_violations=$(printf '%s' "$result" | cut -f3)
348
352
  r008_reverse=$(printf '%s' "$result" | cut -f4)
353
+ # 미접두 도구 이름 목록 (#1687) — $ntools와 동일 필터의 순서 보존 목록, "," join.
354
+ tool_names=$(printf '%s' "$result" | cut -f5)
349
355
 
350
356
  : "${r007_violations:=0}"
351
357
  : "${r008_violations:=0}"
@@ -397,6 +403,26 @@ if [ "$r008_violations" -gt 0 ]; then
397
403
  violation_desc="R008 도구 식별 접두사 누락 ${r008_violations}건"
398
404
  instruction="모든 도구 호출에 [agent][model] → Tool: 접두사를 포함하십시오."
399
405
  fi
406
+ # 미접두 도구 이름 귀속 (#1687): announce는 턴 단위로 매칭되므로, $tool_names(순서 보존,
407
+ # non-Skill tool_use)의 마지막 r008_violations개를 부족분으로 귀속한다. 카운트 문구
408
+ # "R008 도구 식별 접두사 누락 N건"은 위에서 이미 확정되어 바이트 동일 유지 — 이 접미사는
409
+ # 항상 그 뒤에 이어붙인다(scripts/count-r007-r008.sh의 grep -oE 앵커와 무관).
410
+ if [ -n "$tool_names" ]; then
411
+ r008_missing_tools=$(printf '%s' "$tool_names" | awk -F',' -v n="$r008_violations" '{
412
+ total = NF
413
+ start = total - n + 1
414
+ if (start < 1) start = 1
415
+ out = ""
416
+ for (i = start; i <= total; i++) {
417
+ if (out != "") out = out ", "
418
+ out = out $i
419
+ }
420
+ print out
421
+ }')
422
+ if [ -n "$r008_missing_tools" ]; then
423
+ violation_desc="${violation_desc} (미접두 도구: ${r008_missing_tools})"
424
+ fi
425
+ fi
400
426
  fi
401
427
 
402
428
  if [ -n "$violation_desc" ]; then
@@ -597,13 +597,34 @@ raw_command=$(printf '%s' "$input" | jq -r '.tool_input.command // ""')
597
597
  # Distinguish "the same file edited 3 times with DIFFERENT content" (a normal
598
598
  # incremental-edit workflow — the #1641 false positive) from "the same edit
599
599
  # repeated 3 times" (a genuine stuck loop). Only the latter should hard-block.
600
- # Alphanumerics-only + length cap: deterministic, platform-independent (no
601
- # md5sum, absent on macOS) and safe to embed in a grep pattern.
600
+ # #1649: the original alphanumerics-only + 120-char-cut key had two defects —
601
+ # (M-1) edits differing only in punctuation/whitespace (e.g. re-aligning a
602
+ # markdown table) collapsed to the SAME key and were falsely blocked as
603
+ # "identical", and (M-2) Write calls sharing a long identical prefix (e.g.
604
+ # frontmatter) collided after the 120-char cut even when the body differed.
605
+ # New spec: collapse whitespace runs to one space (still deterministic,
606
+ # platform-independent, no md5sum) but PRESERVE punctuation, then key on
607
+ # "<len>#<full>" when the normalized string is <=120 chars (short strings fit
608
+ # whole, so no sum is needed), else "<len>#<codepoint sum>#<first 80 chars>
609
+ # #<last 40 chars>" — length + codepoint sum + head/tail. Adversarial review
610
+ # found the length+head+tail-only key (no sum) still collides when a
611
+ # same-length middle-only substitution falls entirely outside both the head
612
+ # and tail windows (e.g. this repo's own count/version-bump Writes: 80 "A"s +
613
+ # "version-115-count" + 40 "Z"s vs "...-116-..." vs "...-117-..." — all 137
614
+ # chars, identical head/tail). The codepoint sum changes whenever the changed
615
+ # substring's characters change, so a substitution is now caught by the sum;
616
+ # a same-sum transposition of the middle segment can still collide — an
617
+ # accepted residual risk, not fully eliminated.
602
618
  edit_hash=""
603
619
  if [ "$tool_name" = "Edit" ] || [ "$tool_name" = "Write" ]; then
604
620
  edit_hash=$(printf '%s' "$input" \
605
621
  | jq -r '(.tool_input.old_string // .tool_input.content // .tool_input.new_string // "")
606
- | gsub("[^A-Za-z0-9]"; "") | .[0:120]')
622
+ | gsub("[[:space:]]+"; " ") | ltrimstr(" ") | rtrimstr(" ")
623
+ | (length as $l
624
+ | if $l <= 120 then "\($l)#\(.)"
625
+ else ((explode | add // 0) as $sum
626
+ | "\($l)#\($sum)#\(.[0:80])#\(.[-40:])")
627
+ end)')
607
628
  fi
608
629
 
609
630
  # History entries are written by jq, so their "path" values are JSON-ENCODED.
@@ -615,6 +636,15 @@ fi
615
636
  target_key_json=$(jq -n --arg v "$target_key" '$v')
616
637
  path_match="\"path\":${target_key_json}"
617
638
 
639
+ # #1649 follow-up: edit_hash now preserves punctuation (see the edit_hash
640
+ # comment above), so it can contain quotes/backslashes just like a Bash
641
+ # command can. It is written to history the same JSON-encoded way "path" is
642
+ # (--arg ehash "$edit_hash" -> jq serializes it), so Check 1 / Check 3 below
643
+ # must match it with the SAME JSON-encoded literal, not the raw string — same
644
+ # fix as path_match above, applied to edit_hash.
645
+ edit_hash_json=$(jq -n --arg v "$edit_hash" '$v')
646
+ edit_hash_match="\"edit_hash\":${edit_hash_json}"
647
+
618
648
  is_readonly="false"
619
649
  if [ "$tool_name" = "Bash" ]; then
620
650
  is_readonly=$(is_readonly_bash_command "$raw_command")
@@ -761,7 +791,7 @@ if [ -f "$HISTORY_FILE" ]; then
761
791
  if [ "$is_readonly" != "true" ] && [ -n "$file_path" ]; then
762
792
  consecutive_file=$(printf '%s\n' "$last_n" \
763
793
  | grep -F -e "$path_match" \
764
- | grep -cF -e "\"edit_hash\":\"${edit_hash}\"" 2>/dev/null || true)
794
+ | grep -cF -e "$edit_hash_match" 2>/dev/null || true)
765
795
  [ -n "$consecutive_file" ] || consecutive_file=0
766
796
  if [ "$consecutive_file" -ge "$HARD_BLOCK_THRESHOLD" ]; then
767
797
  hard_block=true
@@ -791,7 +821,7 @@ if [ -f "$HISTORY_FILE" ]; then
791
821
  consecutive_tool_target=$(printf '%s\n' "$last_n" \
792
822
  | grep -F -e "\"tool\":\"${tool_name}\"" \
793
823
  | grep -F -e "$path_match" \
794
- | grep -cF -e "\"edit_hash\":\"${edit_hash}\"" 2>/dev/null || true)
824
+ | grep -cF -e "$edit_hash_match" 2>/dev/null || true)
795
825
  [ -n "$consecutive_tool_target" ] || consecutive_tool_target=0
796
826
  if [ "$consecutive_tool_target" -ge "$HARD_BLOCK_THRESHOLD" ]; then
797
827
  hard_block=true
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.1.67",
2
+ "version": "1.1.68",
3
3
  "lastUpdated": "2026-09-03",
4
4
  "omcustomMinClaudeCode": "2.1.121",
5
5
  "omcustomMinClaudeCodeReason": "Sensitive-path direct Write/Edit on .claude/** under bypassPermissions (R010 deprecation, #1101)",