@ccoalm/ccl-skills 0.14.0 → 0.15.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.
Files changed (36) hide show
  1. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/SKILL.md +19 -24
  2. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/references/client-routing.md +32 -32
  3. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/references/manual-invocation-and-prompts.md +16 -14
  4. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/references/staged-review-contract.md +24 -26
  5. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/AGENTS.md +11 -0
  6. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/claude_review.sh +60 -209
  7. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/init_policy_matrix.py +114 -367
  8. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/parse_probe_result.py +52 -672
  9. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/review_gate.py +10 -2
  10. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/runtime-surface-verification-design.md +4 -2
  11. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_claude_review_probe.sh +77 -444
  12. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_init_policy_matrix.sh +33 -98
  13. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_parse_probe_result.sh +57 -173
  14. package/dist/assets/marketplace/plugins/ccl-skills/skills/defect-diagnosis/SKILL.md +1 -1
  15. package/dist/assets/marketplace/plugins/ccl-skills/skills/grill-me/SKILL.md +1 -1
  16. package/dist/assets/marketplace/plugins/ccl-skills/skills/miniapp-product-dev/SKILL.md +1 -1
  17. package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-observability/SKILL.md +1 -1
  18. package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-release-engineering/SKILL.md +1 -1
  19. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/SKILL.md +2 -2
  20. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/rd-standards-doc-family-checklist.md +2 -2
  21. package/dist/assets/marketplace/plugins/ccl-skills/skills/requirement-baseline/SKILL.md +1 -1
  22. package/dist/assets/marketplace/plugins/ccl-skills/skills/requirement-doc-writer/SKILL.md +1 -1
  23. package/dist/assets/marketplace/plugins/ccl-skills/skills/requirement-scope/SKILL.md +1 -1
  24. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/eval-routing.md +6 -0
  25. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/external-practice-controls.md +1 -1
  26. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/source-register.md +39 -0
  27. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/eval-routing-bank.rb +62 -3
  28. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/impact-chain-gate.rb +114 -10
  29. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/review_ledger_binding.py +36 -13
  30. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_ccl_impact_chain_refscripts.sh +188 -14
  31. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_ccl_regressions.sh +2 -0
  32. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_eval_routing_bank_resolution.sh +253 -0
  33. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_impact_chain_gate_verdict_differential.sh +49 -25
  34. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_review_ledger_binding.sh +63 -5
  35. package/dist/assets/release.json +41 -36
  36. package/package.json +1 -1
@@ -25,9 +25,6 @@ Usage: claude [options] [prompt]
25
25
  --no-session-persistence
26
26
  --effort <level>
27
27
  HELP
28
- if [ "${CLAUDE_FAKE_NO_MAX_BUDGET:-0}" != "1" ]; then
29
- printf '%s\n' ' --max-budget-usd <amount>'
30
- fi
31
28
  if [ "${CLAUDE_FAKE_NO_VERBOSE:-0}" != "1" ]; then
32
29
  printf '%s\n' ' --verbose'
33
30
  fi
@@ -88,9 +85,6 @@ fi
88
85
 
89
86
  prompt="$(cat)"
90
87
  is_host_baseline=0
91
- if [ "$prompt" = "Return a short acknowledgement." ]; then
92
- is_host_baseline=1
93
- fi
94
88
  if [ -n "${CLAUDE_ENV_LOG:-}" ]; then
95
89
  printf '%s\t%s\t%s\n' \
96
90
  "$is_host_baseline" \
@@ -103,9 +97,6 @@ if [ -n "${CLAUDE_ARGV_LOG:-}" ]; then
103
97
  # with the invocation kind, then the argv one token per line. The wrapper must
104
98
  # make exactly one model call for a conforming review/challenge.
105
99
  argv_kind=main
106
- if [ "$is_host_baseline" = "1" ]; then
107
- argv_kind=host-baseline
108
- fi
109
100
  printf '\037%s\n' "$argv_kind" >> "$CLAUDE_ARGV_LOG"
110
101
  for a in "$@"; do printf '%s\n' "$a"; done >> "$CLAUDE_ARGV_LOG"
111
102
  fi
@@ -150,35 +141,6 @@ for arg in "$@"; do
150
141
  expect_plugin_dir_value=1
151
142
  fi
152
143
  done
153
- if [ "$is_host_baseline" = "1" ]; then
154
- if [ "${CLAUDE_FAKE_BASELINE_SLEEP_S:-0}" != "0" ]; then
155
- sleep "$CLAUDE_FAKE_BASELINE_SLEEP_S"
156
- fi
157
- if [ "${CLAUDE_FAKE_BASELINE_WRITE:-0}" = "1" ]; then
158
- mkdir -p baseline-leak/nested
159
- printf '%s\n' leak > baseline-leak/nested/state
160
- fi
161
- if [ "${CLAUDE_FAKE_BASELINE_SIGNAL:-0}" = "1" ]; then
162
- kill -TERM "$$"
163
- fi
164
- baseline_commands='["auto-mode-setup","doctor"]'
165
- baseline_skills='[]'
166
- if [ "${CLAUDE_FAKE_HOST_VOCABULARY:-0}" = "1" ] \
167
- || [ "${CLAUDE_FAKE_HOST_VOCABULARY_PLUS_BREACH:-0}" = "1" ]; then
168
- baseline_commands='["auto-mode-setup","doctor","brand-new-builtin"]'
169
- fi
170
- if [ "${CLAUDE_FAKE_BASELINE_NEW_SKILL:-0}" = "1" ]; then
171
- baseline_skills='["brand-new-host-skill"]'
172
- fi
173
- baseline_tools='[]'
174
- if [ "${CLAUDE_FAKE_BASELINE_TOOL:-0}" = "1" ]; then
175
- baseline_tools='["Read"]'
176
- fi
177
- printf '{"type":"system","subtype":"init","claude_code_version":"%s","permissionMode":"default","tools":%s,"mcp_servers":[],"slash_commands":%s,"terminal_slash_commands":["doctor"],"skills":%s,"plugins":[]}\n' \
178
- "${CLAUDE_FAKE_BASELINE_VERSION:-2.1.233}" "$baseline_tools" "$baseline_commands" "$baseline_skills"
179
- printf '%s\n' '{"type":"result","subtype":"error_max_budget_usd","is_error":true,"result":"budget exhausted after init"}'
180
- exit "${CLAUDE_FAKE_BASELINE_RC:-1}"
181
- fi
182
144
  if [ -n "$plugin_dir_value" ] && [ -n "${CLAUDE_NATIVE_PLUGIN_MARKER:-}" ]; then
183
145
  [ -f "$plugin_dir_value/.claude-plugin/plugin.json" ] \
184
146
  && [ -f "$plugin_dir_value/skills/testing-strategy/SKILL.md" ] \
@@ -256,15 +218,6 @@ if [ "$has_stream_json" = "1" ]; then
256
218
  if [ "${CLAUDE_FAKE_HOST_VOCABULARY:-0}" = "1" ]; then
257
219
  customization_fields='"mcp_servers":[],"slash_commands":["ccl-skills:testing-strategy","brand-new-builtin"],"skills":["testing-strategy"],"plugins":["ccl-skills"]'
258
220
  fi
259
- if [ "${CLAUDE_FAKE_BASELINE_NEW_SKILL:-0}" = "1" ]; then
260
- customization_fields='"mcp_servers":[],"slash_commands":["ccl-skills:testing-strategy"],"skills":["testing-strategy","brand-new-host-skill"],"plugins":["ccl-skills"]'
261
- fi
262
- if [ "${CLAUDE_FAKE_UNBASELINED_HOST_VOCABULARY:-0}" = "1" ]; then
263
- customization_fields='"mcp_servers":[],"slash_commands":["ccl-skills:testing-strategy","formal-only-command"],"skills":["testing-strategy"],"plugins":["ccl-skills"]'
264
- fi
265
- if [ "${CLAUDE_FAKE_HOST_VOCABULARY_PLUS_BREACH:-0}" = "1" ]; then
266
- customization_fields='"mcp_servers":[],"slash_commands":["ccl-skills:testing-strategy","brand-new-builtin","rogue:exfil"],"skills":["testing-strategy"],"plugins":["ccl-skills"]'
267
- fi
268
221
  if [ "${CLAUDE_FAKE_COLLIDING_CUSTOMIZATION:-0}" = "1" ]; then
269
222
  customization_fields='"mcp_servers":[],"slash_commands":["ccl-skills:testing-strategy"],"skills":["testing-strategy","debug","debug"],"plugins":["ccl-skills"]'
270
223
  fi
@@ -628,24 +581,51 @@ if grep -Fxq -- '--disable-slash-commands' "$tmp_dir/native-skill-argv.log"; the
628
581
  exit 1
629
582
  fi
630
583
 
584
+ # A plugin manifest that declares an executable surface is not loaded. The
585
+ # review still runs -- without owner skills, with host commands disabled, and
586
+ # with the binding reported as unavailable so the controller can see it.
631
587
  printf '%s\n' '{"name":"ccl-skills","skills":"./skills/","hooks":"./hooks/hooks.json"}' >"$tmp_dir/ccl-plugin/.claude-plugin/plugin.json"
632
588
  rm -f "$tmp_dir/native-skill-plugin-ok"
633
- set +e
589
+ : >"$tmp_dir/native-skill-unsafe-manifest-argv.log"
634
590
  PATH="$tmp_dir/bin:$PATH" CLAUDE_NATIVE_PLUGIN_MARKER="$tmp_dir/native-skill-plugin-ok" \
591
+ CLAUDE_ARGV_LOG="$tmp_dir/native-skill-unsafe-manifest-argv.log" \
635
592
  "$script_dir/claude_review.sh" challenge --cwd "$tmp_dir/repo" \
636
593
  --diff-file "$tmp_dir/frozen.patch" --review-profile-file "$tmp_dir/native-review-profile.json" \
637
594
  --skill-registry-root "$tmp_dir/ccl-plugin/skills" --review-skill testing-strategy \
638
595
  >"$tmp_dir/native-skill-unsafe-manifest.json"
639
- native_skill_unsafe_manifest_rc=$?
640
- set -e
641
- if [ "$native_skill_unsafe_manifest_rc" -ne 2 ]; then
642
- printf 'expected unsafe Claude plugin manifest to fail inconclusively with rc=2, got %s\n' "$native_skill_unsafe_manifest_rc" >&2
596
+ test ! -e "$tmp_dir/native-skill-plugin-ok"
597
+ grep -q '"native_skill_binding": "unavailable"' "$tmp_dir/native-skill-unsafe-manifest.json"
598
+ if grep -Fxq -- '--plugin-dir' "$tmp_dir/native-skill-unsafe-manifest-argv.log"; then
599
+ printf 'a plugin manifest with an executable surface must not be loaded\n' >&2
643
600
  exit 1
644
601
  fi
645
- test ! -e "$tmp_dir/native-skill-plugin-ok"
646
- grep -q '"reason_code": "capability_missing"' "$tmp_dir/native-skill-unsafe-manifest.json"
602
+ grep -Fxq -- '--disable-slash-commands' "$tmp_dir/native-skill-unsafe-manifest-argv.log"
647
603
  printf '%s\n' '{"name":"ccl-skills","skills":"./skills/"}' >"$tmp_dir/ccl-plugin/.claude-plugin/plugin.json"
648
604
 
605
+ # An installed registry the controller profile does not match -- an absent or
606
+ # older CCL install -- costs the owner-skill binding, never the review.
607
+ mkdir -p "$tmp_dir/stale-plugin/.claude-plugin" "$tmp_dir/stale-plugin/skills/testing-strategy"
608
+ printf '%s\n' '{"name":"ccl-skills","skills":"./skills/"}' >"$tmp_dir/stale-plugin/.claude-plugin/plugin.json"
609
+ printf '%s\n' '---' 'name: testing-strategy' 'description: an older release' '---' '' 'Review tests differently.' >"$tmp_dir/stale-plugin/skills/testing-strategy/SKILL.md"
610
+ : >"$tmp_dir/native-skill-stale-registry-argv.log"
611
+ PATH="$tmp_dir/bin:$PATH" CLAUDE_ARGV_LOG="$tmp_dir/native-skill-stale-registry-argv.log" \
612
+ "$script_dir/claude_review.sh" challenge --cwd "$tmp_dir/repo" \
613
+ --diff-file "$tmp_dir/frozen.patch" --review-profile-file "$tmp_dir/native-review-profile.json" \
614
+ --skill-registry-root "$tmp_dir/stale-plugin/skills" --review-skill testing-strategy \
615
+ >"$tmp_dir/native-skill-stale-registry.json"
616
+ grep -q '"native_skill_binding": "unavailable"' "$tmp_dir/native-skill-stale-registry.json"
617
+ grep -q '"mode": "challenge"' "$tmp_dir/native-skill-stale-registry.json"
618
+ if grep -Fxq -- '--plugin-dir' "$tmp_dir/native-skill-stale-registry-argv.log"; then
619
+ printf 'an unverified registry must not be loaded as the owner plugin\n' >&2
620
+ exit 1
621
+ fi
622
+ PATH="$tmp_dir/bin:$PATH" \
623
+ "$script_dir/claude_review.sh" challenge --cwd "$tmp_dir/repo" \
624
+ --diff-file "$tmp_dir/frozen.patch" --review-profile-file "$tmp_dir/native-review-profile.json" \
625
+ --skill-registry-root "$tmp_dir/nowhere/skills" --review-skill testing-strategy \
626
+ >"$tmp_dir/native-skill-missing-registry.json"
627
+ grep -q '"native_skill_binding": "unavailable"' "$tmp_dir/native-skill-missing-registry.json"
628
+
649
629
  set +e
650
630
  PATH="$tmp_dir/bin:$PATH" CLAUDE_FAKE_NO_BARE=1 \
651
631
  "$script_dir/claude_review.sh" challenge --cwd "$tmp_dir/repo" \
@@ -674,294 +654,34 @@ PATH="$tmp_dir/bin:$PATH" CLAUDE_FAKE_BUILTIN_ONLY_WITH_PLUGIN=1 \
674
654
  >"$tmp_dir/native-skill-builtins-only.json"
675
655
  grep -q '"native_skill_binding": "established"' "$tmp_dir/native-skill-builtins-only.json"
676
656
 
677
- printf '%s\n' \
678
- '{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":[],"slash_commands":[],"skills":["code-review"],"plugins":["ccl-skills"]}' \
679
- '{"type":"result","subtype":"success","is_error":false,"result":"ok"}' \
680
- >"$tmp_dir/ambiguous-selected-owner-events.jsonl"
681
- : >"$tmp_dir/ambiguous-selected-owner-stderr.log"
682
- set +e
683
- python3 "$script_dir/parse_probe_result.py" 0 \
684
- "$tmp_dir/ambiguous-selected-owner-events.jsonl" \
685
- "$tmp_dir/ambiguous-selected-owner-stderr.log" \
686
- --require-empty-init --expected-native-skills code-review \
687
- --required-native-skills code-review --runtime-surface-only \
688
- >"$tmp_dir/ambiguous-selected-owner-result.json"
689
- ambiguous_selected_owner_rc=$?
690
- set -e
691
- if [ "$ambiguous_selected_owner_rc" -ne 1 ]; then
692
- printf 'expected built-in/selected owner collision to fail parser, got %s\n' "$ambiguous_selected_owner_rc" >&2
693
- exit 1
694
- fi
695
-
696
- printf '%s\n' '{"type":"result","subtype":"success","is_error":false,"result":"ok"}' \
697
- >"$tmp_dir/native-skill-no-init-events.jsonl"
698
- set +e
699
- python3 "$script_dir/parse_probe_result.py" 0 \
700
- "$tmp_dir/native-skill-no-init-events.jsonl" \
701
- "$tmp_dir/ambiguous-selected-owner-stderr.log" \
702
- --expected-native-skills testing-strategy \
703
- --required-native-skills testing-strategy \
704
- >"$tmp_dir/native-skill-no-init-result.json"
705
- native_skill_no_init_rc=$?
706
- set -e
707
- if [ "$native_skill_no_init_rc" -ne 1 ]; then
708
- printf 'expected native skill binding without stream init to fail parser, got %s\n' "$native_skill_no_init_rc" >&2
709
- exit 1
710
- fi
711
-
712
- set +e
713
- PATH="$tmp_dir/bin:$PATH" CLAUDE_FAKE_EMPTY_NATIVE_CUSTOMIZATIONS=1 \
714
- "$script_dir/claude_review.sh" challenge --cwd "$tmp_dir/repo" \
715
- --diff-file "$tmp_dir/frozen.patch" --review-profile-file "$tmp_dir/native-review-profile.json" \
716
- --skill-registry-root "$tmp_dir/ccl-plugin/skills" --review-skill testing-strategy \
717
- >"$tmp_dir/native-skill-missing-plugin.json"
718
- native_skill_missing_rc=$?
719
- set -e
720
- if [ "$native_skill_missing_rc" -ne 2 ]; then
721
- printf 'expected missing CCL plugin registration to exit 2, got %s\n' "$native_skill_missing_rc" >&2
722
- exit 1
723
- fi
724
- if grep -q '"native_skill_binding": "established"' "$tmp_dir/native-skill-missing-plugin.json"; then
725
- printf 'missing CCL plugin registration claimed established binding\n' >&2
726
- exit 1
727
- fi
728
-
729
- set +e
730
- PATH="$tmp_dir/bin:$PATH" CLAUDE_FAKE_OMIT_SELECTED_CUSTOMIZATION=1 \
731
- "$script_dir/claude_review.sh" challenge --cwd "$tmp_dir/repo" \
732
- --diff-file "$tmp_dir/frozen.patch" --review-profile-file "$tmp_dir/native-review-profile.json" \
733
- --skill-registry-root "$tmp_dir/ccl-plugin/skills" --review-skill testing-strategy \
734
- >"$tmp_dir/native-skill-plugin-only-public-surface.json"
735
- native_skill_omitted_rc=$?
736
- set -e
737
- if [ "$native_skill_omitted_rc" -ne 2 ]; then
738
- printf 'expected an enumerated surface missing the selected owner to exit 2, got %s\n' "$native_skill_omitted_rc" >&2
739
- exit 1
740
- fi
741
-
742
- PATH="$tmp_dir/bin:$PATH" CLAUDE_FAKE_BUILTIN_CUSTOMIZATIONS=1 \
743
- "$script_dir/claude_review.sh" challenge --cwd "$tmp_dir/repo" \
744
- --diff-file "$tmp_dir/frozen.patch" --review-profile-file "$tmp_dir/native-review-profile.json" \
745
- --skill-registry-root "$tmp_dir/ccl-plugin/skills" --review-skill testing-strategy \
746
- >"$tmp_dir/native-skill-builtins.json"
747
-
748
- set +e
749
- PATH="$tmp_dir/bin:$PATH" CLAUDE_FAKE_EXTRA_CUSTOMIZATION=1 \
750
- "$script_dir/claude_review.sh" challenge --cwd "$tmp_dir/repo" \
751
- --diff-file "$tmp_dir/frozen.patch" --review-profile-file "$tmp_dir/native-review-profile.json" \
752
- --skill-registry-root "$tmp_dir/ccl-plugin/skills" --review-skill testing-strategy \
753
- >"$tmp_dir/native-skill-extra-customization.json"
754
- native_skill_extra_rc=$?
755
- set -e
756
- if [ "$native_skill_extra_rc" -ne 2 ]; then
757
- printf 'expected unrelated native customization to exit 2, got %s\n' "$native_skill_extra_rc" >&2
758
- exit 1
759
- fi
760
- python3 - "$tmp_dir/native-skill-extra-customization.json" <<'PY'
761
- import json
762
- import sys
763
-
764
- payload = json.load(open(sys.argv[1], encoding="utf-8"))
765
- reason = payload["reason"]
766
- assert "slash_commands:unrelated:danger" in reason, payload
767
- assert "skills:unrelated-skill" in reason, payload
768
- assert "description" not in reason, payload
769
- PY
770
-
771
- # Host-vocabulary routing, asserted through the real wrapper. A new built-in
772
- # reported by the same-version, no-plugin baseline is safe to accept; a command
773
- # absent from that baseline remains a proven customization and must not be
774
- # laundered by the presence of an accepted built-in.
775
- PATH="$tmp_dir/bin:$PATH" CLAUDE_FAKE_HOST_VOCABULARY=1 \
776
- CLAUDE_CWD_LOG="$tmp_dir/native-skill-cwds.log" \
777
- CLAUDE_ENV_LOG="$tmp_dir/native-skill-env.log" \
778
- "$script_dir/claude_review.sh" challenge --cwd "$tmp_dir/repo" \
779
- --diff-file "$tmp_dir/frozen.patch" --review-profile-file "$tmp_dir/native-review-profile.json" \
780
- --skill-registry-root "$tmp_dir/ccl-plugin/skills" --review-skill testing-strategy \
781
- >"$tmp_dir/native-skill-host-vocabulary.json"
782
- python3 - "$tmp_dir/native-skill-host-vocabulary.json" <<'PY'
783
- import json
784
- import sys
785
-
786
- payload = json.load(open(sys.argv[1], encoding="utf-8"))
787
- assert payload["mode"] == "challenge", payload
788
- assert payload["native_skill_binding"] == "established", payload
789
- PY
790
- python3 - "$tmp_dir/native-skill-cwds.log" "$tmp_dir/repo" <<'PY'
791
- import os
792
- import sys
793
-
794
- rows = [line.rstrip("\n").split("\t", 1) for line in open(sys.argv[1], encoding="utf-8")]
795
- baseline_cwds = [cwd for baseline, cwd in rows if baseline == "1"]
796
- assert len(baseline_cwds) == 1, rows
797
- assert os.path.realpath(baseline_cwds[0]) != os.path.realpath(sys.argv[2]), rows
798
- PY
799
- python3 - "$tmp_dir/native-skill-env.log" <<'PY'
800
- import sys
801
-
802
- rows = [line.rstrip("\n").split("\t") for line in open(sys.argv[1], encoding="utf-8")]
803
- baseline_env = [row[1:] for row in rows if row[0] == "1"]
804
- assert baseline_env == [["1", "1"]], rows
805
- PY
806
-
807
- set +e
808
- PATH="$tmp_dir/bin:$PATH" CLAUDE_FAKE_BASELINE_NEW_SKILL=1 \
809
- "$script_dir/claude_review.sh" challenge --cwd "$tmp_dir/repo" \
810
- --diff-file "$tmp_dir/frozen.patch" --review-profile-file "$tmp_dir/native-review-profile.json" \
811
- --skill-registry-root "$tmp_dir/ccl-plugin/skills" --review-skill testing-strategy \
812
- >"$tmp_dir/native-skill-baseline-new-skill.json"
813
- baseline_new_skill_rc=$?
814
- set -e
815
- if [ "$baseline_new_skill_rc" -ne 2 ]; then
816
- printf 'expected a baseline-only new skill to refuse (exit 2), got %s\n' \
817
- "$baseline_new_skill_rc" >&2
818
- exit 1
819
- fi
820
- python3 - "$tmp_dir/native-skill-baseline-new-skill.json" <<'PY'
821
- import json
822
- import sys
823
-
824
- payload = json.load(open(sys.argv[1], encoding="utf-8"))
825
- assert payload["reason_code"] == "capability_missing", payload
826
- assert payload["fallback_eligible"] is True, payload
827
- assert payload["next_action"] == "fallback", payload
828
- assert "skills:brand-new-host-skill" in payload["reason"], payload
829
- PY
830
-
831
- set +e
832
- PATH="$tmp_dir/bin:$PATH" CLAUDE_FAKE_UNBASELINED_HOST_VOCABULARY=1 \
833
- "$script_dir/claude_review.sh" challenge --cwd "$tmp_dir/repo" \
834
- --diff-file "$tmp_dir/frozen.patch" --review-profile-file "$tmp_dir/native-review-profile.json" \
835
- --skill-registry-root "$tmp_dir/ccl-plugin/skills" --review-skill testing-strategy \
836
- >"$tmp_dir/native-skill-unbaselined-host-vocabulary.json"
837
- unbaselined_host_vocabulary_rc=$?
838
- set -e
839
- if [ "$unbaselined_host_vocabulary_rc" -ne 2 ]; then
840
- printf 'expected a formal-only host-vocabulary entry to refuse (exit 2), got %s\n' \
841
- "$unbaselined_host_vocabulary_rc" >&2
842
- exit 1
843
- fi
844
- python3 - "$tmp_dir/native-skill-unbaselined-host-vocabulary.json" <<'PY'
845
- import json
846
- import sys
847
-
848
- payload = json.load(open(sys.argv[1], encoding="utf-8"))
849
- assert payload["reason_code"] == "capability_missing", payload
850
- assert payload["fallback_eligible"] is True, payload
851
- assert payload["next_action"] == "fallback", payload
852
- assert "slash_commands:formal-only-command" in payload["reason"], payload
853
- PY
854
-
855
- set +e
856
- PATH="$tmp_dir/bin:$PATH" CLAUDE_FAKE_HOST_VOCABULARY_PLUS_BREACH=1 \
857
- "$script_dir/claude_review.sh" challenge --cwd "$tmp_dir/repo" \
657
+ # What the loaded plugin's init enumerates -- nothing, other registry entries,
658
+ # the host's own built-ins, names this repo never heard of, namespaced entries,
659
+ # duplicates -- is vocabulary. The plugin was loaded through --plugin-dir and
660
+ # the owners were named in the prompt, so every one of these is a bound run.
661
+ for vocabulary_fixture in \
662
+ CLAUDE_FAKE_EMPTY_NATIVE_CUSTOMIZATIONS \
663
+ CLAUDE_FAKE_OMIT_SELECTED_CUSTOMIZATION \
664
+ CLAUDE_FAKE_BUILTIN_CUSTOMIZATIONS \
665
+ CLAUDE_FAKE_EXTRA_CUSTOMIZATION \
666
+ CLAUDE_FAKE_HOST_VOCABULARY \
667
+ CLAUDE_FAKE_COLLIDING_CUSTOMIZATION
668
+ do
669
+ env "PATH=$tmp_dir/bin:$PATH" "$vocabulary_fixture=1" \
670
+ "$script_dir/claude_review.sh" challenge --cwd "$tmp_dir/repo" \
858
671
  --diff-file "$tmp_dir/frozen.patch" --review-profile-file "$tmp_dir/native-review-profile.json" \
859
672
  --skill-registry-root "$tmp_dir/ccl-plugin/skills" --review-skill testing-strategy \
860
- >"$tmp_dir/native-skill-host-vocabulary-breach.json"
861
- host_vocabulary_breach_rc=$?
862
- set -e
863
- if [ "$host_vocabulary_breach_rc" -ne 2 ]; then
864
- printf 'expected a breach alongside host vocabulary to refuse (exit 2), got %s\n' "$host_vocabulary_breach_rc" >&2
865
- exit 1
866
- fi
867
- python3 - "$tmp_dir/native-skill-host-vocabulary-breach.json" <<'PY'
673
+ >"$tmp_dir/native-skill-vocabulary-$vocabulary_fixture.json"
674
+ python3 - "$tmp_dir/native-skill-vocabulary-$vocabulary_fixture.json" "$vocabulary_fixture" <<'PY'
868
675
  import json
869
676
  import sys
870
677
 
871
678
  payload = json.load(open(sys.argv[1], encoding="utf-8"))
872
- # the namespaced entry is a PROVEN customization, so the run must stay terminal
873
- # no matter that an unclassifiable name sits beside it.
874
- assert payload["reason_code"] == "tool_boundary_violation", payload
875
- assert payload["fallback_eligible"] is False, payload
876
- assert payload["next_action"] == "stop_reviewer_lane", payload
877
- assert "unclassifiable host-vocabulary entry" not in payload["reason"], payload
679
+ assert payload["mode"] == "challenge", (sys.argv[2], payload)
680
+ assert payload["native_skill_binding"] == "established", (sys.argv[2], payload)
681
+ assert "reason" not in payload, (sys.argv[2], payload)
878
682
  PY
879
-
880
- for baseline_failure in version-mismatch exposed-tool; do
881
- expected_reason_code=capability_missing
882
- set +e
883
- if [ "$baseline_failure" = "version-mismatch" ]; then
884
- expected_reason="host-baseline-mismatch"
885
- PATH="$tmp_dir/bin:$PATH" CLAUDE_FAKE_MAIN_VERSION=2.1.234 \
886
- "$script_dir/claude_review.sh" challenge --cwd "$tmp_dir/repo" \
887
- --diff-file "$tmp_dir/frozen.patch" --review-profile-file "$tmp_dir/native-review-profile.json" \
888
- --skill-registry-root "$tmp_dir/ccl-plugin/skills" --review-skill testing-strategy \
889
- >"$tmp_dir/native-skill-$baseline_failure.json"
890
- else
891
- expected_reason="Claude host-vocabulary baseline exposed a tool"
892
- PATH="$tmp_dir/bin:$PATH" CLAUDE_FAKE_BASELINE_TOOL=1 \
893
- "$script_dir/claude_review.sh" challenge --cwd "$tmp_dir/repo" \
894
- --diff-file "$tmp_dir/frozen.patch" --review-profile-file "$tmp_dir/native-review-profile.json" \
895
- --skill-registry-root "$tmp_dir/ccl-plugin/skills" --review-skill testing-strategy \
896
- >"$tmp_dir/native-skill-$baseline_failure.json"
897
- fi
898
- baseline_failure_rc=$?
899
- set -e
900
- if [ "$baseline_failure_rc" -ne 2 ]; then
901
- printf 'expected Claude host-baseline %s to exit 2, got %s\n' \
902
- "$baseline_failure" "$baseline_failure_rc" >&2
903
- exit 1
904
- fi
905
- grep -q "\"reason_code\": \"$expected_reason_code\"" \
906
- "$tmp_dir/native-skill-$baseline_failure.json"
907
- grep -Fq "$expected_reason" "$tmp_dir/native-skill-$baseline_failure.json"
908
683
  done
909
684
 
910
- rm -f "$tmp_dir/native-skill-baseline-write-cwds.log"
911
- set +e
912
- PATH="$tmp_dir/bin:$PATH" CLAUDE_FAKE_BASELINE_WRITE=1 \
913
- CLAUDE_CWD_LOG="$tmp_dir/native-skill-baseline-write-cwds.log" \
914
- "$script_dir/claude_review.sh" challenge --cwd "$tmp_dir/repo" \
915
- --diff-file "$tmp_dir/frozen.patch" --review-profile-file "$tmp_dir/native-review-profile.json" \
916
- --skill-registry-root "$tmp_dir/ccl-plugin/skills" --review-skill testing-strategy \
917
- >"$tmp_dir/native-skill-baseline-write.json"
918
- baseline_write_rc=$?
919
- set -e
920
- if [ "$baseline_write_rc" -ne 2 ]; then
921
- printf 'expected a host-baseline cwd write to exit 2, got %s\n' "$baseline_write_rc" >&2
922
- exit 1
923
- fi
924
- grep -Fq 'Claude host-vocabulary baseline wrote into its isolated working directory' \
925
- "$tmp_dir/native-skill-baseline-write.json"
926
- baseline_write_cwd="$(awk -F '\t' '$1 == "1" { print $2 }' "$tmp_dir/native-skill-baseline-write-cwds.log")"
927
- [ -n "$baseline_write_cwd" ] && [ ! -e "$baseline_write_cwd" ]
928
-
929
- set +e
930
- PATH="$tmp_dir/bin:$PATH" CLAUDE_FAKE_BASELINE_WRITE=1 CLAUDE_FAKE_BASELINE_SIGNAL=1 \
931
- "$script_dir/claude_review.sh" challenge --cwd "$tmp_dir/repo" \
932
- --diff-file "$tmp_dir/frozen.patch" --review-profile-file "$tmp_dir/native-review-profile.json" \
933
- --skill-registry-root "$tmp_dir/ccl-plugin/skills" --review-skill testing-strategy \
934
- >"$tmp_dir/native-skill-baseline-signal-after-write.json"
935
- baseline_signal_after_write_rc=$?
936
- set -e
937
- if [ "$baseline_signal_after_write_rc" -ne 2 ]; then
938
- printf 'expected a signaled host baseline to exit 2, got %s\n' \
939
- "$baseline_signal_after_write_rc" >&2
940
- exit 1
941
- fi
942
- python3 - "$tmp_dir/native-skill-baseline-signal-after-write.json" <<'PY'
943
- import json
944
- import sys
945
-
946
- payload = json.load(open(sys.argv[1], encoding="utf-8"))
947
- assert payload["reason_code"] == "operator_interrupt", payload
948
- assert payload["fallback_eligible"] is False, payload
949
- assert payload["next_action"] == "stop_reviewer_lane", payload
950
- PY
951
-
952
- set +e
953
- PATH="$tmp_dir/bin:$PATH" CLAUDE_FAKE_COLLIDING_CUSTOMIZATION=1 \
954
- "$script_dir/claude_review.sh" challenge --cwd "$tmp_dir/repo" \
955
- --diff-file "$tmp_dir/frozen.patch" --review-profile-file "$tmp_dir/native-review-profile.json" \
956
- --skill-registry-root "$tmp_dir/ccl-plugin/skills" --review-skill testing-strategy \
957
- >"$tmp_dir/native-skill-collision.json"
958
- native_skill_collision_rc=$?
959
- set -e
960
- if [ "$native_skill_collision_rc" -ne 2 ]; then
961
- printf 'expected colliding native customization to exit 2, got %s\n' "$native_skill_collision_rc" >&2
962
- exit 1
963
- fi
964
-
965
685
  awk 'BEGIN { printf "{\"x\":\""; for (i = 0; i < 39992; i++) printf "p"; printf "\"}" }' > "$tmp_dir/max-review-profile.json"
966
686
  PATH="$tmp_dir/bin:$PATH" CLAUDE_PROMPT_LOG="$tmp_dir/max-profile-prompt.log" \
967
687
  "$script_dir/claude_review.sh" challenge --cwd "$tmp_dir/repo" \
@@ -1522,66 +1242,24 @@ import sys
1522
1242
  payload = json.load(open(sys.argv[1], encoding="utf-8"))
1523
1243
  assert payload["mode"] == "review", payload
1524
1244
  assert payload["status"] == "inconclusive", payload
1525
- assert "cannot prove that safe mode disables inherited Claude skills" in payload["reason"], payload
1526
- PY
1527
-
1528
- set +e
1529
- PATH="$tmp_dir/bin:$PATH" CLAUDE_FAKE_SAFE_MODE_NO_SKILL_CONTRACT=1 \
1530
- "$script_dir/claude_review.sh" review --cwd "$tmp_dir/repo" \
1531
- > "$tmp_dir/review-safe-mode-without-skill-contract.json"
1532
- safe_mode_without_skill_contract_rc=$?
1533
- set -e
1534
- if [ "$safe_mode_without_skill_contract_rc" -ne 2 ]; then
1535
- printf 'expected review without a documented safe-mode skill boundary to exit 2, got %s\n' \
1536
- "$safe_mode_without_skill_contract_rc" >&2
1537
- exit 1
1538
- fi
1539
- grep -Fq 'cannot prove that safe mode disables inherited Claude skills' \
1540
- "$tmp_dir/review-safe-mode-without-skill-contract.json"
1541
-
1542
- set +e
1543
- PATH="$tmp_dir/bin:$PATH" CLAUDE_FAKE_SAFE_MODE_NO_SKILL_CONTRACT=1 \
1544
- CLAUDE_FAKE_SHORT_OPTION_SKILL_TEXT=1 \
1545
- "$script_dir/claude_review.sh" review --cwd "$tmp_dir/repo" \
1546
- > "$tmp_dir/review-safe-mode-short-option-spill.json"
1547
- safe_mode_short_option_spill_rc=$?
1548
- set -e
1549
- if [ "$safe_mode_short_option_spill_rc" -ne 2 ]; then
1550
- printf 'expected safe-mode capture to stop before a short-option entry, got %s\n' \
1551
- "$safe_mode_short_option_spill_rc" >&2
1552
- exit 1
1553
- fi
1554
- grep -Fq 'cannot prove that safe mode disables inherited Claude skills' \
1555
- "$tmp_dir/review-safe-mode-short-option-spill.json"
1556
-
1557
- set +e
1558
- PATH="$tmp_dir/bin:$PATH" CLAUDE_FAKE_SAFE_MODE_NO_SKILL_CONTRACT=1 \
1559
- CLAUDE_FAKE_TRAILING_SKILL_TEXT=1 \
1560
- "$script_dir/claude_review.sh" review --cwd "$tmp_dir/repo" \
1561
- > "$tmp_dir/review-safe-mode-trailing-prose.json"
1562
- safe_mode_trailing_prose_rc=$?
1563
- set -e
1564
- if [ "$safe_mode_trailing_prose_rc" -ne 2 ]; then
1565
- printf 'expected safe-mode capture to stop before trailing prose, got %s\n' \
1566
- "$safe_mode_trailing_prose_rc" >&2
1567
- exit 1
1568
- fi
1569
- grep -Fq 'cannot prove that safe mode disables inherited Claude skills' \
1570
- "$tmp_dir/review-safe-mode-trailing-prose.json"
1571
-
1572
- set +e
1573
- PATH="$tmp_dir/bin:$PATH" CLAUDE_FAKE_SAFE_MODE_SKILLS_UNAFFECTED=1 \
1574
- "$script_dir/claude_review.sh" review --cwd "$tmp_dir/repo" \
1575
- > "$tmp_dir/review-safe-mode-skills-unaffected.json"
1576
- safe_mode_skills_unaffected_rc=$?
1577
- set -e
1578
- if [ "$safe_mode_skills_unaffected_rc" -ne 2 ]; then
1579
- printf 'expected negated safe-mode skill boundary to exit 2, got %s\n' \
1580
- "$safe_mode_skills_unaffected_rc" >&2
1581
- exit 1
1582
- fi
1583
- grep -Fq 'cannot prove that safe mode disables inherited Claude skills' \
1584
- "$tmp_dir/review-safe-mode-skills-unaffected.json"
1245
+ assert "has no --safe-mode" in payload["reason"], payload
1246
+ PY
1247
+
1248
+ # The safe-mode HELP PROSE is not parsed. A CLI release that rewords, trims,
1249
+ # or contradicts its description of what safe mode disables still runs: the
1250
+ # flag itself is the isolation, and the pinned tool set proves the rest.
1251
+ for safe_mode_prose in \
1252
+ CLAUDE_FAKE_SAFE_MODE_NO_SKILL_CONTRACT \
1253
+ CLAUDE_FAKE_SAFE_MODE_SKILLS_UNAFFECTED \
1254
+ CLAUDE_FAKE_SHORT_OPTION_SKILL_TEXT \
1255
+ CLAUDE_FAKE_TRAILING_SKILL_TEXT
1256
+ do
1257
+ env "PATH=$tmp_dir/bin:$PATH" "$safe_mode_prose=1" \
1258
+ "$script_dir/claude_review.sh" review --cwd "$tmp_dir/repo" \
1259
+ >"$tmp_dir/review-safe-mode-prose-$safe_mode_prose.json"
1260
+ grep -q '"native_skill_binding": "not_requested"' \
1261
+ "$tmp_dir/review-safe-mode-prose-$safe_mode_prose.json"
1262
+ done
1585
1263
 
1586
1264
  PATH="$tmp_dir/bin:$PATH" CLAUDE_FAKE_SAFE_MODE_DISABLE_STEM=1 \
1587
1265
  "$script_dir/claude_review.sh" review --cwd "$tmp_dir/repo" \
@@ -1600,37 +1278,16 @@ assert payload == {
1600
1278
  }, payload
1601
1279
  PY
1602
1280
 
1603
- set +e
1604
- PATH="$tmp_dir/bin:$PATH" CLAUDE_FAKE_NO_MAX_BUDGET=1 \
1605
- "$script_dir/claude_review.sh" challenge --cwd "$tmp_dir/repo" \
1606
- --diff-file "$tmp_dir/frozen.patch" --review-profile-file "$tmp_dir/native-review-profile.json" \
1607
- --skill-registry-root "$tmp_dir/ccl-plugin/skills" --review-skill testing-strategy \
1608
- >"$tmp_dir/native-skill-no-max-budget.json"
1609
- no_max_budget_rc=$?
1610
- set -e
1611
- if [ "$no_max_budget_rc" -ne 2 ]; then
1612
- printf 'expected missing max-budget support to exit 2, got %s\n' \
1613
- "$no_max_budget_rc" >&2
1614
- exit 1
1615
- fi
1616
- python3 - "$tmp_dir/native-skill-no-max-budget.json" <<'PY'
1617
- import json
1618
- import sys
1619
-
1620
- payload = json.load(open(sys.argv[1], encoding="utf-8"))
1621
- assert payload["reason_code"] == "capability_missing", payload
1622
- assert payload["fallback_eligible"] is True, payload
1623
- assert payload["next_action"] == "fallback", payload
1624
- assert "bounded host-vocabulary baseline" in payload["reason"], payload
1625
- PY
1626
-
1281
+ # A CLI without --disable-slash-commands still runs: host commands are
1282
+ # vocabulary, and the consult's tool set is pinned separately. The repository
1283
+ # consult keeps its ordinary advisory exit.
1627
1284
  set +e
1628
1285
  PATH="$tmp_dir/bin:$PATH" CLAUDE_FAKE_NO_DISABLE_SLASH_COMMANDS=1 \
1629
1286
  "$script_dir/claude_review.sh" consult --cwd "$tmp_dir/repo" --include-diff --extra "Inspect this repository." > "$tmp_dir/consult-no-disable-slash-commands.json"
1630
1287
  no_disable_slash_commands_rc=$?
1631
1288
  set -e
1632
1289
  if [ "$no_disable_slash_commands_rc" -ne 2 ]; then
1633
- printf 'expected repository consult without skill/command isolation to exit 2, got %s\n' "$no_disable_slash_commands_rc" >&2
1290
+ printf 'expected the repository consult advisory exit 2 without --disable-slash-commands, got %s\n' "$no_disable_slash_commands_rc" >&2
1634
1291
  exit 1
1635
1292
  fi
1636
1293
  python3 - "$tmp_dir/consult-no-disable-slash-commands.json" <<'PY'
@@ -1639,8 +1296,8 @@ import sys
1639
1296
 
1640
1297
  payload = json.load(open(sys.argv[1], encoding="utf-8"))
1641
1298
  assert payload["mode"] == "consult", payload
1642
- assert payload["status"] == "inconclusive", payload
1643
- assert "cannot disable Claude skills and commands" in payload["reason"], payload
1299
+ assert payload["status"] != "inconclusive", payload
1300
+ assert payload["consult_scope"] == "repository", payload
1644
1301
  PY
1645
1302
 
1646
1303
  set +e
@@ -2289,28 +1946,4 @@ assert payload["fallback_eligible"] is True, payload
2289
1946
  assert payload["next_action"] == "fallback", payload
2290
1947
  PY
2291
1948
 
2292
- set +e
2293
- PATH="$tmp_dir/bin:$PATH" CLAUDE_FAKE_BASELINE_SLEEP_S=2 CLAUDE_FAKE_MAIN_SLEEP_S=30 \
2294
- "$script_dir/claude_review.sh" challenge --cwd "$tmp_dir/repo" --timeout 5 \
2295
- --diff-file "$tmp_dir/frozen.patch" --review-profile-file "$tmp_dir/native-review-profile.json" \
2296
- --skill-registry-root "$tmp_dir/ccl-plugin/skills" --review-skill testing-strategy \
2297
- > "$tmp_dir/baseline-budget-timeout.json"
2298
- baseline_budget_timeout_rc=$?
2299
- set -e
2300
- if [ "$baseline_budget_timeout_rc" -ne 2 ]; then
2301
- printf 'expected baseline-budgeted main timeout exit 2, got %s\n' \
2302
- "$baseline_budget_timeout_rc" >&2
2303
- exit 1
2304
- fi
2305
- python3 - "$tmp_dir/baseline-budget-timeout.json" <<'PY'
2306
- import json
2307
- import re
2308
- import sys
2309
-
2310
- payload = json.load(open(sys.argv[1], encoding="utf-8"))
2311
- match = re.search(r"after ([0-9]+) seconds", payload["reason"])
2312
- assert payload["reason_code"] == "timeout", payload
2313
- assert match is not None and 1 <= int(match.group(1)) < 5, payload
2314
- PY
2315
-
2316
1949
  printf 'claude_review_runtime_tests_ok\n'