@ccoalm/ccl-skills 0.1.1 → 0.3.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.
- package/README.md +12 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_init_policy_matrix.sh +93 -16
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_parse_probe_result.sh +10 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_review_gate.sh +249 -5
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_review_gate_abort_leak.sh +394 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/model-prompt-evaluation.md +7 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/external-ui-ux-quality-benchmarks.md +50 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/ui-ux-audit.md +1 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/SKILL.md +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/external-practice-controls.md +59 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/rule-consolidation.md +3 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/source-register.md +34 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/source-to-skill-extraction.md +16 -4
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/impact-chain-gate.rb +391 -14
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/register-firing-path-resolution.rb +74 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_ccl_regressions.sh +74 -33
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_ccl_skill_catalog.sh +11 -4
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_impact_chain_gate_verdict_differential.sh +421 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_impact_chain_round_attribution.sh +576 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_impact_chain_source_refuted.sh +176 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_regression_runner_lanes.sh +101 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_validate_skill_root_depth.sh +6 -2
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/ci-fixtures-and-flake-control.md +1 -1
- package/dist/assets/release.json +66 -21
- package/dist/cli.js +23 -2
- package/dist/update-notice.d.ts +71 -0
- package/dist/update-notice.js +173 -0
- package/dist/version-check.d.ts +2 -0
- package/dist/version-check.js +7 -0
- package/package.json +1 -1
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# 043:`source-refuted` 证据类的冻结验收用例(specs/043-evidence-class-source-refuted/frozen-acceptance.md)。
|
|
3
|
+
#
|
|
4
|
+
# A-F 在闸被触碰之前冻结;G/H 由独立评审与挑战各指出一处滥用路径后补入(**加严**,
|
|
5
|
+
# 不是放宽)。通过条件是全部命中——任何一条不符即本轮
|
|
6
|
+
# 未完成,**不得**以"主要目标达成"结案,也不得为让 A 变绿而放宽 B–F。
|
|
7
|
+
#
|
|
8
|
+
# 全部确定性,不调模型。每用例一条分支,互不影响本地未提交改动。
|
|
9
|
+
set -u
|
|
10
|
+
ROOT="$(cd "$(dirname "$0")/../../.." && pwd -P)"
|
|
11
|
+
GATE="$ROOT/skills/skill-extraction-workflow/scripts/impact-chain-gate.rb"
|
|
12
|
+
TMP="$(mktemp -d)"; trap 'rm -rf "$TMP"' EXIT INT TERM
|
|
13
|
+
fails=0
|
|
14
|
+
fail() { echo "FAIL: $*" >&2; fails=$((fails+1)); }
|
|
15
|
+
ok() { echo " ok $*"; }
|
|
16
|
+
|
|
17
|
+
REPO="$TMP/repo"
|
|
18
|
+
git clone -q "$ROOT" "$REPO"
|
|
19
|
+
git -C "$REPO" config user.email test@example.invalid
|
|
20
|
+
git -C "$REPO" config user.name "Test User"
|
|
21
|
+
|
|
22
|
+
OWNER_REF="skills/product-rd-workflow/SKILL.md"
|
|
23
|
+
REGISTER="skills/skill-extraction-workflow/references/source-register.md"
|
|
24
|
+
ZLOSS="specs/043-evidence-class-source-refuted/zero-loss-fixture.md"
|
|
25
|
+
|
|
26
|
+
# 种子:给 owner 的 reference 加一段可被后续用例整段删掉的文本(保证净字节 < 0),
|
|
27
|
+
# 以及一份非空的零损失义务对照 fixture。
|
|
28
|
+
WITHDRAWN_TEXT='A fixture claim that a later case withdraws wholesale; it is long enough that removing it makes the owner package shrink by a clear margin.'
|
|
29
|
+
mkdir -p "$REPO/$(dirname "$ZLOSS")"
|
|
30
|
+
printf '# 零损失义务对照\n\n被撤回的原文(逐字):\n\n> %s\n\n| before 义务 | 去向 |\n| --- | --- |\n| 该段承载的义务 | survives-verbatim: 同文件上一段 |\n' "$WITHDRAWN_TEXT" > "$REPO/$ZLOSS"
|
|
31
|
+
printf '\n%s\n' "$WITHDRAWN_TEXT" >> "$REPO/$OWNER_REF"
|
|
32
|
+
printf '\n<!-- fixture-withdrawable-start -->\nA fixture claim that a later case withdraws wholesale; it is long enough that removing it makes the owner package shrink by a clear margin, which is what the net-bytes floor checks.\n<!-- fixture-withdrawable-end -->\n' >> "$REPO/$OWNER_REF"
|
|
33
|
+
git -C "$REPO" add -A >/dev/null
|
|
34
|
+
git -C "$REPO" commit -qm "seed fixtures for source-refuted cases"
|
|
35
|
+
git -C "$REPO" branch fixture-base HEAD
|
|
36
|
+
|
|
37
|
+
new_case() { git -C "$REPO" switch -q -C "$1" fixture-base; git -C "$REPO" branch --set-upstream-to=fixture-base "$1" >/dev/null 2>&1; }
|
|
38
|
+
commit_case() { git -C "$REPO" add -A >/dev/null; git -C "$REPO" commit -qm "$1"; }
|
|
39
|
+
run_gate() { set +e; OUT="$(env -u CCL_SKILL_BASE_REF ruby "$GATE" "$REPO" 2>&1)"; RC=$?; set -e 2>/dev/null || true; }
|
|
40
|
+
add_row() { printf '%s\n' "$1" >> "$REPO/$REGISTER"; }
|
|
41
|
+
withdraw_fixture() { # **纯删除**:只删那一行,不加任何内容。说明文字进 reference。
|
|
42
|
+
python3 - "$REPO/$OWNER_REF" "$WITHDRAWN_TEXT" <<'PYX'
|
|
43
|
+
import io,sys
|
|
44
|
+
p, txt = sys.argv[1], sys.argv[2]
|
|
45
|
+
s = io.open(p, encoding='utf-8').read()
|
|
46
|
+
io.open(p, 'w', encoding='utf-8').write(s.replace("\n" + txt + "\n", "\n", 1))
|
|
47
|
+
PYX
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
SRC="https://example.invalid/primary-source-that-refutes-the-claim"
|
|
51
|
+
FIRING="firing-path: file:skills/product-rd-workflow/SKILL.md#must survive verbatim above"
|
|
52
|
+
FIRING_F="firing-path: file:skills/product-rd-workflow/SKILL.md#must record a RED-baseline row before it lands"
|
|
53
|
+
|
|
54
|
+
# ---- A:合规撤回 —— 有类时必须绿,无类时必须红 ----
|
|
55
|
+
new_case case-a; withdraw_fixture
|
|
56
|
+
add_row "| A fixture claim is refuted by its primary source and is withdrawn wholesale | \`downstream-executor\` | behavioral-evidence: source-refuted; observed-failure: no | \`updated\` | zero-loss: \`$ZLOSS#零损失义务对照\`; refuting source: $SRC; \`product-rd-workflow/SKILL.md\` |"
|
|
57
|
+
commit_case "case A: compliant source-refuted withdrawal"; run_gate
|
|
58
|
+
# A 的期望值在裁决后由绿改红:该类不再顶起 RED 底线(见 frozen-acceptance.md 的裁决记录)。
|
|
59
|
+
# 合规撤回现在仍然被拦——它要么配一条 RED 行,要么由具名风险 owner 人工放行。
|
|
60
|
+
[ "$RC" != "0" ] && ok "A 合规撤回 -> 仍红(该类不顶底线,撤回需人工放行)" || fail "A 不得自动放行"
|
|
61
|
+
|
|
62
|
+
# ---- B:真行为变更披该标签 —— 任何时候都必须红 ----
|
|
63
|
+
new_case case-b
|
|
64
|
+
printf '\n- Every fixture change must obtain approval before it lands.\n' >> "$REPO/$OWNER_REF"
|
|
65
|
+
add_row "| A newly added normative rule wearing the withdrawal label | \`downstream-executor\` | behavioral-evidence: source-refuted; observed-failure: no | \`updated\` | zero-loss: \`$ZLOSS#零损失义务对照\`; refuting source: $SRC; \`product-rd-workflow/SKILL.md\` |"
|
|
66
|
+
commit_case "case B: real behaviour change wearing the label"; run_gate
|
|
67
|
+
[ "$RC" != "0" ] && ok "B 真行为变更披标签 -> 仍红" || fail "B 不得通过(净增却用撤回类)"
|
|
68
|
+
|
|
69
|
+
# ---- C:缺一手源 URL —— 必须红 ----
|
|
70
|
+
new_case case-c; withdraw_fixture
|
|
71
|
+
add_row "| A withdrawal whose row cites no refuting source | \`downstream-executor\` | behavioral-evidence: source-refuted; observed-failure: no | \`updated\` | zero-loss: \`$ZLOSS#零损失义务对照\`; \`product-rd-workflow/SKILL.md\` |"
|
|
72
|
+
commit_case "case C: missing refuting source"; run_gate
|
|
73
|
+
[ "$RC" != "0" ] && ok "C 缺一手源 -> 仍红" || fail "C 不得通过(无源即无据)"
|
|
74
|
+
|
|
75
|
+
# ---- D:缺零损失指针 —— 必须红 ----
|
|
76
|
+
new_case case-d; withdraw_fixture
|
|
77
|
+
add_row "| A withdrawal whose row carries no zero-loss map | \`downstream-executor\` | behavioral-evidence: source-refuted; observed-failure: no | \`updated\` | refuting source: $SRC; \`product-rd-workflow/SKILL.md\` |"
|
|
78
|
+
commit_case "case D: missing zero-loss pointer"; run_gate
|
|
79
|
+
[ "$RC" != "0" ] && ok "D 缺零损失指针 -> 仍红" || fail "D 不得通过(义务保全无对照)"
|
|
80
|
+
|
|
81
|
+
# ---- E:observed-failure: yes —— 必须红 ----
|
|
82
|
+
new_case case-e; withdraw_fixture
|
|
83
|
+
add_row "| A withdrawal self-declaring an observed failure | \`downstream-executor\` | behavioral-evidence: source-refuted; observed-failure: yes | \`updated\` | zero-loss: \`$ZLOSS#零损失义务对照\`; refuting source: $SRC; \`product-rd-workflow/SKILL.md\` |"
|
|
84
|
+
commit_case "case E: observed-failure yes"; run_gate
|
|
85
|
+
[ "$RC" != "0" ] && ok "E observed-failure: yes -> 仍红" || fail "E 不得通过(分类语义不得自选)"
|
|
86
|
+
|
|
87
|
+
# ---- F:既有类不得回归 ----
|
|
88
|
+
new_case case-f
|
|
89
|
+
printf '\n- Every fixture delivery must record a RED-baseline row before it lands.\n' >> "$REPO/$OWNER_REF"
|
|
90
|
+
add_row "| An ordinary behaviour-changing rule with a RED-baseline row | \`downstream-executor\` | behavioral-evidence: RED-baseline; observed-failure: yes; $FIRING_F | \`updated\` | \`product-rd-workflow/SKILL.md\` |"
|
|
91
|
+
commit_case "case F: existing RED-baseline path"; run_gate
|
|
92
|
+
if [ "$RC" = "0" ]; then ok "F 既有 RED-baseline 路径 -> 绿(无回归)"; else echo "--- F 完整输出 ---"; printf '%s\n' "$OUT"; fail "F 回归"; fi
|
|
93
|
+
|
|
94
|
+
# ---- G:混合行 —— 同 owner 一条合规撤回 + 一条真行为变更的 semantic-control。必须红 ----
|
|
95
|
+
# 独立评审 REVIEW-1:any? 顶起底线时,真行为变更会搭便车。
|
|
96
|
+
new_case case-g; withdraw_fixture
|
|
97
|
+
printf '\n- Every unrelated fixture delivery must obtain approval before it lands. zzmixedrule\n' >> "$REPO/$OWNER_REF"
|
|
98
|
+
add_row "| A compliant withdrawal alongside an unrelated change | \`downstream-executor\` | behavioral-evidence: source-refuted; observed-failure: no | \`updated\` | zero-loss: \`$ZLOSS#零损失义务对照\`; refuting source: $SRC; \`product-rd-workflow/SKILL.md\` |"
|
|
99
|
+
add_row "| An unrelated behaviour change riding along on a stable-control label | \`downstream-executor\` | behavioral-evidence: semantic-control; observed-failure: no; firing-path: file:skills/product-rd-workflow/SKILL.md#must obtain approval before it lands | \`updated\` | \`product-rd-workflow/SKILL.md\` |"
|
|
100
|
+
commit_case "case G: mixed rows"; run_gate
|
|
101
|
+
[ "$RC" != "0" ] && ok "G 混合行 -> 仍红" || fail "G 不得通过(真行为变更搭撤回的便车)"
|
|
102
|
+
|
|
103
|
+
# ---- H:抵消式新增 + 假锚点 —— 必须红 ----
|
|
104
|
+
# 独立挑战 CHALLENGE-1:删无关文字凑净负、加一条新规则、指针写不存在的锚。
|
|
105
|
+
new_case case-h; withdraw_fixture
|
|
106
|
+
printf '\n- Every smuggled fixture rule must be rejected by the withdrawal class. zzsmuggled\n' >> "$REPO/$OWNER_REF"
|
|
107
|
+
add_row "| A smuggled rule hidden behind an offsetting deletion | \`downstream-executor\` | behavioral-evidence: source-refuted; observed-failure: no | \`updated\` | zero-loss: \`README.md#no-such-anchor-exists-here\`; refuting source: $SRC; \`product-rd-workflow/SKILL.md\` |"
|
|
108
|
+
commit_case "case H: offset addition with bogus anchor"; run_gate
|
|
109
|
+
[ "$RC" != "0" ] && ok "H 抵消式新增 + 假锚点 -> 仍红" || fail "H 不得通过(新增规范行 / 锚点不解析)"
|
|
110
|
+
|
|
111
|
+
# ---- I:脚本改动、零删除 —— 必须红(旧代理谓词看不见脚本)----
|
|
112
|
+
new_case case-i
|
|
113
|
+
printf '\n# fixture: an added shell line that changes behaviour without matching any prose predicate\n' >> "$REPO/skills/product-rd-workflow/scripts/check-agent-contract-coverage.sh"
|
|
114
|
+
add_row "| A script change wearing the withdrawal label with nothing deleted | \`downstream-executor\` | behavioral-evidence: source-refuted; observed-failure: no | \`updated\` | zero-loss: \`$ZLOSS#零损失义务对照\`; refuting source: $SRC; \`product-rd-workflow/SKILL.md\` |"
|
|
115
|
+
commit_case "case I: script change, no deletion"; run_gate
|
|
116
|
+
[ "$RC" != "0" ] && ok "I 脚本改动零删除 -> 仍红" || fail "I 不得通过(非 .md、且无删除)"
|
|
117
|
+
|
|
118
|
+
# ---- J:`Always` 规则、零删除 —— 必须红(旧谓词故意排除 always)----
|
|
119
|
+
new_case case-j
|
|
120
|
+
printf '\n- Always authenticate fixture requests before dispatch.\n' >> "$REPO/$OWNER_REF"
|
|
121
|
+
add_row "| An Always-phrased rule wearing the withdrawal label with nothing deleted | \`downstream-executor\` | behavioral-evidence: source-refuted; observed-failure: no | \`updated\` | zero-loss: \`$ZLOSS#零损失义务对照\`; refuting source: $SRC; \`product-rd-workflow/SKILL.md\` |"
|
|
122
|
+
commit_case "case J: Always rule, no deletion"; run_gate
|
|
123
|
+
[ "$RC" != "0" ] && ok "J Always 规则零删除 -> 仍红" || fail "J 不得通过(有新增行)"
|
|
124
|
+
|
|
125
|
+
# ---- K:改权限 + 一次真删除 —— 必须红 ----
|
|
126
|
+
# 独立评审:chmod 在 --name-status 里显示为 M、在 --numstat 里记 0/0。
|
|
127
|
+
new_case case-k; withdraw_fixture
|
|
128
|
+
chmod 755 "$REPO/skills/product-rd-workflow/references/adr-convention.md"
|
|
129
|
+
add_row "| A mode change riding along with a genuine deletion | \`downstream-executor\` | behavioral-evidence: source-refuted; observed-failure: no | \`updated\` | zero-loss: \`$ZLOSS#零损失义务对照\`; refuting source: $SRC; \`product-rd-workflow/SKILL.md\` |"
|
|
130
|
+
commit_case "case K: chmod plus deletion"; run_gate
|
|
131
|
+
[ "$RC" != "0" ] && ok "K 改权限 + 删除 -> 仍红" || fail "K 不得通过(mode 变更未被 numstat 反映)"
|
|
132
|
+
|
|
133
|
+
# ---- L:指针路径穿越出仓 —— 必须红 ----
|
|
134
|
+
new_case case-l; withdraw_fixture
|
|
135
|
+
add_row "| A withdrawal whose zero-loss pointer escapes the repository | \`downstream-executor\` | behavioral-evidence: source-refuted; observed-failure: no | \`updated\` | zero-loss: \`../../../etc/hosts#localhost\`; refuting source: $SRC; \`product-rd-workflow/SKILL.md\` |"
|
|
136
|
+
commit_case "case L: traversal pointer"; run_gate
|
|
137
|
+
[ "$RC" != "0" ] && ok "L 指针穿越出仓 -> 仍红" || fail "L 不得通过(路径逃出仓库)"
|
|
138
|
+
|
|
139
|
+
# ---- M:锚点是存在但无意义的单字符子串 —— 必须红 ----
|
|
140
|
+
new_case case-m; withdraw_fixture
|
|
141
|
+
add_row "| A withdrawal whose anchor is a bare existing substring | \`downstream-executor\` | behavioral-evidence: source-refuted; observed-failure: no | \`updated\` | zero-loss: \`$ZLOSS#a\`; refuting source: $SRC; \`product-rd-workflow/SKILL.md\` |"
|
|
142
|
+
commit_case "case M: one-character substring anchor"; run_gate
|
|
143
|
+
[ "$RC" != "0" ] && ok "M 单字符子串锚 -> 仍红" || fail "M 不得通过(锚点未落在标题上)"
|
|
144
|
+
|
|
145
|
+
# ---- N:锚点是存在但不相干的整词 —— 必须红 ----
|
|
146
|
+
new_case case-n; withdraw_fixture
|
|
147
|
+
add_row "| A withdrawal whose anchor is an unrelated existing word | \`downstream-executor\` | behavioral-evidence: source-refuted; observed-failure: no | \`updated\` | zero-loss: \`$ZLOSS#survives-verbatim\`; refuting source: $SRC; \`product-rd-workflow/SKILL.md\` |"
|
|
148
|
+
commit_case "case N: unrelated existing substring anchor"; run_gate
|
|
149
|
+
[ "$RC" != "0" ] && ok "N 不相干整词锚 -> 仍红" || fail "N 不得通过(锚点未落在标题上)"
|
|
150
|
+
|
|
151
|
+
# ---- O:既有 semantic-control 路径不得回归(配对 RED 行)----
|
|
152
|
+
new_case case-o
|
|
153
|
+
printf '\n- Every fixture control rule must be recorded before it lands. zzsemctl\n' >> "$REPO/$OWNER_REF"
|
|
154
|
+
add_row "| An unchanged control alongside a RED-baseline row | \`downstream-executor\` | behavioral-evidence: semantic-control; observed-failure: no; firing-path: file:skills/product-rd-workflow/SKILL.md#must be recorded before it lands | \`updated\` | \`product-rd-workflow/SKILL.md\` |"
|
|
155
|
+
add_row "| The behaviour change the control accompanies | \`downstream-executor\` | behavioral-evidence: RED-baseline; observed-failure: yes; firing-path: file:skills/product-rd-workflow/SKILL.md#must be recorded before it lands | \`updated\` | \`product-rd-workflow/SKILL.md\` |"
|
|
156
|
+
commit_case "case O: semantic-control beside RED-baseline"; run_gate
|
|
157
|
+
[ "$RC" = "0" ] && ok "O semantic-control + RED-baseline -> 绿(无回归)" || { echo "--- O ---"; printf '%s\n' "$OUT" | tail -3; fail "O 既有路径回归"; }
|
|
158
|
+
|
|
159
|
+
# ---- P:对照表没有逐字交代被删内容 —— 必须红 ----
|
|
160
|
+
new_case case-p; withdraw_fixture
|
|
161
|
+
python3 - "$REPO/$ZLOSS" <<'PYP'
|
|
162
|
+
import io,sys
|
|
163
|
+
p=sys.argv[1]
|
|
164
|
+
io.open(p,'w',encoding='utf-8').write("# 零损失义务对照\n\n| before 义务 | 去向 |\n| --- | --- |\n| 某条义务 | survives-verbatim: 别处 |\n")
|
|
165
|
+
PYP
|
|
166
|
+
add_row "| A withdrawal whose map does not quote what was removed | \`downstream-executor\` | behavioral-evidence: source-refuted; observed-failure: no | \`updated\` | zero-loss: \`$ZLOSS#零损失义务对照\`; refuting source: $SRC; \`product-rd-workflow/SKILL.md\` |"
|
|
167
|
+
commit_case "case P: map does not account for deleted text"; run_gate
|
|
168
|
+
[ "$RC" != "0" ] && ok "P 对照表未逐字交代被删内容 -> 仍红" || fail "P 不得通过(删了什么没抄出来)"
|
|
169
|
+
|
|
170
|
+
echo
|
|
171
|
+
if [ "$fails" = "0" ]; then
|
|
172
|
+
echo "all frozen cases behaved as specified"
|
|
173
|
+
else
|
|
174
|
+
echo "frozen cases did not all behave as specified"
|
|
175
|
+
exit 1
|
|
176
|
+
fi
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Lane-semantics regression for test_check_ccl_regressions.sh (036 challenge
|
|
3
|
+
# P2): --heavy-only must run exactly the heavy_tests entries and no fast entry,
|
|
4
|
+
# propagate a failing heavy suite, and end with its own token; --fast must run
|
|
5
|
+
# exactly the fast_tests entries and no heavy entry. Runs the real runner
|
|
6
|
+
# against a stub fixture tree via REGRESSION_SCRIPTS_DIR, so it proves the mode
|
|
7
|
+
# dispatch in seconds without executing the real multi-minute suites. The stub
|
|
8
|
+
# list is derived from the runner's own arrays, so a lane edit cannot drift the
|
|
9
|
+
# fixture.
|
|
10
|
+
set -euo pipefail
|
|
11
|
+
|
|
12
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
|
|
13
|
+
RUNNER="$SCRIPT_DIR/test_check_ccl_regressions.sh"
|
|
14
|
+
|
|
15
|
+
fail() { printf 'FAIL: %s\n' "$1" >&2; exit 1; }
|
|
16
|
+
|
|
17
|
+
extract_lane() {
|
|
18
|
+
# Bare entry tokens of one array block, comments stripped.
|
|
19
|
+
sed -n "/^${1}=(/,/^)/p" "$RUNNER" | sed -e '/^#/d' -e '/=($/d' -e '/^)$/d' \
|
|
20
|
+
-e 's/[[:space:]]*#.*$//' -e 's/^[[:space:]]*//' -e '/^$/d'
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
fast_lane="$(extract_lane fast_tests)"
|
|
24
|
+
heavy_lane="$(extract_lane heavy_tests)"
|
|
25
|
+
[ -n "$fast_lane" ] || fail "could not extract fast_tests from the runner"
|
|
26
|
+
[ -n "$heavy_lane" ] || fail "could not extract heavy_tests from the runner"
|
|
27
|
+
|
|
28
|
+
# Exactly-once contract at the array level (r4 challenge P2): a suite listed
|
|
29
|
+
# twice in one lane, or in both lanes, would run twice in CI while every
|
|
30
|
+
# per-mode comparison here still passed — reject it before building stubs.
|
|
31
|
+
dup_fast="$(sort <<<"$fast_lane" | uniq -d)"
|
|
32
|
+
[ -z "$dup_fast" ] || fail "duplicate entries inside fast_tests: $dup_fast"
|
|
33
|
+
dup_heavy="$(sort <<<"$heavy_lane" | uniq -d)"
|
|
34
|
+
[ -z "$dup_heavy" ] || fail "duplicate entries inside heavy_tests: $dup_heavy"
|
|
35
|
+
overlap="$(comm -12 <(sort <<<"$fast_lane") <(sort <<<"$heavy_lane"))"
|
|
36
|
+
[ -z "$overlap" ] || fail "entries registered in both lanes (would run twice per pipeline): $overlap"
|
|
37
|
+
|
|
38
|
+
TMP="$(mktemp -d)"
|
|
39
|
+
trap 'rm -rf "$TMP"' EXIT
|
|
40
|
+
FIX="$TMP/skills/skill-extraction-workflow/scripts"
|
|
41
|
+
mkdir -p "$FIX"
|
|
42
|
+
LOG="$TMP/ran.log"
|
|
43
|
+
|
|
44
|
+
write_stub() {
|
|
45
|
+
local entry="$1"
|
|
46
|
+
local path="$FIX/$entry"
|
|
47
|
+
mkdir -p "$(dirname "$path")"
|
|
48
|
+
printf '#!/usr/bin/env bash\nprintf "%%s\\n" "%s" >> "%s"\n' "$entry" "$LOG" >"$path"
|
|
49
|
+
}
|
|
50
|
+
while IFS= read -r entry; do write_stub "$entry"; done <<<"$fast_lane"
|
|
51
|
+
while IFS= read -r entry; do write_stub "$entry"; done <<<"$heavy_lane"
|
|
52
|
+
|
|
53
|
+
run_mode() {
|
|
54
|
+
: >"$LOG"
|
|
55
|
+
REGRESSION_SCRIPTS_DIR="$FIX" bash "$RUNNER" "$1" >"$TMP/out.$2" 2>&1
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
# --heavy-only: exactly the heavy lane, its own token, no fast token.
|
|
59
|
+
run_mode --heavy-only heavy || fail "--heavy-only exited nonzero on passing stubs"
|
|
60
|
+
diff <(sort <<<"$heavy_lane") <(sort "$LOG") >/dev/null \
|
|
61
|
+
|| fail "--heavy-only did not run exactly the heavy_tests entries"
|
|
62
|
+
grep -q '^test_check_ccl_regressions_heavy_only_ok$' "$TMP/out.heavy" \
|
|
63
|
+
|| fail "--heavy-only missing its completion token"
|
|
64
|
+
if grep -q 'test_check_ccl_regressions_fast_ok\|test_check_ccl_regressions_full_ok' "$TMP/out.heavy"; then
|
|
65
|
+
fail "--heavy-only emitted a fast/full token"
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
# --fast: exactly the fast lane, fast token, no heavy entry.
|
|
69
|
+
run_mode --fast fast || fail "--fast exited nonzero on passing stubs"
|
|
70
|
+
diff <(sort <<<"$fast_lane") <(sort "$LOG") >/dev/null \
|
|
71
|
+
|| fail "--fast did not run exactly the fast_tests entries"
|
|
72
|
+
grep -q '^test_check_ccl_regressions_fast_ok$' "$TMP/out.fast" \
|
|
73
|
+
|| fail "--fast missing its completion token"
|
|
74
|
+
|
|
75
|
+
# --full: both lanes, full token.
|
|
76
|
+
run_mode --full full || fail "--full exited nonzero on passing stubs"
|
|
77
|
+
diff <(sort <(printf '%s\n%s\n' "$fast_lane" "$heavy_lane")) <(sort "$LOG") >/dev/null \
|
|
78
|
+
|| fail "--full did not run exactly fast_tests + heavy_tests"
|
|
79
|
+
grep -q '^test_check_ccl_regressions_full_ok$' "$TMP/out.full" \
|
|
80
|
+
|| fail "--full missing its completion token"
|
|
81
|
+
|
|
82
|
+
# Failure propagation: a red heavy stub must fail --heavy-only.
|
|
83
|
+
first_heavy="$(head -n 1 <<<"$heavy_lane")"
|
|
84
|
+
printf '#!/usr/bin/env bash\nexit 1\n' >"$FIX/$first_heavy"
|
|
85
|
+
if REGRESSION_SCRIPTS_DIR="$FIX" bash "$RUNNER" --heavy-only >"$TMP/out.red" 2>&1; then
|
|
86
|
+
fail "--heavy-only exited zero although a heavy stub failed"
|
|
87
|
+
fi
|
|
88
|
+
write_stub "$first_heavy"
|
|
89
|
+
|
|
90
|
+
# Unregistered-sibling enforcement (036 challenge P1): an unregistered
|
|
91
|
+
# test_*.sh must hard-fail every execution mode, independent of the
|
|
92
|
+
# registration guard test staying registered.
|
|
93
|
+
: >"$FIX/test_unregistered_probe.sh"
|
|
94
|
+
if REGRESSION_SCRIPTS_DIR="$FIX" bash "$RUNNER" --fast >"$TMP/out.unreg" 2>&1; then
|
|
95
|
+
fail "--fast exited zero although an unregistered sibling test exists"
|
|
96
|
+
fi
|
|
97
|
+
grep -q 'test_unregistered_probe.sh' "$TMP/out.unreg" \
|
|
98
|
+
|| fail "unregistered-sibling failure did not name the offending file"
|
|
99
|
+
rm "$FIX/test_unregistered_probe.sh"
|
|
100
|
+
|
|
101
|
+
echo "regression_runner_lanes_ok"
|
|
@@ -39,7 +39,11 @@ printf 'not-frontmatter\n' > "$tmp/repo/skills/sample-skill/fixtures/SKILL.md"
|
|
|
39
39
|
mkdir -p "$tmp/repo/vendor/thing"
|
|
40
40
|
printf 'not-frontmatter\n' > "$tmp/repo/vendor/thing/SKILL.md"
|
|
41
41
|
out="$(bash "$VALIDATE" "$tmp/repo" 2>&1)" || fail "repo-root run exited non-zero: $out"
|
|
42
|
-
|
|
42
|
+
# Pure-bash substring match, not `printf | grep -q`: grep -q exits on its first
|
|
43
|
+
# hit, the producer takes SIGPIPE, and under `set -o pipefail` the SUCCESS path
|
|
44
|
+
# then reports failure. Timing-dependent, so it stayed latent until this lane
|
|
45
|
+
# ran concurrently (specs/037-ci-intra-job-parallel/plan.md).
|
|
46
|
+
[[ "$out" == *"validating 1 skill root(s)"* ]] \
|
|
43
47
|
|| fail "expected exactly 1 root (nested fixture must be excluded): $out"
|
|
44
48
|
|
|
45
49
|
# (2) a tree with no SKILL.md still fails loudly (exit 2, no silent green).
|
|
@@ -47,7 +51,7 @@ mkdir -p "$tmp/empty/sub/deeper"
|
|
|
47
51
|
if out="$(bash "$VALIDATE" "$tmp/empty" 2>&1)"; then
|
|
48
52
|
fail "empty tree unexpectedly passed: $out"
|
|
49
53
|
fi
|
|
50
|
-
|
|
54
|
+
[[ "$out" == *no_skill_roots_found* ]] \
|
|
51
55
|
|| fail "empty tree missing loud no_skill_roots_found: $out"
|
|
52
56
|
|
|
53
57
|
echo "PASS: validate-skill discovers skills/<name>/SKILL.md and stays loud on empty trees"
|
|
@@ -36,7 +36,7 @@ The live layer proves wiring and credentials, never the fault matrix.
|
|
|
36
36
|
|
|
37
37
|
## Flake Control
|
|
38
38
|
|
|
39
|
-
- Replace sleeps with explicit conditions. When an assertion still depends on time, make the ORACLE a state whose existence proves the invariant — the helper process still alive, the record not yet written, the lock still held — rather than "finished within N seconds"; a wall-clock margin only holds while the runner is fast enough, so it turns into a red on a loaded runner and, worse, into a silent pass when the margin is generous. Where a fixture's own lifetime is what the assertion races (a sleeping helper, a TTL, a retention window), push that lifetime far past any plausible run so it stops being a deadline, and keep any wall-clock bound as a coarse backstop only. Sample process state, not just liveness: an unreaped zombie still answers `kill -0`, so "still running" and "already gone" both need the state check, and reap lag on a loaded runner needs a bounded grace period instead of an instantaneous sample.
|
|
39
|
+
- Replace sleeps with explicit conditions. When an assertion still depends on time, make the ORACLE a state whose existence proves the invariant — the helper process still alive, the record not yet written, the lock still held — rather than "finished within N seconds"; a wall-clock margin only holds while the runner is fast enough, so it turns into a red on a loaded runner and, worse, into a silent pass when the margin is generous. Where a fixture's own lifetime is what the assertion races (a sleeping helper, a TTL, a retention window), push that lifetime far past any plausible run so it stops being a deadline, and keep any wall-clock bound as a coarse backstop only — far past, but never UNBOUNDED: the thing that normally ends such a helper is whatever the suite is testing, and when that reaper dies first (an aborted run, a cancelled job, a suspended host) the fixture's own lifetime becomes the only thing that will ever end it, so an infinite loop is how a test helper outlives the machine rather than the run. The suite also owns reaping what it started, and cannot delegate that to the component under test: a helper deliberately made signal-immune, or started in its own session/process group where a signal aimed at the suite cannot reach it, has no other reaper — trap the abort signals as well as EXIT, identify what to reap by something the run owns (its own private temp path, its recorded process groups) rather than by a shared name that would hit a concurrent lane, and prove ownership again at the moment of signalling because a pid or group id read earlier is a number the OS recycles. Assert at exit that nothing the run started is still alive: every case can pass while the process table is not clean, so a green suite is not the acceptance object here. Sample process state, not just liveness: an unreaped zombie still answers `kill -0`, so "still running" and "already gone" both need the state check, and reap lag on a loaded runner needs a bounded grace period instead of an instantaneous sample.
|
|
40
40
|
- Isolate tests by namespace, temp directory, tenant, user, DB schema, or unique id.
|
|
41
41
|
- Clean up with test cleanup hooks.
|
|
42
42
|
- Avoid shared global state or reset it explicitly.
|
package/dist/assets/release.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": 1,
|
|
3
3
|
"npmPackage": "@ccoalm/ccl-skills",
|
|
4
|
-
"version": "0.
|
|
5
|
-
"sourceCommit": "
|
|
4
|
+
"version": "0.3.0",
|
|
5
|
+
"sourceCommit": "0e8a42aee6ffd691679245331af0ad346baf4fdc",
|
|
6
6
|
"sourceState": "clean",
|
|
7
7
|
"files": [
|
|
8
8
|
{
|
|
@@ -407,7 +407,7 @@
|
|
|
407
407
|
},
|
|
408
408
|
{
|
|
409
409
|
"path": "marketplace/plugins/ccl-skills/skills/code-review/scripts/test_init_policy_matrix.sh",
|
|
410
|
-
"sha256": "
|
|
410
|
+
"sha256": "c93b3db0e68758a71b85f6e05c2553fd64f023e038d765976778fb69435387c3",
|
|
411
411
|
"mode": 493
|
|
412
412
|
},
|
|
413
413
|
{
|
|
@@ -432,7 +432,7 @@
|
|
|
432
432
|
},
|
|
433
433
|
{
|
|
434
434
|
"path": "marketplace/plugins/ccl-skills/skills/code-review/scripts/test_parse_probe_result.sh",
|
|
435
|
-
"sha256": "
|
|
435
|
+
"sha256": "d035ef9c2cd154c4e81ae8818b1b12469f69514ad6e8d01b53f620387c568774",
|
|
436
436
|
"mode": 493
|
|
437
437
|
},
|
|
438
438
|
{
|
|
@@ -450,9 +450,14 @@
|
|
|
450
450
|
"sha256": "18b61e5f43921ebf7c36b059afb8de948c3d174990c3707d5c37a01cee2f5884",
|
|
451
451
|
"mode": 493
|
|
452
452
|
},
|
|
453
|
+
{
|
|
454
|
+
"path": "marketplace/plugins/ccl-skills/skills/code-review/scripts/test_review_gate_abort_leak.sh",
|
|
455
|
+
"sha256": "9434aa303e93754ef5a8dfdaf6453bab86f0c253eb787b80fecc00b5f7b3e984",
|
|
456
|
+
"mode": 493
|
|
457
|
+
},
|
|
453
458
|
{
|
|
454
459
|
"path": "marketplace/plugins/ccl-skills/skills/code-review/scripts/test_review_gate.sh",
|
|
455
|
-
"sha256": "
|
|
460
|
+
"sha256": "6659beaca736d91c9498157766b3d90ce1cbdff828d12fb91b4fff17b9857166",
|
|
456
461
|
"mode": 493
|
|
457
462
|
},
|
|
458
463
|
{
|
|
@@ -902,7 +907,7 @@
|
|
|
902
907
|
},
|
|
903
908
|
{
|
|
904
909
|
"path": "marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/model-prompt-evaluation.md",
|
|
905
|
-
"sha256": "
|
|
910
|
+
"sha256": "8c1a38ed0e4007fdc1912046680ed146d762a15a6c3d8eef98f1c26ceb1d3547",
|
|
906
911
|
"mode": 420
|
|
907
912
|
},
|
|
908
913
|
{
|
|
@@ -1452,7 +1457,7 @@
|
|
|
1452
1457
|
},
|
|
1453
1458
|
{
|
|
1454
1459
|
"path": "marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/external-ui-ux-quality-benchmarks.md",
|
|
1455
|
-
"sha256": "
|
|
1460
|
+
"sha256": "a226dad35b1ef81e74c7f4295bcc4b03153577339c04a6a01486ebcce23b15b6",
|
|
1456
1461
|
"mode": 420
|
|
1457
1462
|
},
|
|
1458
1463
|
{
|
|
@@ -1532,7 +1537,7 @@
|
|
|
1532
1537
|
},
|
|
1533
1538
|
{
|
|
1534
1539
|
"path": "marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/ui-ux-audit.md",
|
|
1535
|
-
"sha256": "
|
|
1540
|
+
"sha256": "36ef05c9b24f8af566cf4200ce2ef36ad4408854a5c5fc884e9e567a2334d93d",
|
|
1536
1541
|
"mode": 420
|
|
1537
1542
|
},
|
|
1538
1543
|
{
|
|
@@ -1922,7 +1927,7 @@
|
|
|
1922
1927
|
},
|
|
1923
1928
|
{
|
|
1924
1929
|
"path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/external-practice-controls.md",
|
|
1925
|
-
"sha256": "
|
|
1930
|
+
"sha256": "703204ddcf298bf0618d777f5551649ca97fa89d4df0cefc7118b7b2396c7ace",
|
|
1926
1931
|
"mode": 420
|
|
1927
1932
|
},
|
|
1928
1933
|
{
|
|
@@ -1997,7 +2002,7 @@
|
|
|
1997
2002
|
},
|
|
1998
2003
|
{
|
|
1999
2004
|
"path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/rule-consolidation.md",
|
|
2000
|
-
"sha256": "
|
|
2005
|
+
"sha256": "adb14725a9ac36cc6d4cf24c3a518e3a2301e2cf7495067b017844b15624884e",
|
|
2001
2006
|
"mode": 420
|
|
2002
2007
|
},
|
|
2003
2008
|
{
|
|
@@ -2007,12 +2012,12 @@
|
|
|
2007
2012
|
},
|
|
2008
2013
|
{
|
|
2009
2014
|
"path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/source-register.md",
|
|
2010
|
-
"sha256": "
|
|
2015
|
+
"sha256": "b028098c3d5fdcdb49b6e26fde4a162f958fa236085532e8975e4e7ce2e7de14",
|
|
2011
2016
|
"mode": 420
|
|
2012
2017
|
},
|
|
2013
2018
|
{
|
|
2014
2019
|
"path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/source-to-skill-extraction.md",
|
|
2015
|
-
"sha256": "
|
|
2020
|
+
"sha256": "1c4c99821e26a36a3b82a6194dc82997ce509f50f03f963b7db5a5126e2c5e21",
|
|
2016
2021
|
"mode": 420
|
|
2017
2022
|
},
|
|
2018
2023
|
{
|
|
@@ -2097,12 +2102,12 @@
|
|
|
2097
2102
|
},
|
|
2098
2103
|
{
|
|
2099
2104
|
"path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/impact-chain-gate.rb",
|
|
2100
|
-
"sha256": "
|
|
2105
|
+
"sha256": "f15d8b1d1932589e981ad1c104e73bfb9e057f61e5ceae60c3a75004422b7ae9",
|
|
2101
2106
|
"mode": 493
|
|
2102
2107
|
},
|
|
2103
2108
|
{
|
|
2104
2109
|
"path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/register-firing-path-resolution.rb",
|
|
2105
|
-
"sha256": "
|
|
2110
|
+
"sha256": "36da0a9c3b2065f743f25796c0539b93663cfbf84e0106be974c6d66121ce54a",
|
|
2106
2111
|
"mode": 493
|
|
2107
2112
|
},
|
|
2108
2113
|
{
|
|
@@ -2142,7 +2147,7 @@
|
|
|
2142
2147
|
},
|
|
2143
2148
|
{
|
|
2144
2149
|
"path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_ccl_regressions.sh",
|
|
2145
|
-
"sha256": "
|
|
2150
|
+
"sha256": "c6ff1fe420383ec343281678a96ba9b7b2905c8946ea6cd145a7c38da0ff28f2",
|
|
2146
2151
|
"mode": 493
|
|
2147
2152
|
},
|
|
2148
2153
|
{
|
|
@@ -2157,7 +2162,7 @@
|
|
|
2157
2162
|
},
|
|
2158
2163
|
{
|
|
2159
2164
|
"path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_ccl_skill_catalog.sh",
|
|
2160
|
-
"sha256": "
|
|
2165
|
+
"sha256": "a4dfa305d4aa9be5cd64cadae1a71169ec7024a20d202ca451378cebb043a599",
|
|
2161
2166
|
"mode": 493
|
|
2162
2167
|
},
|
|
2163
2168
|
{
|
|
@@ -2215,6 +2220,21 @@
|
|
|
2215
2220
|
"sha256": "493443e08b635ac1acd47339fcd0fe966646374e4224baa68a99f46dba932ae1",
|
|
2216
2221
|
"mode": 493
|
|
2217
2222
|
},
|
|
2223
|
+
{
|
|
2224
|
+
"path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_impact_chain_gate_verdict_differential.sh",
|
|
2225
|
+
"sha256": "3c6d27086a7c0d97b636f09faef811ed7d1a53806dbcce21de69707cc6f3dc0a",
|
|
2226
|
+
"mode": 493
|
|
2227
|
+
},
|
|
2228
|
+
{
|
|
2229
|
+
"path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_impact_chain_round_attribution.sh",
|
|
2230
|
+
"sha256": "a8e9bc8a8d60dae6c037c8fa760d15b5a0633e575a9831b9ab11235f3ca12da3",
|
|
2231
|
+
"mode": 493
|
|
2232
|
+
},
|
|
2233
|
+
{
|
|
2234
|
+
"path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_impact_chain_source_refuted.sh",
|
|
2235
|
+
"sha256": "e52069f1ab54e431d62db309c752ded5d7d148e221900a201235ef879e8d3af5",
|
|
2236
|
+
"mode": 493
|
|
2237
|
+
},
|
|
2218
2238
|
{
|
|
2219
2239
|
"path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_register_firing_path_resolution.sh",
|
|
2220
2240
|
"sha256": "4894f739af0b3aa995243592d71ca3f93de3108a11f9734422a4f15c2ca33668",
|
|
@@ -2225,6 +2245,11 @@
|
|
|
2225
2245
|
"sha256": "2be264f3dc5291eb51c0512b3ca1f85a74ed8a869b5ae0bac4b0468a195e207f",
|
|
2226
2246
|
"mode": 493
|
|
2227
2247
|
},
|
|
2248
|
+
{
|
|
2249
|
+
"path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_regression_runner_lanes.sh",
|
|
2250
|
+
"sha256": "dd9ce18143e2cce5722c30396d0f8f06f896aa2787ca1f3cb0600233f31b272b",
|
|
2251
|
+
"mode": 493
|
|
2252
|
+
},
|
|
2228
2253
|
{
|
|
2229
2254
|
"path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_regression_runner_registration.sh",
|
|
2230
2255
|
"sha256": "79159a98cf1ca73054d45b2c6f5d8707641477ba930d87a9c3486e419cbcac9b",
|
|
@@ -2252,7 +2277,7 @@
|
|
|
2252
2277
|
},
|
|
2253
2278
|
{
|
|
2254
2279
|
"path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_validate_skill_root_depth.sh",
|
|
2255
|
-
"sha256": "
|
|
2280
|
+
"sha256": "1261c93b9049dd02120b45ce93284cb30af1c90cfc7da9a4c7ec9cd421ce9de4",
|
|
2256
2281
|
"mode": 493
|
|
2257
2282
|
},
|
|
2258
2283
|
{
|
|
@@ -2262,7 +2287,7 @@
|
|
|
2262
2287
|
},
|
|
2263
2288
|
{
|
|
2264
2289
|
"path": "marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/SKILL.md",
|
|
2265
|
-
"sha256": "
|
|
2290
|
+
"sha256": "081a7d21813d00a462f2c77c53923edf60cd6f740138d6c028b84ea4675c1aeb",
|
|
2266
2291
|
"mode": 420
|
|
2267
2292
|
},
|
|
2268
2293
|
{
|
|
@@ -2412,7 +2437,7 @@
|
|
|
2412
2437
|
},
|
|
2413
2438
|
{
|
|
2414
2439
|
"path": "marketplace/plugins/ccl-skills/skills/testing-strategy/references/ci-fixtures-and-flake-control.md",
|
|
2415
|
-
"sha256": "
|
|
2440
|
+
"sha256": "f35c12479559a56701338e715101a7a5eccba1f2ccbcee4827e9696def8cfc33",
|
|
2416
2441
|
"mode": 420
|
|
2417
2442
|
},
|
|
2418
2443
|
{
|
|
@@ -2694,7 +2719,7 @@
|
|
|
2694
2719
|
},
|
|
2695
2720
|
{
|
|
2696
2721
|
"path": "cli.js",
|
|
2697
|
-
"sha256": "
|
|
2722
|
+
"sha256": "5b5ab7f39b7faa81ea209b3e479295da64f2a834969ee5ac8d76354a182c2822",
|
|
2698
2723
|
"mode": 493
|
|
2699
2724
|
},
|
|
2700
2725
|
{
|
|
@@ -2787,6 +2812,26 @@
|
|
|
2787
2812
|
"sha256": "2aeabe2364755dc91d7058bf3e3b8e2bb4086a0392da6b8f87a3892879334915",
|
|
2788
2813
|
"mode": 420
|
|
2789
2814
|
},
|
|
2815
|
+
{
|
|
2816
|
+
"path": "update-notice.d.ts",
|
|
2817
|
+
"sha256": "2caf9b8512c1969c4ecdb31e90de0265ef435b70a9bcca07f649d5055d63c6ab",
|
|
2818
|
+
"mode": 420
|
|
2819
|
+
},
|
|
2820
|
+
{
|
|
2821
|
+
"path": "update-notice.js",
|
|
2822
|
+
"sha256": "da5ceca856f4492afd38010918d4c33c5f8dfc04d490bbf84ff955a8e12f7245",
|
|
2823
|
+
"mode": 420
|
|
2824
|
+
},
|
|
2825
|
+
{
|
|
2826
|
+
"path": "version-check.d.ts",
|
|
2827
|
+
"sha256": "43e818adf60173644896298637f47b01d5819b17eda46eaa32d0c7d64724d012",
|
|
2828
|
+
"mode": 420
|
|
2829
|
+
},
|
|
2830
|
+
{
|
|
2831
|
+
"path": "version-check.js",
|
|
2832
|
+
"sha256": "bd6babcff7eb222ce39f8ed4d8945f55f4004f45d17600fee497ee64357099da",
|
|
2833
|
+
"mode": 420
|
|
2834
|
+
},
|
|
2790
2835
|
{
|
|
2791
2836
|
"path": "version.d.ts",
|
|
2792
2837
|
"sha256": "edc6c24c912373b1ffc68f7b261f2e04d616b0486e9ab2401d1201f094c5a885",
|
|
@@ -2798,5 +2843,5 @@
|
|
|
2798
2843
|
"mode": 420
|
|
2799
2844
|
}
|
|
2800
2845
|
],
|
|
2801
|
-
"snapshotHash": "
|
|
2846
|
+
"snapshotHash": "f339a0ca319bb93956aebf42d2f63143ae37de54484398b0a3f87af313064436"
|
|
2802
2847
|
}
|
package/dist/cli.js
CHANGED
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
import { readFileSync, realpathSync } from "node:fs";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { Worker } from "node:worker_threads";
|
|
5
|
-
import { spawnSync } from "node:child_process";
|
|
5
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
6
|
+
import { paths } from "./paths.js";
|
|
7
|
+
import { cachePath, emitNotice } from "./update-notice.js";
|
|
6
8
|
const pkg = JSON.parse(readFileSync(fileURLToPath(new URL("../package.json", import.meta.url)), "utf8"));
|
|
7
|
-
const HELP = `ccl-skills — npm snapshot installer for Claude Code, Codex, and OpenCode\n\nUsage:\n ccl-skills install [--host claude|codex|opencode] [--json]\n ccl-skills update [--host claude|codex|opencode] [--yes] [--allow-downgrade] [--json]\n ccl-skills doctor [--host claude|codex|opencode] [--json]\n ccl-skills uninstall [--host claude|codex|opencode] [--yes] [--json]\n\nWithout --host, every installed or package-owned host is selected.\nUpdate and uninstall are dry-run unless --yes is supplied.\nBy default update --yes upgrades the global npm package to @latest before refreshing assets.\nSet CCL_SKILLS_SKIP_SELF_UPDATE=1 for an assets-only refresh; --allow-downgrade always uses the invoked package without installing @latest first.`;
|
|
9
|
+
const HELP = `ccl-skills — npm snapshot installer for Claude Code, Codex, and OpenCode\n\nUsage:\n ccl-skills install [--host claude|codex|opencode] [--json]\n ccl-skills update [--host claude|codex|opencode] [--yes] [--allow-downgrade] [--json]\n ccl-skills doctor [--host claude|codex|opencode] [--json]\n ccl-skills uninstall [--host claude|codex|opencode] [--yes] [--json]\n\nWithout --host, every installed or package-owned host is selected.\nUpdate and uninstall are dry-run unless --yes is supplied.\nBy default update --yes upgrades the global npm package to @latest before refreshing assets.\nSet CCL_SKILLS_SKIP_SELF_UPDATE=1 for an assets-only refresh; --allow-downgrade always uses the invoked package without installing @latest first.\n\nAn interactive run prints an update notice on stderr at most once a day.\nSet CCL_SKILLS_NO_UPDATE_NOTIFIER=1 (or NO_UPDATE_NOTIFIER) to silence it; it is\nalready silent under --json, in CI, and when output is not a terminal.`;
|
|
8
10
|
export function parseArgs(args) {
|
|
9
11
|
if (!args.length ||
|
|
10
12
|
args.includes("--help") ||
|
|
@@ -164,10 +166,28 @@ function selfUpdate(options) {
|
|
|
164
166
|
return { code: 5, status: "package-updated-assets-unknown", message: "npm package updated, but the fresh CLI returned an invalid result" };
|
|
165
167
|
}
|
|
166
168
|
}
|
|
169
|
+
/** Secondary guidance chrome. It is handed a stderr writer only, runs after the
|
|
170
|
+
* command's own output, and schedules its registry check in a detached child,
|
|
171
|
+
* so it can neither reach stdout nor add latency to this invocation. */
|
|
172
|
+
function notifyUpdate(json) {
|
|
173
|
+
emitNotice({
|
|
174
|
+
current: pkg.version,
|
|
175
|
+
now: Date.now(),
|
|
176
|
+
env: process.env,
|
|
177
|
+
stdoutTTY: !!process.stdout.isTTY,
|
|
178
|
+
stderrTTY: !!process.stderr.isTTY,
|
|
179
|
+
columns: process.stdout.columns,
|
|
180
|
+
json,
|
|
181
|
+
}, cachePath(paths().root), {
|
|
182
|
+
stderr: (text) => write(process.stderr, text),
|
|
183
|
+
spawnCheck: () => spawn(process.execPath, [fileURLToPath(new URL("./version-check.js", import.meta.url))], { detached: true, stdio: "ignore" }).unref(),
|
|
184
|
+
});
|
|
185
|
+
}
|
|
167
186
|
export async function main(args) {
|
|
168
187
|
const parsed = parseArgs(args);
|
|
169
188
|
if (parsed.direct) {
|
|
170
189
|
write(parsed.direct.stream === "stdout" ? process.stdout : process.stderr, parsed.direct.text);
|
|
190
|
+
notifyUpdate(false);
|
|
171
191
|
return parsed.direct.code;
|
|
172
192
|
}
|
|
173
193
|
const shouldSelfUpdate = parsed.command === "update" && parsed.options.yes && !parsed.options.allowDowngrade && process.env.CCL_SKILLS_SKIP_SELF_UPDATE !== "1";
|
|
@@ -184,6 +204,7 @@ export async function main(args) {
|
|
|
184
204
|
write(process.stdout, parsed.json
|
|
185
205
|
? JSON.stringify(result)
|
|
186
206
|
: `${result.status}: ${result.message}${result.plan ? `\n${result.plan.map((x) => `- ${x}`).join("\n")}` : ""}`);
|
|
207
|
+
notifyUpdate(!!parsed.json);
|
|
187
208
|
return result.code;
|
|
188
209
|
}
|
|
189
210
|
export function isDirectEntrypoint(importMetaUrl, argv1) {
|