@ccoalm/ccl-skills 0.7.0 → 0.9.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 (127) hide show
  1. package/README.md +2 -2
  2. package/dist/assets/marketplace/plugins/ccl-skills/skills/app-cross-platform-dev/SKILL.md +8 -7
  3. package/dist/assets/marketplace/plugins/ccl-skills/skills/app-cross-platform-dev/references/mobile-quality-release.md +6 -1
  4. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/SKILL.md +16 -17
  5. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/references/client-routing.md +1 -1
  6. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/references/manual-invocation-and-prompts.md +6 -0
  7. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/references/staged-review-contract.md +195 -7
  8. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/references/timeout-auth-and-capabilities.md +3 -3
  9. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/claude_review.sh +13 -5
  10. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/codex_review.sh +9 -3
  11. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/kimi_review.sh +9 -3
  12. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/normalize_review_timeout.sh +22 -0
  13. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/opencode_review.sh +9 -3
  14. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/review_gate.py +1540 -129
  15. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_claude_review_probe.sh +8 -3
  16. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_review_client_compat.py +76 -1
  17. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_review_gate.sh +1858 -3
  18. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_update_review_plan_intent.sh +789 -0
  19. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/update_review_plan_intent.py +513 -0
  20. package/dist/assets/marketplace/plugins/ccl-skills/skills/defect-diagnosis/SKILL.md +1 -0
  21. package/dist/assets/marketplace/plugins/ccl-skills/skills/feature-risk-router/SKILL.md +3 -1
  22. package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/architecture-playbook.md +1 -1
  23. package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/multi-tenant-isolation.md +1 -1
  24. package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/SKILL.md +4 -1
  25. package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/references/state-machine-task-patterns.md +2 -0
  26. package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/SKILL.md +2 -1
  27. package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/inference-capacity-operations.md +24 -0
  28. package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/llm-client-gateway.md +1 -1
  29. package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/model-prompt-evaluation.md +4 -1
  30. package/dist/assets/marketplace/plugins/ccl-skills/skills/miniapp-product-dev/SKILL.md +11 -10
  31. package/dist/assets/marketplace/plugins/ccl-skills/skills/miniapp-product-dev/references/contracts-and-state.md +5 -0
  32. package/dist/assets/marketplace/plugins/ccl-skills/skills/nodejs-service-dev/SKILL.md +64 -0
  33. package/dist/assets/marketplace/plugins/ccl-skills/skills/nodejs-service-dev/agents/openai.yaml +4 -0
  34. package/dist/assets/marketplace/plugins/ccl-skills/skills/nodejs-service-dev/references/async-lifecycle-and-performance.md +73 -0
  35. package/dist/assets/marketplace/plugins/ccl-skills/skills/nodejs-service-dev/references/runtime-and-project-contract.md +58 -0
  36. package/dist/assets/marketplace/plugins/ccl-skills/skills/nodejs-service-dev/references/source-map.md +41 -0
  37. package/dist/assets/marketplace/plugins/ccl-skills/skills/nodejs-service-dev/references/verification-diagnostics-and-security.md +63 -0
  38. package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-observability/SKILL.md +3 -2
  39. package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-observability/references/metrics-conventions.md +8 -1
  40. package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-observability/references/sli-slo-design.md +2 -2
  41. package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-release-engineering/references/canary-and-rollout-strategy.md +16 -2
  42. package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-release-engineering/references/promotion-gate-and-review.md +9 -0
  43. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/SKILL.md +14 -16
  44. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/code-review-checklist.md +4 -0
  45. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/delivery-lifecycle.md +1 -1
  46. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/design-routing-and-readiness.md +10 -14
  47. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/rd-standards-doc-family-checklist.md +1 -0
  48. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/verify-developer-experience.md +1 -1
  49. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/SKILL.md +135 -86
  50. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/behavioral-aesthetic-logic.md +66 -80
  51. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/delivery-contract.md +275 -0
  52. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/design-execution-checklist.md +88 -214
  53. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/design-impl-naming-and-versioning.md +2 -2
  54. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/design-intake-and-acceptance.md +10 -8
  55. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/design-system-source-of-truth.md +6 -5
  56. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/external-ui-ux-quality-benchmarks.md +112 -95
  57. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/frontend-code-evidence-map.md +30 -21
  58. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/interaction-design-patterns.md +22 -3
  59. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/layout-recipes-and-screenshot-acceptance.md +20 -17
  60. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/multi-project-token-consistency.md +7 -9
  61. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/multi-stack-strategy.md +14 -10
  62. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/operational-processing-workflows.md +2 -0
  63. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/platform-mobile-patterns.md +3 -3
  64. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/product-lifecycle-acceptance-and-iteration.md +9 -6
  65. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/product-surface-patterns.md +3 -0
  66. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/source-map.md +37 -10
  67. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/tokens-and-components.md +8 -1
  68. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/ui-ux-audit.md +16 -5
  69. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/ui-ux-design-development.md +16 -5
  70. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/visual-craft.md +4 -2
  71. package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-architecture/references/multi-tenant-isolation.md +1 -1
  72. package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-dev/SKILL.md +4 -1
  73. package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-dev/references/state-machine-task-patterns.md +2 -0
  74. package/dist/assets/marketplace/plugins/ccl-skills/skills/release-coordination/SKILL.md +1 -1
  75. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/SKILL.md +8 -8
  76. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/description-authoring.md +4 -0
  77. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/dual-track-review-gate.md +104 -5
  78. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/extraction-quickstart.md +11 -9
  79. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/r0-leakage-audit.md +102 -0
  80. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/source-register.md +103 -0
  81. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/source-to-skill-extraction.md +20 -0
  82. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/uiux-judgment-extraction.md +6 -6
  83. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/validation-and-landing.md +4 -3
  84. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/check-ccl-skills.sh +69 -2
  85. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/extraction_review_gate.sh +22 -0
  86. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/impact-chain-gate.rb +49 -4
  87. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/obligation-ledger.py +2748 -0
  88. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/register-firing-path-resolution.rb +20 -5
  89. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/shared_git_surface_gate.py +1142 -0
  90. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_ccl_regressions.sh +17 -0
  91. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_ccl_skill_catalog.sh +41 -4
  92. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_ci_checkout_ref_binding.sh +120 -0
  93. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_entrypoint_domain_scan_terms.sh +82 -8
  94. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_extraction_review_gate.sh +336 -0
  95. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_impact_chain_self_adjudication.sh +82 -10
  96. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_obligation_ledger.sh +1416 -0
  97. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_obligation_ledger_repo_audit.sh +57 -0
  98. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_register_firing_path_wiring.sh +141 -4
  99. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_routing_pointer_integrity.sh +3 -1
  100. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_shared_git_surface_gate.sh +1696 -0
  101. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_uiux_delivery_contract.sh +2117 -0
  102. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_uiux_loading_budget.sh +316 -0
  103. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_validate_extraction_review_state.sh +1176 -0
  104. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_validate_skill_cross_refs.sh +31 -1
  105. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/validate-skill.sh +9 -4
  106. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/validate_extraction_review_state.py +980 -0
  107. package/dist/assets/marketplace/plugins/ccl-skills/skills/terminal-cli-dev/SKILL.md +8 -6
  108. package/dist/assets/marketplace/plugins/ccl-skills/skills/test-artifact-management/references/classical-test-design-techniques.md +1 -1
  109. package/dist/assets/marketplace/plugins/ccl-skills/skills/test-artifact-management/references/tc-review-and-prioritization.md +1 -1
  110. package/dist/assets/marketplace/plugins/ccl-skills/skills/test-artifact-management/references/update-lifecycle.md +2 -0
  111. package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/SKILL.md +16 -15
  112. package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/ci-fixtures-and-flake-control.md +5 -1
  113. package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/client-runtime-test-matrices.md +10 -2
  114. package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/e2e-real-flow-testing.md +2 -2
  115. package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/integration-contract-testing.md +10 -0
  116. package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/test-code-authoring-patterns.md +2 -2
  117. package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/test-topology-and-commands.md +1 -1
  118. package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/SKILL.md +2 -1
  119. package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/references/annotation-driven-revision.md +9 -0
  120. package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/references/figure-and-table-craft.md +8 -2
  121. package/dist/assets/marketplace/plugins/ccl-skills/skills/web-react-dev/SKILL.md +7 -5
  122. package/dist/assets/marketplace/plugins/ccl-skills/skills/web-react-dev/references/complex-workspace-patterns.md +1 -1
  123. package/dist/assets/marketplace/plugins/ccl-skills/skills/web-react-dev/references/react-architecture.md +3 -0
  124. package/dist/assets/marketplace/plugins/ccl-skills/skills/web-react-dev/references/web-quality-release.md +37 -4
  125. package/dist/assets/marketplace/plugins/ccl-skills/skills/web-react-dev/references/web-ui-quality.md +10 -1
  126. package/dist/assets/release.json +215 -105
  127. package/package.json +1 -1
@@ -1885,6 +1885,7 @@ PY
1885
1885
  # the skill tree. The runtime-surface classifier must be present there too.
1886
1886
  mkdir -p "$tmp_dir/harness/scripts"
1887
1887
  cp "$script_dir/claude_review.sh" "$tmp_dir/harness/scripts/"
1888
+ cp "$script_dir/normalize_review_timeout.sh" "$tmp_dir/harness/scripts/"
1888
1889
  cp "$script_dir/run_claude_capture.py" "$tmp_dir/harness/scripts/"
1889
1890
  cp "$script_dir/parse_review_json.py" "$tmp_dir/harness/scripts/"
1890
1891
  cp "$script_dir/parse_probe_result.py" "$tmp_dir/harness/scripts/"
@@ -1901,6 +1902,7 @@ PY
1901
1902
  # When the runtime classifier is absent, both review and challenge fail closed.
1902
1903
  mkdir -p "$tmp_dir/harness-no-runtime-parser/scripts"
1903
1904
  cp "$script_dir/claude_review.sh" "$tmp_dir/harness-no-runtime-parser/scripts/"
1905
+ cp "$script_dir/normalize_review_timeout.sh" "$tmp_dir/harness-no-runtime-parser/scripts/"
1904
1906
  cp "$script_dir/run_claude_capture.py" "$tmp_dir/harness-no-runtime-parser/scripts/"
1905
1907
  cp "$script_dir/parse_review_json.py" "$tmp_dir/harness-no-runtime-parser/scripts/"
1906
1908
  cp "$script_dir/classify_envelope.py" "$tmp_dir/harness-no-runtime-parser/scripts/"
@@ -1927,11 +1929,11 @@ done
1927
1929
 
1928
1930
  # Other local harness helpers are integrity inputs too; their absence must stop
1929
1931
  # instead of being laundered into an eligible provider fallback.
1930
- for missing_helper in run_claude_capture.py classify_envelope.py parse_review_json.py; do
1932
+ for missing_helper in normalize_review_timeout.sh run_claude_capture.py classify_envelope.py parse_review_json.py; do
1931
1933
  helper_slug="${missing_helper%.py}"
1932
1934
  helper_dir="$tmp_dir/harness-no-$helper_slug/scripts"
1933
1935
  mkdir -p "$helper_dir"
1934
- for helper in claude_review.sh run_claude_capture.py parse_review_json.py parse_probe_result.py classify_envelope.py; do
1936
+ for helper in claude_review.sh normalize_review_timeout.sh run_claude_capture.py parse_review_json.py parse_probe_result.py classify_envelope.py; do
1935
1937
  [ "$helper" = "$missing_helper" ] || cp "$script_dir/$helper" "$helper_dir/"
1936
1938
  done
1937
1939
  set +e
@@ -1951,7 +1953,10 @@ payload = json.load(open(sys.argv[2], encoding="utf-8"))
1951
1953
  assert payload["mode"] == "review", payload
1952
1954
  assert payload["status"] == "inconclusive", payload
1953
1955
  assert helper in payload["reason"], payload
1954
- assert payload["reason_code"] == "policy_denied", payload
1956
+ expected_reason_code = (
1957
+ "local_tool_failure" if helper == "normalize_review_timeout.sh" else "policy_denied"
1958
+ )
1959
+ assert payload["reason_code"] == expected_reason_code, payload
1955
1960
  assert payload["fallback_eligible"] is False, payload
1956
1961
  assert payload["next_action"] == "stop_reviewer_lane", payload
1957
1962
  PY
@@ -5,7 +5,10 @@ from __future__ import annotations
5
5
 
6
6
  import argparse
7
7
  import importlib.util
8
+ import json
9
+ import os
8
10
  from pathlib import Path
11
+ import subprocess
9
12
  import sys
10
13
  import tempfile
11
14
  import unittest
@@ -420,7 +423,8 @@ class ReviewClientCompatibilityTest(unittest.TestCase):
420
423
  def test_kimi_bounds_inline_argv_exposure_and_file_backs_large_packets(self) -> None:
421
424
  wrapper = (SCRIPT_DIR / "kimi_review.sh").read_text(encoding="utf-8")
422
425
 
423
- self.assertIn('[ "$TIMEOUT" -le 600 ] || TIMEOUT=600', wrapper)
426
+ self.assertIn('. "$SCRIPT_DIR/normalize_review_timeout.sh"', wrapper)
427
+ self.assertIn('TIMEOUT="$(normalize_review_timeout "$TIMEOUT")"', wrapper)
424
428
  self.assertIn("visible in process argv", wrapper)
425
429
  self.assertIn("MAX_INLINE_PROMPT_BYTES=16000", wrapper)
426
430
  self.assertIn('[ "$FORMAL_TIMEOUT" -le 120 ] || FORMAL_TIMEOUT=120', wrapper)
@@ -429,6 +433,77 @@ class ReviewClientCompatibilityTest(unittest.TestCase):
429
433
  self.assertIn('--agent-file "$AGENT_FILE"', wrapper)
430
434
  self.assertIn("mcp__code_review_packet__read_packet", wrapper)
431
435
 
436
+ def test_every_wrapper_guards_the_shared_timeout_normalizer(self) -> None:
437
+ for wrapper_name in (
438
+ "claude_review.sh",
439
+ "codex_review.sh",
440
+ "kimi_review.sh",
441
+ "opencode_review.sh",
442
+ ):
443
+ with self.subTest(wrapper=wrapper_name):
444
+ wrapper = (SCRIPT_DIR / wrapper_name).read_text(encoding="utf-8")
445
+ if wrapper_name == "claude_review.sh":
446
+ guard = '[ -f "$script_dir/normalize_review_timeout.sh" ]'
447
+ source = '. "$script_dir/normalize_review_timeout.sh"'
448
+ missing_contract = (
449
+ 'emit_inconclusive_payload "Claude review helper missing: '
450
+ 'normalize_review_timeout.sh" local_tool_failure false '
451
+ "stop_reviewer_lane"
452
+ )
453
+ missing_contracts = (missing_contract,)
454
+ else:
455
+ guard = '[ -f "$SCRIPT_DIR/normalize_review_timeout.sh" ]'
456
+ source = '. "$SCRIPT_DIR/normalize_review_timeout.sh"'
457
+ missing_contracts = (
458
+ "timeout_normalizer_missing",
459
+ "local_tool_failure false",
460
+ )
461
+ self.assertIn(guard, wrapper)
462
+ for missing_contract in missing_contracts:
463
+ self.assertIn(missing_contract, wrapper)
464
+ self.assertLess(wrapper.index(guard), wrapper.index(source))
465
+
466
+ def test_every_wrapper_rejects_below_minimum_timeout_at_runtime(self) -> None:
467
+ with tempfile.TemporaryDirectory() as temp_dir:
468
+ opencode = Path(temp_dir) / "opencode"
469
+ opencode.write_text("#!/bin/sh\nexit 99\n", encoding="utf-8")
470
+ opencode.chmod(0o755)
471
+ environment = {**os.environ, "PATH": f"{temp_dir}:{os.environ['PATH']}"}
472
+ for wrapper_name in (
473
+ "claude_review.sh",
474
+ "codex_review.sh",
475
+ "kimi_review.sh",
476
+ "opencode_review.sh",
477
+ ):
478
+ with self.subTest(wrapper=wrapper_name):
479
+ command = ["bash", str(SCRIPT_DIR / wrapper_name)]
480
+ if wrapper_name == "claude_review.sh":
481
+ command.append("review")
482
+ elif wrapper_name == "opencode_review.sh":
483
+ command.extend(("--implementer-family", "openai"))
484
+ command.extend(("--timeout", "4"))
485
+ completed = subprocess.run(
486
+ command,
487
+ check=False,
488
+ capture_output=True,
489
+ text=True,
490
+ env=environment,
491
+ )
492
+ self.assertEqual(completed.returncode, 2, completed.stderr)
493
+ payload = json.loads(completed.stdout)
494
+ self.assertEqual(payload["status"], "inconclusive")
495
+ self.assertEqual(payload["reason_code"], "invalid_input")
496
+ expected_reason = (
497
+ "--timeout must be an integer of at least 5 seconds"
498
+ if wrapper_name == "claude_review.sh"
499
+ else "invalid_timeout"
500
+ )
501
+ self.assertEqual(payload["reason"], expected_reason)
502
+ eligibility = payload.get(
503
+ "fallback_eligible", payload.get("cascade_eligible")
504
+ )
505
+ self.assertFalse(eligibility)
506
+
432
507
 
433
508
  if __name__ == "__main__":
434
509
  unittest.main()