@ccoalm/ccl-skills 0.15.5 → 0.17.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 (22) hide show
  1. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/SKILL.md +21 -19
  2. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/references/staged-review-contract.md +113 -123
  3. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/references/wording-only-review.md +136 -0
  4. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/codex_review.sh +99 -11
  5. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/review_gate.py +297 -100
  6. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_cli_review_wrappers.sh +162 -0
  7. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_review_client_compat.py +17 -1
  8. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_review_client_order.sh +30 -15
  9. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_review_gate.sh +445 -13
  10. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_update_review_plan_intent.sh +14 -7
  11. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/attention-budget-ratchet.md +1 -0
  12. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/firing-point-placement.md +22 -0
  13. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/source-register.md +25 -0
  14. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/contract-anchors.tsv +4 -0
  15. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/review_ledger_binding.py +2 -2
  16. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_extraction_review_gate.sh +56 -18
  17. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_register_firing_path_resolution.sh +41 -1
  18. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_review_ledger_binding.sh +68 -0
  19. package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/SKILL.md +3 -2
  20. package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/references/closeout-reread.md +40 -0
  21. package/dist/assets/release.json +31 -21
  22. package/package.json +1 -1
@@ -16,7 +16,7 @@ MAX_PROMPT_BYTES=245000
16
16
  CHALLENGE_CLASSES="race conditions, data loss, security holes, auth bypass, lost or duplicated work, operational footguns"
17
17
 
18
18
  emit_inconclusive() {
19
- python3 - "$MODE" "$1" "${2:-invalid_input}" "${3:-false}" "${4:-}" <<'PY'
19
+ python3 - "$MODE" "$1" "${2:-invalid_input}" "${3:-false}" "${4:-}" "${5:-}" "${6:-}" <<'PY'
20
20
  import json, sys
21
21
  payload = {
22
22
  "reviewer": "codex",
@@ -31,6 +31,10 @@ payload = {
31
31
  }
32
32
  if sys.argv[5]:
33
33
  payload["transport_exit_code"] = int(sys.argv[5]) if sys.argv[5].isdigit() else sys.argv[5]
34
+ if sys.argv[6]:
35
+ payload["transport_diagnostic"] = sys.argv[6]
36
+ if sys.argv[7]:
37
+ payload["transport_run_dir"] = sys.argv[7]
34
38
  print(json.dumps(payload, ensure_ascii=False, separators=(",", ":")))
35
39
  PY
36
40
  }
@@ -179,7 +183,15 @@ if [ "$REVIEW_SKILL_COUNT" -gt 0 ]; then
179
183
  || die_inconclusive codex_installed_skill_binding_invalid binding_mismatch false
180
184
  fi
181
185
  RUN_ROOT="$(mktemp -d "${TMPDIR:-/tmp}/codex-review.XXXXXX")"
182
- cleanup() { rm -rf "$RUN_ROOT"; }
186
+ # A failure that deletes its own evidence is the defect this round started from:
187
+ # rounds 122 and 123 left six receipts and no account of why the lane failed,
188
+ # because both captured streams went out with the run directory. On a transport
189
+ # failure the directory stays, and the receipt names it. It is mode 0700 under
190
+ # TMPDIR and holds exactly what it held while the run was in flight, so nothing
191
+ # is exposed that was not already; reclaiming it is the platform's temp-directory
192
+ # lifetime, as it is for every other run directory here.
193
+ PRESERVE_RUN_ROOT=0
194
+ cleanup() { [ "$PRESERVE_RUN_ROOT" = 1 ] || rm -rf "$RUN_ROOT"; }
183
195
  trap cleanup EXIT
184
196
  signal_inconclusive() {
185
197
  emit_inconclusive codex_review_terminated operator_interrupt false
@@ -515,26 +527,102 @@ if [ -n "$AUTH_LINK_TARGET" ]; then
515
527
  || die_inconclusive codex_runtime_home_credential_moved binding_mismatch false
516
528
  fi
517
529
  if [ "$run_rc" != 0 ]; then
530
+ # `codex exec --json` reports supply and credential failures as structured
531
+ # events on stdout, not on stderr, so a classifier reading only stderr sees a
532
+ # quota exhaustion as an unclassifiable failure and stops the reviewer lane
533
+ # instead of cascading.
534
+ #
535
+ # Only TOP-LEVEL error events are read. Model-authored content arrives nested
536
+ # under `item`, and the model quotes the packet, which is untrusted candidate
537
+ # data -- grepping the raw stream would let a reviewed diff pick the verdict
538
+ # for this lane by writing quota vocabulary into itself.
539
+ TRANSPORT_ERRORS="$RUN_ROOT/transport-errors.txt"
540
+ : >"$TRANSPORT_ERRORS"
541
+ python3 - "$EVENTS" >"$TRANSPORT_ERRORS" 2>/dev/null <<'PY_TRANSPORT_ERRORS'
542
+ import json, sys
543
+ from pathlib import Path
544
+
545
+ try:
546
+ lines = Path(sys.argv[1]).read_text(encoding="utf-8", errors="replace").splitlines()
547
+ except OSError:
548
+ sys.exit(0)
549
+ seen = set()
550
+ for line in lines:
551
+ try:
552
+ event = json.loads(line)
553
+ except ValueError:
554
+ continue
555
+ if not isinstance(event, dict):
556
+ continue
557
+ kind = event.get("type")
558
+ if not isinstance(kind, str) or not (kind == "error" or kind.endswith(".failed")):
559
+ continue
560
+ message = event.get("message")
561
+ if not isinstance(message, str):
562
+ nested = event.get("error")
563
+ message = nested.get("message") if isinstance(nested, dict) else None
564
+ if not isinstance(message, str) or not message:
565
+ continue
566
+ # A failing turn repeats the error event verbatim, and the diagnostic is
567
+ # bounded: relaying both would spend half the budget on one sentence.
568
+ message = " ".join(message.split())
569
+ if message not in seen:
570
+ seen.add(message)
571
+ print(message)
572
+ PY_TRANSPORT_ERRORS
573
+ PRESERVE_RUN_ROOT=1
574
+ # Physical paths on both sides, not the literal `$HOME` string: a home spelled
575
+ # with a trailing slash, or reached through a symlink, is the same directory
576
+ # and must elide the same way. Comparing the raw variable would put the
577
+ # username into a committed receipt on exactly those hosts.
578
+ TRANSPORT_RUN_DIR="$(cd "$RUN_ROOT" 2>/dev/null && pwd -P)" || TRANSPORT_RUN_DIR="$RUN_ROOT"
579
+ [ -n "$TRANSPORT_RUN_DIR" ] || TRANSPORT_RUN_DIR="$RUN_ROOT"
580
+ transport_home_real=""
581
+ if [ -n "${HOME:-}" ]; then
582
+ transport_home_real="$(cd "$HOME" 2>/dev/null && pwd -P)" || transport_home_real=""
583
+ fi
584
+ case "$transport_home_real" in
585
+ "" | */) transport_home_real="" ;;
586
+ esac
587
+ if [ -n "$transport_home_real" ]; then
588
+ case "$TRANSPORT_RUN_DIR" in
589
+ "$transport_home_real"/*)
590
+ TRANSPORT_RUN_DIR="~${TRANSPORT_RUN_DIR#"$transport_home_real"}" ;;
591
+ esac
592
+ fi
593
+ # The receipt carries NO text derived from the run. Eight review chains each
594
+ # found a different escape from a filter over that text -- an unlisted key
595
+ # name, an assignment form, URL userinfo, a password containing the separator,
596
+ # an escaped quote, an uppercase scheme -- because "nothing secret-shaped
597
+ # survives" is not a decidable property of free text, and an adversarial
598
+ # reviewer can always spell one more. So the free text is gone: what the
599
+ # transport said stays in the preserved run directory, and the receipt says
600
+ # where that is. The classifier still reads the extracted error messages
601
+ # above; those are matched against fixed patterns and never persisted.
602
+ TRANSPORT_DIAGNOSTIC="the transport output for this failure is in transport_run_dir"
603
+
518
604
  if bash "$TIMEOUT_CLASSIFIER" "$run_rc" "$run_elapsed" "$TIMEOUT"; then
519
- die_inconclusive codex_timeout timeout true "$run_rc"
605
+ die_inconclusive codex_timeout timeout true "$run_rc" "$TRANSPORT_DIAGNOSTIC" "$TRANSPORT_RUN_DIR"
520
606
  fi
521
607
  case "$run_rc" in
522
- 129|130|137|143) die_inconclusive codex_process_interrupted operator_interrupt false "$run_rc" ;;
608
+ 129|130|137|143) die_inconclusive codex_process_interrupted operator_interrupt false "$run_rc" "$TRANSPORT_DIAGNOSTIC" "$TRANSPORT_RUN_DIR" ;;
523
609
  esac
524
- if grep -qiE '429|rate.?limit|quota' "$STDERR_FILE"; then
525
- die_inconclusive codex_quota quota true "$run_rc"
610
+ # `usage limit` is the wording the CLI actually uses for an exhausted account;
611
+ # none of the older patterns match it.
612
+ if grep -qiE '429|rate.?limit|quota|usage limit' "$STDERR_FILE" "$TRANSPORT_ERRORS"; then
613
+ die_inconclusive codex_quota quota true "$run_rc" "$TRANSPORT_DIAGNOSTIC" "$TRANSPORT_RUN_DIR"
526
614
  fi
527
- if grep -qiE 'unauthori[sz]ed|authentication|login|api key' "$STDERR_FILE"; then
528
- die_inconclusive codex_auth_unavailable provider_unavailable true "$run_rc"
615
+ if grep -qiE 'unauthori[sz]ed|authentication|login|api key' "$STDERR_FILE" "$TRANSPORT_ERRORS"; then
616
+ die_inconclusive codex_auth_unavailable provider_unavailable true "$run_rc" "$TRANSPORT_DIAGNOSTIC" "$TRANSPORT_RUN_DIR"
529
617
  fi
530
618
  if [ ! -s "$EVENTS" ] && [ ! -s "$RESULT_FILE" ] \
531
619
  && grep -qiE 'failed to initialize in-process app-server client: Operation not permitted' "$STDERR_FILE"; then
532
620
  if [ "$HOST_REMEDIATION_ATTEMPTED" -eq 1 ]; then
533
- die_inconclusive codex_host_path_unavailable_after_host_retry host_path_unavailable_after_host_retry true "$run_rc"
621
+ die_inconclusive codex_host_path_unavailable_after_host_retry host_path_unavailable_after_host_retry true "$run_rc" "$TRANSPORT_DIAGNOSTIC" "$TRANSPORT_RUN_DIR"
534
622
  fi
535
- die_inconclusive codex_host_path_unavailable host_path_unavailable false "$run_rc"
623
+ die_inconclusive codex_host_path_unavailable host_path_unavailable false "$run_rc" "$TRANSPORT_DIAGNOSTIC" "$TRANSPORT_RUN_DIR"
536
624
  fi
537
- die_inconclusive codex_run_failed unknown_client_failure false "$run_rc"
625
+ die_inconclusive codex_run_failed unknown_client_failure false "$run_rc" "$TRANSPORT_DIAGNOSTIC" "$TRANSPORT_RUN_DIR"
538
626
  fi
539
627
 
540
628
  python3 "$PARSER" --client codex --mode "$MODE" --implementer-family "$IMPL_FAMILY" \