@ccoalm/ccl-skills 0.13.0 → 0.14.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 (24) hide show
  1. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/SKILL.md +14 -41
  2. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/attention-budget-ratchet.md +11 -0
  3. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/correction-routing-map.md +22 -0
  4. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/coverage-exhaustion-traps.md +7 -0
  5. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/description-authoring.md +26 -0
  6. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/dual-track-review-gate.md +2 -2
  7. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/eval-routing.md +2 -0
  8. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/external-practice-controls.md +6 -0
  9. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/extraction-quickstart.md +4 -2
  10. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/harness-patterns-and-eval.md +8 -0
  11. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/incident-postmortem-extraction.md +8 -0
  12. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/rule-consolidation.md +1 -0
  13. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/source-register.md +34 -0
  14. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/uiux-judgment-extraction.md +11 -0
  15. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/validation-and-landing.md +11 -0
  16. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/entrypoint_form_census.py +169 -0
  17. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/reference-access-census.sh +157 -0
  18. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/review_ledger_binding.py +454 -103
  19. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_ccl_regressions.sh +8 -0
  20. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_entrypoint_form_census.sh +174 -0
  21. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_reference_access_census.sh +209 -0
  22. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_review_ledger_binding.sh +331 -0
  23. package/dist/assets/release.json +45 -20
  24. package/package.json +1 -1
@@ -492,6 +492,337 @@ out="$(run_part --base "$PART_BASE")"; rc=$?
492
492
  check "the passing partition state still passes after the probes" \
493
493
  '[ "$rc" = 0 ]'
494
494
 
495
+ # Chain: an integration branch accumulates several reviewed rounds, each merged
496
+ # with its own ledger bound at its own base, and is then promoted as one pull
497
+ # request. No single ledger binds the promotion candidate, and a path partition
498
+ # cannot either when two rounds append to the same file: that file's promotion
499
+ # diff is the sum of both appends and no round ever froze that sum. Every byte
500
+ # of the promotion reached the branch through a first-parent merge whose second
501
+ # parent is a reviewed head, so the gate walks that chain and rebinds each round
502
+ # in a detached checkout at the round's own base, requiring every merge to be
503
+ # exactly the automatic merge of its parents.
504
+ CHAIN="$WORK/chain-repo"
505
+ mkdir -p "$CHAIN/skills/code-review/scripts" "$CHAIN/skills/skill-extraction-workflow/scripts" "$CHAIN/specs"
506
+ cp "$CONTROLLER" "$CHAIN/skills/code-review/scripts/review_gate.py"
507
+ # This stub has a rule, unlike the accept-all stubs above, so a round can forge a
508
+ # ledger the real validator would reject and the suite can tell whose validator
509
+ # judged it.
510
+ STRICT_VALIDATOR='import json, sys
511
+ payload = json.load(open(sys.argv[1], encoding="utf-8"))
512
+ if payload.get("closeout_state") == "ready_for_human_decision":
513
+ print("extraction_review_state_ok: stub accepted")
514
+ sys.exit(0)
515
+ print("extraction_review_state_invalid: stub rejected")
516
+ sys.exit(1)
517
+ '
518
+ printf '%s' "$STRICT_VALIDATOR" >"$CHAIN/skills/skill-extraction-workflow/scripts/validate_extraction_review_state.py"
519
+ git -C "$CHAIN" init -q -b main .
520
+ git -C "$CHAIN" config user.email t@example.invalid
521
+ git -C "$CHAIN" config user.name tester
522
+ printf 'baseline\n' >"$CHAIN/skills/skill-extraction-workflow/SKILL.md"
523
+ printf '| row | owner |\n' >"$CHAIN/skills/skill-extraction-workflow/register.md"
524
+ printf 'baseline\n' >"$CHAIN/README.md"
525
+ git -C "$CHAIN" add -A && git -C "$CHAIN" commit -qm baseline
526
+ CHAIN_BASE="$(git -C "$CHAIN" rev-parse HEAD)"
527
+ git -C "$CHAIN" checkout -q -b dev
528
+
529
+ run_chain() { python3 "$GATE" --repo-root "$CHAIN" "$@" 2>&1; }
530
+
531
+ # Land one reviewed round on the integration branch: branch, edit, ledger bound
532
+ # to the round's own candidate (its base is the integration tip it forked from),
533
+ # then a non-fast-forward merge so the round is one first-parent step.
534
+ land_round() {
535
+ local name="$1" ledger="$2"; shift 2
536
+ git -C "$CHAIN" checkout -q -b "round-$name" dev
537
+ "$@"
538
+ git -C "$CHAIN" add -A && git -C "$CHAIN" commit -qm "round $name"
539
+ if [ "$ledger" = with-ledger ]; then
540
+ local digest
541
+ digest="$(run_chain --base dev --print-candidate)"
542
+ mkdir -p "$CHAIN/specs/$name/evidence"
543
+ write_closeout "$CHAIN/specs/$name/evidence/closeout.json" "$digest"
544
+ git -C "$CHAIN" add -A && git -C "$CHAIN" commit -qm "round $name ledger"
545
+ fi
546
+ git -C "$CHAIN" checkout -q dev
547
+ git -C "$CHAIN" merge -q --no-ff -m "merge round $name" "round-$name"
548
+ }
549
+ edit_round_a() {
550
+ printf 'baseline\nround a\n' >"$CHAIN/skills/skill-extraction-workflow/SKILL.md"
551
+ printf '| round a | owner |\n' >>"$CHAIN/skills/skill-extraction-workflow/register.md"
552
+ }
553
+ edit_round_b() {
554
+ mkdir -p "$CHAIN/lane"
555
+ printf 'round b\n' >"$CHAIN/lane/file.txt"
556
+ printf '| round b | owner |\n' >>"$CHAIN/skills/skill-extraction-workflow/register.md"
557
+ }
558
+ land_round a with-ledger edit_round_a
559
+ land_round b with-ledger edit_round_b
560
+ CHAIN_TWO="$(git -C "$CHAIN" rev-parse HEAD)"
561
+
562
+ worktrees_before="$(git -C "$CHAIN" worktree list --porcelain)"
563
+ tree_before="$(git -C "$CHAIN" status --porcelain --ignored)"
564
+ out="$(run_chain --base "$CHAIN_BASE")"; rc=$?
565
+ check "two rounds appending to one file bind through the first-parent chain where no single ledger or path partition can" \
566
+ '[ "$rc" = 0 ] && case "$out" in *"first-parent chain"*"2 rounds"*"specs/b/evidence/closeout.json"*"specs/a/evidence/closeout.json"*) true;; *) false;; esac'
567
+ check "walking the chain leaves no detached checkout registered and the bound tree byte-identical" \
568
+ '[ "$(git -C "$CHAIN" worktree list --porcelain)" = "$worktrees_before" ] && [ "$(git -C "$CHAIN" status --porcelain --ignored)" = "$tree_before" ]'
569
+
570
+ out="$(run_chain --base "$CHAIN_BASE" --paths skills)"; rc=$?
571
+ check "a narrowed --paths scope does not evaluate the chain, because each round's ledger binds the whole round" \
572
+ '[ "$rc" = 1 ] && case "$out" in *"default path set"*) true;; *) false;; esac'
573
+
574
+ # The promotion pull request is brought up to date with its target: the target
575
+ # advanced, and the sync merge's second parent is already on the base. That step
576
+ # owes no evidence, but it must still be exactly the automatic merge.
577
+ git -C "$CHAIN" checkout -q main
578
+ printf 'baseline\nfixed on the target\n' >"$CHAIN/README.md"
579
+ git -C "$CHAIN" add -A && git -C "$CHAIN" commit -qm "target advances"
580
+ CHAIN_MAIN="$(git -C "$CHAIN" rev-parse HEAD)"
581
+ git -C "$CHAIN" checkout -q dev
582
+ git -C "$CHAIN" merge -q --no-ff -m "sync target into dev" main
583
+ out="$(run_chain --base "$CHAIN_MAIN")"; rc=$?
584
+ check "a sync merge of the advanced target on top of the chain owes no evidence and still binds" \
585
+ '[ "$rc" = 0 ] && case "$out" in *"first-parent chain"*"2 rounds"*"sync"*) true;; *) false;; esac'
586
+ CHAIN_GOOD="$(git -C "$CHAIN" rev-parse HEAD)"
587
+
588
+ # A round the integration branch advanced past before it merged: its fork point
589
+ # is not the merge's first parent, the merge is still the automatic one, and the
590
+ # round's ledger was bound at its own fork point.
591
+ git -C "$CHAIN" checkout -q -b round-late dev
592
+ printf 'round late\n' >"$CHAIN/lane/late.txt"
593
+ git -C "$CHAIN" add -A && git -C "$CHAIN" commit -qm "round late"
594
+ LATE_DIGEST="$(run_chain --base dev --print-candidate)"
595
+ mkdir -p "$CHAIN/specs/late/evidence"
596
+ write_closeout "$CHAIN/specs/late/evidence/closeout.json" "$LATE_DIGEST"
597
+ git -C "$CHAIN" add -A && git -C "$CHAIN" commit -qm "round late ledger"
598
+ git -C "$CHAIN" checkout -q dev
599
+ edit_round_c() { printf 'round c\n' >"$CHAIN/lane/c.txt"; }
600
+ land_round c with-ledger edit_round_c
601
+ git -C "$CHAIN" merge -q --no-ff -m "merge round late" round-late
602
+ out="$(run_chain --base "$CHAIN_MAIN")"; rc=$?
603
+ check "a round merged after the integration branch advanced still binds at its own fork point" \
604
+ '[ "$rc" = 0 ] && case "$out" in *"first-parent chain"*"4 rounds"*) true;; *) false;; esac'
605
+ CHAIN_ADVANCED="$(git -C "$CHAIN" rev-parse HEAD)"
606
+
607
+ # Every way a chain step can fail to be a reviewed round is refused for its own
608
+ # reason. Each probe branches from the passing state so the cases stay independent.
609
+ probe_chain() { git -C "$CHAIN" checkout -q -B dev "$CHAIN_GOOD"; }
610
+
611
+ probe_chain
612
+ edit_round_d() { printf 'round d\n' >"$CHAIN/lane/d.txt"; }
613
+ land_round d no-ledger edit_round_d
614
+ UNBOUND_MERGE="$(git -C "$CHAIN" rev-parse --short=12 HEAD)"
615
+ out="$(run_chain --base "$CHAIN_MAIN")"; rc=$?
616
+ check "a round with no accepted ledger at its own base refuses the whole chain, naming that round" \
617
+ '[ "$rc" = 1 ] && case "$out" in *"round $UNBOUND_MERGE"*"does not bind at its own base"*) true;; *) false;; esac'
618
+
619
+ probe_chain
620
+ printf 'pushed straight to the integration branch\n' >"$CHAIN/lane/direct.txt"
621
+ git -C "$CHAIN" add -A && git -C "$CHAIN" commit -qm "direct commit on dev"
622
+ DIRECT="$(git -C "$CHAIN" rev-parse --short=12 HEAD)"
623
+ out="$(run_chain --base "$CHAIN_MAIN")"; rc=$?
624
+ check "a non-merge commit on the integration branch is refused: nothing reviewed binds its content" \
625
+ '[ "$rc" = 1 ] && case "$out" in *"$DIRECT is not a merge commit"*) true;; *) false;; esac'
626
+
627
+ probe_chain
628
+ git -C "$CHAIN" checkout -q -b round-evil dev
629
+ printf 'round evil\n' >"$CHAIN/lane/evil.txt"
630
+ git -C "$CHAIN" add -A && git -C "$CHAIN" commit -qm "round evil"
631
+ EVIL_DIGEST="$(run_chain --base dev --print-candidate)"
632
+ mkdir -p "$CHAIN/specs/evil/evidence"
633
+ write_closeout "$CHAIN/specs/evil/evidence/closeout.json" "$EVIL_DIGEST"
634
+ git -C "$CHAIN" add -A && git -C "$CHAIN" commit -qm "round evil ledger"
635
+ git -C "$CHAIN" checkout -q dev
636
+ git -C "$CHAIN" merge -q --no-ff --no-commit round-evil
637
+ printf 'slipped into the merge commit itself\n' >"$CHAIN/lane/smuggled.txt"
638
+ git -C "$CHAIN" add -A && git -C "$CHAIN" commit -qm "merge round evil (with extra content)"
639
+ EVIL_MERGE="$(git -C "$CHAIN" rev-parse --short=12 HEAD)"
640
+ out="$(run_chain --base "$CHAIN_MAIN")"; rc=$?
641
+ check "a merge whose tree is not the automatic merge of its parents is refused, naming the merge" \
642
+ '[ "$rc" = 1 ] && case "$out" in *"$EVIL_MERGE"*"automatic merge"*) true;; *) false;; esac'
643
+
644
+ probe_chain
645
+ git -C "$CHAIN" checkout -q -b round-conflict "$CHAIN_TWO"
646
+ printf 'baseline\nconflicting fix\n' >"$CHAIN/README.md"
647
+ git -C "$CHAIN" add -A && git -C "$CHAIN" commit -qm "round conflict"
648
+ CONFLICT_DIGEST="$(run_chain --base "$CHAIN_TWO" --print-candidate)"
649
+ mkdir -p "$CHAIN/specs/conflict/evidence"
650
+ write_closeout "$CHAIN/specs/conflict/evidence/closeout.json" "$CONFLICT_DIGEST"
651
+ git -C "$CHAIN" add -A && git -C "$CHAIN" commit -qm "round conflict ledger"
652
+ git -C "$CHAIN" checkout -q dev
653
+ git -C "$CHAIN" merge -q --no-ff --no-commit round-conflict >/dev/null 2>&1 || true
654
+ printf 'baseline\nresolved by hand\n' >"$CHAIN/README.md"
655
+ git -C "$CHAIN" add -A && git -C "$CHAIN" commit -qm "merge round conflict (resolved by hand)"
656
+ CONFLICT_MERGE="$(git -C "$CHAIN" rev-parse --short=12 HEAD)"
657
+ out="$(run_chain --base "$CHAIN_MAIN")"; rc=$?
658
+ check "a merge that needed hand resolution is refused: the resolution is content no round reviewed" \
659
+ '[ "$rc" = 1 ] && case "$out" in *"$CONFLICT_MERGE"*"automatic merge"*) true;; *) false;; esac'
660
+
661
+ probe_chain
662
+ git -C "$CHAIN" checkout -q -b round-stale dev
663
+ printf 'round stale\n' >"$CHAIN/lane/stale.txt"
664
+ git -C "$CHAIN" add -A && git -C "$CHAIN" commit -qm "round stale"
665
+ STALE_DIGEST="$(run_chain --base dev --print-candidate)"
666
+ mkdir -p "$CHAIN/specs/stale/evidence"
667
+ write_closeout "$CHAIN/specs/stale/evidence/closeout.json" "$STALE_DIGEST"
668
+ git -C "$CHAIN" add -A && git -C "$CHAIN" commit -qm "round stale ledger"
669
+ printf 'edited after the review\n' >>"$CHAIN/lane/stale.txt"
670
+ git -C "$CHAIN" add -A && git -C "$CHAIN" commit -qm "round stale moves after its ledger"
671
+ git -C "$CHAIN" checkout -q dev
672
+ git -C "$CHAIN" merge -q --no-ff -m "merge round stale" round-stale
673
+ STALE_MERGE="$(git -C "$CHAIN" rev-parse --short=12 HEAD)"
674
+ out="$(run_chain --base "$CHAIN_MAIN")"; rc=$?
675
+ check "a round whose ledger binds a candidate it later moved away from is refused" \
676
+ '[ "$rc" = 1 ] && case "$out" in *"round $STALE_MERGE"*"does not bind at its own base"*) true;; *) false;; esac'
677
+
678
+ # A round is judged with the landing tree's controller and validator, never its
679
+ # own: a round that installs an accept-all validator in its own branch, forges a
680
+ # ledger the real validator rejects, and is later followed by a round restoring
681
+ # the real validator must not bind through history's tools.
682
+ probe_chain
683
+ git -C "$CHAIN" checkout -q -b round-forged dev
684
+ printf 'round forged\n' >"$CHAIN/lane/forged.txt"
685
+ printf 'import sys\nprint("extraction_review_state_ok: hollow validator accepts everything")\nsys.exit(0)\n' \
686
+ >"$CHAIN/skills/skill-extraction-workflow/scripts/validate_extraction_review_state.py"
687
+ git -C "$CHAIN" add -A && git -C "$CHAIN" commit -qm "round forged"
688
+ FORGED_DIGEST="$(run_chain --base dev --print-candidate)"
689
+ mkdir -p "$CHAIN/specs/forged/evidence"
690
+ python3 - "$CHAIN/specs/forged/evidence/closeout.json" "$FORGED_DIGEST" <<'PY'
691
+ import json, sys
692
+ from pathlib import Path
693
+ Path(sys.argv[1]).write_text(json.dumps({"schema_version": 3, "closeout_state": "forged", "controller_receipts": [], "candidate_sha256": sys.argv[2]}))
694
+ PY
695
+ git -C "$CHAIN" add -A && git -C "$CHAIN" commit -qm "round forged ledger"
696
+ git -C "$CHAIN" checkout -q dev
697
+ git -C "$CHAIN" merge -q --no-ff -m "merge round forged" round-forged
698
+ FORGED_MERGE="$(git -C "$CHAIN" rev-parse --short=12 HEAD)"
699
+ edit_round_restore() { printf '%s' "$STRICT_VALIDATOR" >"$CHAIN/skills/skill-extraction-workflow/scripts/validate_extraction_review_state.py"; }
700
+ land_round restore with-ledger edit_round_restore
701
+ out="$(run_chain --base "$CHAIN_MAIN")"; rc=$?
702
+ check "a round that forged a ledger under its own hollow validator is refused even after a later round restored the real one" \
703
+ '[ "$rc" = 1 ] && case "$out" in *"round $FORGED_MERGE"*"does not bind at its own base"*) true;; *) false;; esac'
704
+
705
+ # The walk is bounded at exactly 64 steps: a chain of 64 passes, 65 is refused.
706
+ # Receipt-only rounds keep the fixture fast, since a round whose only change is
707
+ # an excluded receipt binds as "no reviewed-path change" without a freeze.
708
+ probe_chain
709
+ fill_round() {
710
+ git -C "$CHAIN" checkout -q -b "round-fill-$1" dev
711
+ mkdir -p "$CHAIN/specs/fill-$1/evidence"
712
+ printf '{"schema_version": 3, "candidate_sha256": "%s"}\n' "$(printf '0%.0s' $(seq 64))" >"$CHAIN/specs/fill-$1/evidence/note.json"
713
+ git -C "$CHAIN" add -A && git -C "$CHAIN" commit -qm "fill $1"
714
+ git -C "$CHAIN" checkout -q dev
715
+ git -C "$CHAIN" merge -q --no-ff -m "merge fill $1" "round-fill-$1"
716
+ }
717
+ for index in $(seq 1 61); do fill_round "$index"; done
718
+ out="$(run_chain --base "$CHAIN_MAIN")"; rc=$?
719
+ check "a chain of exactly 64 steps is still walked and binds" \
720
+ '[ "$rc" = 0 ] && case "$out" in *"first-parent chain"*"63 rounds"*) true;; *) false;; esac'
721
+ fill_round 62
722
+ out="$(run_chain --base "$CHAIN_MAIN")"; rc=$?
723
+ check "a chain of 65 steps is refused as longer than the bound" \
724
+ '[ "$rc" = 1 ] && case "$out" in *"more than 64 steps"*) true;; *) false;; esac'
725
+
726
+ # A checkout this run cannot release is an error, never a pass: the removal's
727
+ # result is checked and the registry read back, and nothing prunes registrations
728
+ # the run did not create. A git shim refuses only `worktree remove`.
729
+ git -C "$CHAIN" checkout -q -B dev "$CHAIN_GOOD"
730
+ REAL_GIT="$(command -v git)"
731
+ mkdir -p "$WORK/fakegit" "$WORK/shim-tmp"
732
+ cat >"$WORK/fakegit/git" <<EOF
733
+ #!/usr/bin/env bash
734
+ if [ "\$1" = "-C" ] && [ "\$3" = "worktree" ] && [ "\$4" = "remove" ]; then
735
+ echo "shim: refusing to remove the worktree" >&2
736
+ exit 1
737
+ fi
738
+ exec "$REAL_GIT" "\$@"
739
+ EOF
740
+ chmod +x "$WORK/fakegit/git"
741
+ out="$(PATH="$WORK/fakegit:$PATH" TMPDIR="$WORK/shim-tmp" run_chain --base "$CHAIN_MAIN")"; rc=$?
742
+ check "a detached checkout that cannot be released turns the verdict into an error, never a pass" \
743
+ '[ "$rc" != 0 ] && case "$out" in *"cannot release the detached checkout"*) case "$out" in *review_ledger_binding_ok*) false;; *) true;; esac;; *) false;; esac'
744
+ git -C "$CHAIN" worktree prune
745
+
746
+ # `git worktree add` can register and populate the checkout and still return
747
+ # nonzero. The failure is an error either way, but the registration it left
748
+ # behind must be released and verified, not merely have its directory deleted.
749
+ mkdir -p "$WORK/fakegit-add" "$WORK/shim-add-tmp"
750
+ cat >"$WORK/fakegit-add/git" <<EOF
751
+ #!/usr/bin/env bash
752
+ if [ "\$1" = "-C" ] && [ "\$3" = "worktree" ] && [ "\$4" = "add" ]; then
753
+ "$REAL_GIT" "\$@"
754
+ echo "shim: worktree add failed after registering" >&2
755
+ exit 1
756
+ fi
757
+ exec "$REAL_GIT" "\$@"
758
+ EOF
759
+ chmod +x "$WORK/fakegit-add/git"
760
+ worktrees_before="$(git -C "$CHAIN" worktree list --porcelain)"
761
+ out="$(PATH="$WORK/fakegit-add:$PATH" TMPDIR="$WORK/shim-add-tmp" run_chain --base "$CHAIN_MAIN")"; rc=$?
762
+ check "a checkout creation that fails after registering is an error and leaves no registration or directory behind" \
763
+ '[ "$rc" != 0 ] && case "$out" in *"cannot check out round head"*) case "$out" in *review_ledger_binding_ok*) false;; *) true;; esac;; *) false;; esac && [ "$(git -C "$CHAIN" worktree list --porcelain)" = "$worktrees_before" ] && [ -z "$(ls -A "$WORK/shim-add-tmp")" ]'
764
+ git -C "$CHAIN" worktree prune
765
+
766
+ # The benign sibling: an add that fails before registering anything must error
767
+ # the same way, leave the registry untouched, and remove the directory this run
768
+ # created for it, without reporting a release problem it does not have.
769
+ mkdir -p "$WORK/fakegit-noadd" "$WORK/shim-noadd-tmp"
770
+ cat >"$WORK/fakegit-noadd/git" <<EOF
771
+ #!/usr/bin/env bash
772
+ if [ "\$1" = "-C" ] && [ "\$3" = "worktree" ] && [ "\$4" = "add" ]; then
773
+ echo "shim: worktree add refused before registering" >&2
774
+ exit 1
775
+ fi
776
+ exec "$REAL_GIT" "\$@"
777
+ EOF
778
+ chmod +x "$WORK/fakegit-noadd/git"
779
+ worktrees_before="$(git -C "$CHAIN" worktree list --porcelain)"
780
+ out="$(PATH="$WORK/fakegit-noadd:$PATH" TMPDIR="$WORK/shim-noadd-tmp" run_chain --base "$CHAIN_MAIN")"; rc=$?
781
+ check "a checkout creation that fails before registering errors cleanly with no registration, no directory, and no release complaint" \
782
+ '[ "$rc" != 0 ] && case "$out" in *"cannot check out round head"*) case "$out" in *"could not be released"*|*review_ledger_binding_ok*) false;; *) true;; esac;; *) false;; esac && [ "$(git -C "$CHAIN" worktree list --porcelain)" = "$worktrees_before" ] && [ -z "$(ls -A "$WORK/shim-noadd-tmp")" ]'
783
+
784
+ # The registry is read NUL-terminated: line-oriented porcelain cannot carry a
785
+ # path with a newline (the line splits; a tab is printed raw on the git in use,
786
+ # and quoting depends on version and core.quotePath), so a registration under
787
+ # such a temporary directory would match neither spelling and read as gone.
788
+ # Here the add registers and fails, the remove is refused, and the surviving
789
+ # registration must be reported.
790
+ TAB_TMP="$WORK/shim nl
791
+ dir"
792
+ mkdir -p "$WORK/fakegit-tab" "$TAB_TMP"
793
+ cat >"$WORK/fakegit-tab/git" <<EOF
794
+ #!/usr/bin/env bash
795
+ if [ "\$1" = "-C" ] && [ "\$3" = "worktree" ] && [ "\$4" = "add" ]; then
796
+ "$REAL_GIT" "\$@"
797
+ echo "shim: worktree add failed after registering" >&2
798
+ exit 1
799
+ fi
800
+ if [ "\$1" = "-C" ] && [ "\$3" = "worktree" ] && [ "\$4" = "remove" ]; then
801
+ echo "shim: refusing to remove the worktree" >&2
802
+ exit 1
803
+ fi
804
+ exec "$REAL_GIT" "\$@"
805
+ EOF
806
+ chmod +x "$WORK/fakegit-tab/git"
807
+ worktrees_before="$(git -C "$CHAIN" worktree list --porcelain)"
808
+ out="$(PATH="$WORK/fakegit-tab:$PATH" TMPDIR="$TAB_TMP" run_chain --base "$CHAIN_MAIN")"; rc=$?
809
+ check "a surviving registration under a newline-bearing temporary path is still reported, not read as gone through line-oriented porcelain" \
810
+ '[ "$rc" != 0 ] && case "$out" in *"cannot check out round head"*"could not be released"*"still registered"*) true;; *) false;; esac'
811
+ rm -rf "$TAB_TMP"
812
+ git -C "$CHAIN" worktree prune
813
+ # This case deliberately leaves a registration behind, so its own cleanup is
814
+ # what restores the fixture. Prune only drops registrations whose directory is
815
+ # already gone, so the directory must go first; asserting the restoration keeps
816
+ # a later reordering from silently handing every following case a mutated
817
+ # registry.
818
+ check "the newline-path case restores the fixture's worktree registry for the cases that follow" \
819
+ '[ "$(git -C "$CHAIN" worktree list --porcelain)" = "$worktrees_before" ]'
820
+
821
+ git -C "$CHAIN" checkout -q -B dev "$CHAIN_ADVANCED"
822
+ out="$(run_chain --base "$CHAIN_MAIN")"; rc=$?
823
+ check "the passing chain state still passes after the probes" \
824
+ '[ "$rc" = 0 ]'
825
+
495
826
  # The suite above exercises a synthetic repository. The gate must also run against
496
827
  # the real checkout it ships in, or a break in that path passes every test here.
497
828
  REAL_ROOT="$(cd "$DIR/../../.." && pwd -P)"
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schema": 1,
3
3
  "npmPackage": "@ccoalm/ccl-skills",
4
- "version": "0.13.0",
5
- "sourceCommit": "17dc842da2e26c10bdd0459da27264048f4144b3",
4
+ "version": "0.14.0",
5
+ "sourceCommit": "3b42a5bd027e29f72b90b055c763333964d46259",
6
6
  "sourceState": "clean",
7
7
  "files": [
8
8
  {
@@ -1992,7 +1992,7 @@
1992
1992
  },
1993
1993
  {
1994
1994
  "path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/attention-budget-ratchet.md",
1995
- "sha256": "3f6fa158cf3e09df7ce59c98b407ef10187711635db720199ad0c0b3585f4a44",
1995
+ "sha256": "b09b1b6908e87b75ecdb2cba5c2499b4a9bd490f7c7225b509a560285a61cb9d",
1996
1996
  "mode": 420
1997
1997
  },
1998
1998
  {
@@ -2005,24 +2005,29 @@
2005
2005
  "sha256": "a7ff4aea676dcf3abc62316a2ddb10c88b035d2f6a7b97d5a0343d8533aeb33c",
2006
2006
  "mode": 420
2007
2007
  },
2008
+ {
2009
+ "path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/correction-routing-map.md",
2010
+ "sha256": "6712b1a91e3a019795e1fbf58fbe52042a31962674159f868671117003f46a12",
2011
+ "mode": 420
2012
+ },
2008
2013
  {
2009
2014
  "path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/coverage-exhaustion-traps.md",
2010
- "sha256": "9d920528936da253c513f3056b4780354d5c73290986cad11437f3abf14472ae",
2015
+ "sha256": "0070f58a0df463fe491d760b2378fae85d7fea956fc01ac4a4b0aae05a25b4b5",
2011
2016
  "mode": 420
2012
2017
  },
2013
2018
  {
2014
2019
  "path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/description-authoring.md",
2015
- "sha256": "a78c1b37bb648da6024e16c1d4435bd9413d403a4171673f270fd86440b70732",
2020
+ "sha256": "6d5ebb079c9f3570985c12a30995a09174ee2efef066a9da7efe89b56c0f0166",
2016
2021
  "mode": 420
2017
2022
  },
2018
2023
  {
2019
2024
  "path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/dual-track-review-gate.md",
2020
- "sha256": "50f907bd644401adbcdf55f259430eb62c39e656e27c14c1f367654c3da1b630",
2025
+ "sha256": "9deda45197efe202db5b3ed1d603aa1e97090476558a254b4612c7c6ab7c95ee",
2021
2026
  "mode": 420
2022
2027
  },
2023
2028
  {
2024
2029
  "path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/eval-routing.md",
2025
- "sha256": "9251d2da1a4ff80c70a5857b44eb5b825d94d2a7a224fb763d263712f029b309",
2030
+ "sha256": "867941f4dcb59c19b36310f8f304bf883e77a5c58c9e9d5cf82e879720dff0de",
2026
2031
  "mode": 420
2027
2032
  },
2028
2033
  {
@@ -2037,7 +2042,7 @@
2037
2042
  },
2038
2043
  {
2039
2044
  "path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/external-practice-controls.md",
2040
- "sha256": "a956c52fdf268c2f75edcc7de66f882be222fdd5bad07b68c1242ad05d79637d",
2045
+ "sha256": "665eaecb1f9ef219f581fa86a02df4bb378694dbc4ff52b5117f7c929bdec287",
2041
2046
  "mode": 420
2042
2047
  },
2043
2048
  {
@@ -2047,7 +2052,7 @@
2047
2052
  },
2048
2053
  {
2049
2054
  "path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/extraction-quickstart.md",
2050
- "sha256": "68b6327538ad1bb99fe9c0dd337bd961f029ddf9929c1ecd7c60c616f59d84de",
2055
+ "sha256": "7ed3fa06032d45fa6d0ab03679cf64e571a80cdf470f34476d77ab54db0869a4",
2051
2056
  "mode": 420
2052
2057
  },
2053
2058
  {
@@ -2057,12 +2062,12 @@
2057
2062
  },
2058
2063
  {
2059
2064
  "path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/harness-patterns-and-eval.md",
2060
- "sha256": "0dd0a49299a54a90b4726cc8223ee2fc0ab145cf9b16f4ae6ddc61d3b58c0c8c",
2065
+ "sha256": "2149bf40adc0eabdd7d0ad4ebc7938288e6c74050ca979d9227f5d9221bec8cb",
2061
2066
  "mode": 420
2062
2067
  },
2063
2068
  {
2064
2069
  "path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/incident-postmortem-extraction.md",
2065
- "sha256": "1d2f764ad17925254509c0f541f81161227752f054b77e0536036b3502a4ff88",
2070
+ "sha256": "31ee01a1b025f1b89631f1b133dcb5449df8087bff49a80065684f39656a027b",
2066
2071
  "mode": 420
2067
2072
  },
2068
2073
  {
@@ -2112,7 +2117,7 @@
2112
2117
  },
2113
2118
  {
2114
2119
  "path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/rule-consolidation.md",
2115
- "sha256": "d2455dfb4f3213db76244a21e004ad0f934279c773d733bae9303a90990f285f",
2120
+ "sha256": "e4c73b6bd412c9aca273cc36af7d987491e77f7da9639d7469110b2dc6da338a",
2116
2121
  "mode": 420
2117
2122
  },
2118
2123
  {
@@ -2122,7 +2127,7 @@
2122
2127
  },
2123
2128
  {
2124
2129
  "path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/source-register.md",
2125
- "sha256": "f49ace762eaa93ed4e662cacc67714b848ca567e98c1f93a7674e3bba30a16b6",
2130
+ "sha256": "12ca28829763dcd5b1e7e55ffe32c5189757855d9e22d34a56c4dc1524293e18",
2126
2131
  "mode": 420
2127
2132
  },
2128
2133
  {
@@ -2137,7 +2142,7 @@
2137
2142
  },
2138
2143
  {
2139
2144
  "path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/uiux-judgment-extraction.md",
2140
- "sha256": "6513a3f9788b37c5577379a1db6f1136fcb43f5206a2c293faa6473e36a90487",
2145
+ "sha256": "969808be6cf5234e689a7675c2108d1ac464882b93216e600122e02bdc05f221",
2141
2146
  "mode": 420
2142
2147
  },
2143
2148
  {
@@ -2147,7 +2152,7 @@
2147
2152
  },
2148
2153
  {
2149
2154
  "path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/validation-and-landing.md",
2150
- "sha256": "58f85c05e3a08c49836113778ba7a8dba86c5dbf4b2716e20c38f86632481c52",
2155
+ "sha256": "cd5cbc4ae9185a1c96fc945dee1bcfd958638498f01ba2487b772a2e9cc49ece",
2151
2156
  "mode": 420
2152
2157
  },
2153
2158
  {
@@ -2195,6 +2200,11 @@
2195
2200
  "sha256": "10cdd03d67185c1b1730a34248edb6c311e6ee8b82b8ecc0f7923e8f8f368b59",
2196
2201
  "mode": 420
2197
2202
  },
2203
+ {
2204
+ "path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/entrypoint_form_census.py",
2205
+ "sha256": "878c4694c4177a29f19c3b46d9b595696a768e26ff275429d380bf0e4bfc809e",
2206
+ "mode": 493
2207
+ },
2198
2208
  {
2199
2209
  "path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/eval-golden-trace.rb",
2200
2210
  "sha256": "14c3c7c1437c6d70c5ab48ac8b1312fab3a421de31b110da84fa0528762b924c",
@@ -2245,6 +2255,11 @@
2245
2255
  "sha256": "8bd90fc37d53e466ac5735d2fc956a9d3a31bcd31dd51614ae9e15d435e39726",
2246
2256
  "mode": 420
2247
2257
  },
2258
+ {
2259
+ "path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/reference-access-census.sh",
2260
+ "sha256": "c408c6d4871d91b9a7d345959154ad70e2c5bf8233ff7e88bbd7d6cd7bb01323",
2261
+ "mode": 493
2262
+ },
2248
2263
  {
2249
2264
  "path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/register-firing-path-resolution.rb",
2250
2265
  "sha256": "db009982ac485aaebf708c4bff9b33fc65e2fef6264769ec1e42870f75bc8677",
@@ -2252,7 +2267,7 @@
2252
2267
  },
2253
2268
  {
2254
2269
  "path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/review_ledger_binding.py",
2255
- "sha256": "a44a65d80dbcb366f667742e160949256c7b191175ab6fb711c38e35c74f11c7",
2270
+ "sha256": "ae7b2aa0c7f0afa569f424fbd57d62209e21fd4da9a6b94da15686eb4b2d8719",
2256
2271
  "mode": 493
2257
2272
  },
2258
2273
  {
@@ -2312,7 +2327,7 @@
2312
2327
  },
2313
2328
  {
2314
2329
  "path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_ccl_regressions.sh",
2315
- "sha256": "2463130c6af00c0611f1197628b3eb760e141b7db3fb8db8b88bb27e3da7fd62",
2330
+ "sha256": "c8309b75883f8e7e404ae15a85efc347e58f0255385bf57ddb6b200a3b587588",
2316
2331
  "mode": 493
2317
2332
  },
2318
2333
  {
@@ -2365,6 +2380,11 @@
2365
2380
  "sha256": "46016ad11df8ee75dd7aa17c2e017fad60dc127a234f0bd4c5bcb3baf4f7d0ee",
2366
2381
  "mode": 493
2367
2382
  },
2383
+ {
2384
+ "path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_entrypoint_form_census.sh",
2385
+ "sha256": "2cb5a411fc9badfd0667cea9cc20567b7edade74b30520de184c1dfca99b6491",
2386
+ "mode": 493
2387
+ },
2368
2388
  {
2369
2389
  "path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_eval_routing_bank_grader_diagnostics.sh",
2370
2390
  "sha256": "10cacb2baf142dbedddbecb34ac2ee1bd9d043b9c946acff9ce83373be0d1553",
@@ -2460,6 +2480,11 @@
2460
2480
  "sha256": "c495841ae6cd6cb3bf4c65a9883da08b4b24f50b53dba2219df9327a41980251",
2461
2481
  "mode": 493
2462
2482
  },
2483
+ {
2484
+ "path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_reference_access_census.sh",
2485
+ "sha256": "4aa6d437078b939270e607d1ad4ea17f4043824aee807859a795a85f7ebc00a6",
2486
+ "mode": 493
2487
+ },
2463
2488
  {
2464
2489
  "path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_register_firing_path_resolution.sh",
2465
2490
  "sha256": "4894f739af0b3aa995243592d71ca3f93de3108a11f9734422a4f15c2ca33668",
@@ -2482,7 +2507,7 @@
2482
2507
  },
2483
2508
  {
2484
2509
  "path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_review_ledger_binding.sh",
2485
- "sha256": "471362ad4524c7c13367e4cc296d48beff3127bd50974fdc5d4e8d038396855e",
2510
+ "sha256": "a7274e735371dcd80b4c1b7745e3e5648d7e84b1dee676bf2743f4600751a770",
2486
2511
  "mode": 493
2487
2512
  },
2488
2513
  {
@@ -2542,7 +2567,7 @@
2542
2567
  },
2543
2568
  {
2544
2569
  "path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/SKILL.md",
2545
- "sha256": "83c6d8bb60a0edafc1c80ca02109f7210ec090e5c9b5eda813672b14779b7cc4",
2570
+ "sha256": "5d46b33dcc0c84ec4cac51bdea93aba643427f88dcd7ee3930b3ecd2132bc4f0",
2546
2571
  "mode": 420
2547
2572
  },
2548
2573
  {
@@ -3378,5 +3403,5 @@
3378
3403
  "mode": 420
3379
3404
  }
3380
3405
  ],
3381
- "snapshotHash": "d4aa7c100eb2cd58f72a70fe4ee98c37c0b6035a75afcf7cc5a001eb88147cce"
3406
+ "snapshotHash": "ba1bcedf0fe6247bda9eb70091de735a5e6fef8e7fc8d82f573841870dcb5302"
3382
3407
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ccoalm/ccl-skills",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "description": "Reusable workflows that help coding agents plan, build, test, review, and release software — for Claude Code, Codex, and OpenCode",
5
5
  "keywords": ["skills", "agent-skills", "claude", "claude-code", "codex", "opencode", "agent", "ai", "ai-agents", "cli", "anthropic", "developer-tools"],
6
6
  "type": "module",