Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,63 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [6.51.1] - 2026-05-20

Hotfix: the install-time skills picker hardcoded a 24-skill list in
`scripts/lib/skills.sh:SKILLS_CATALOG`, so the 38 marketing skills added
in v6.51.0 + the humanizer skill added in v6.50.0 were INVISIBLE to the
TUI even though they were correctly mirrored under
`templates/skills-marketplace/` and registered in
`manifest.json:skills_pins` + `templates/skills-catalog.json`.

User-reported regression — the install picker on a fresh project showed
only the legacy 24 skills, missing all 39 net-new skills from the past
two ships.

### Fixed

- **`scripts/lib/skills.sh:SKILLS_CATALOG`** — expanded from 24 names to
63 (62 mirrored skills + `impeccable` npm-installed special case). The
array now matches `manifest.json:files.skills_marketplace` 1:1, plus
the `impeccable` entry that lives outside the mirror by design.
- Updated SKILLS_CATALOG header comment from "24-skill catalog —
SKILL-01 source of truth" to a description of the actual contract
(mirror dirs + impeccable npm special-case). The vestigial
`REQUIREMENTS.md SKILL-01` reference was already dead (no such file).
- Updated docstring on `skills_catalog_names()` and the variable docs at
the top of the file — no more "24" hardcoded references.

### Why this slipped

The previous 3 ships (v6.49.0, v6.50.0, v6.51.0) updated:

- `manifest.json:skills_pins` (62 entries)
- `manifest.json:files.skills_marketplace` (62 entries)
- `templates/skills-catalog.json` (61 + memo-skill = 62)
- mirror dirs under `templates/skills-marketplace/`

… but did NOT update `SKILLS_CATALOG` in `scripts/lib/skills.sh`. That
array is what `scripts/install.sh` reads when building the TUI checklist
— it is the single source of truth for picker visibility, separate from
the manifest/catalog files. The drift was silent because `make check`
does not enforce SKILLS_CATALOG ↔ manifest consistency.

### Memory correction

The v6.51.0 CHANGELOG + topic file claimed `ab-test-setup` was retained
from the mysticaltech fork "under a distinct name." Re-audit of
`manifest.json:skills_pins` shows `ab-test-setup` was never pinned —
only `analytics-tracking` was kept from mysticaltech. The
`ab-test-setup` claim was a documentation hallucination. The
SKILLS_CATALOG fix in this release does NOT add `ab-test-setup`
because no mirror dir exists for it.

### Follow-up

A future release should add a `make check` gate that compares
`SKILLS_CATALOG` against `manifest.json:files.skills_marketplace` to
prevent recurrence. Tracked as deferred work.

## [6.51.0] - 2026-05-20

Bulk skills-marketplace expansion: 40 marketing skills from the canonical
Expand Down
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"manifest_version": 2,
"version": "6.51.0",
"version": "6.51.1",
"updated": "2026-05-20",
"build_date": "2026-05-20",
"description": "Claude Code Toolkit manifest for smart updates",
Expand Down
2 changes: 1 addition & 1 deletion scripts/init-claude.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ NC='\033[0m'
# `raw.githubusercontent.com/.../v6.24.5/.../init-claude.sh`), leave
# TK_TOOLKIT_REF unset and it inherits the bundled default below —
# guaranteeing every file in the install comes from the same tag.
TK_TOOLKIT_REF="${TK_TOOLKIT_REF:-v6.51.0}"
TK_TOOLKIT_REF="${TK_TOOLKIT_REF:-v6.51.1}"
# Audit INF-MED-2 (2026-04-30 deep): allowlist guard — TK_TOOLKIT_REF flows
# raw into curl URLs. Reject anything outside the tag/SHA charset, plus any
# `..` traversal sequence. Tags / branches / SHAs do not contain `..`.
Expand Down
2 changes: 1 addition & 1 deletion scripts/install-statusline.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ done
: "${YES}" # silence shellcheck SC2034 — no-op stub today

# Audit H5: TK_TOOLKIT_REF pins to a tag/SHA (default `main`).
TK_TOOLKIT_REF="${TK_TOOLKIT_REF:-v6.51.0}"
TK_TOOLKIT_REF="${TK_TOOLKIT_REF:-v6.51.1}"
# Audit INF-MED-2 (2026-04-30 deep): allowlist guard — TK_TOOLKIT_REF flows
# raw into curl URLs. Reject anything outside the tag/SHA charset, plus any
# `..` traversal sequence. Tags / branches / SHAs do not contain `..`.
Expand Down
4 changes: 2 additions & 2 deletions scripts/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export TK_TOOLKIT_REF TK_USER_AGENT
# Config
# Audit H5: TK_TOOLKIT_REF pins to a tag/SHA (default `main`); TK_REPO_URL
# remains the highest-priority override (full URL with ref baked in).
TK_TOOLKIT_REF="${TK_TOOLKIT_REF:-v6.51.0}"
TK_TOOLKIT_REF="${TK_TOOLKIT_REF:-v6.51.1}"
# Audit INF-MED-2 (2026-04-30 deep): allowlist guard — TK_TOOLKIT_REF flows
# raw into curl URLs. Reject anything outside the tag/SHA charset, plus any
# `..` traversal sequence. Tags / branches / SHAs do not contain `..`.
Expand Down Expand Up @@ -1279,7 +1279,7 @@ fi
# Mirror of the --mcps branch above; reuses TUI_* globals + print_install_status.
# ─────────────────────────────────────────────────
if [[ "$SKILLS" -eq 1 ]]; then
# Populate TUI_INSTALLED[] from the 24-skill catalog.
# Populate TUI_INSTALLED[] from SKILLS_CATALOG (sourced from scripts/lib/skills.sh).
skills_status_array

# Build TUI globals from SKILLS_CATALOG.
Expand Down
52 changes: 47 additions & 5 deletions scripts/lib/skills.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
# Claude Code Toolkit — Skills Catalog Loader + Detection + Install Helper (v4.5+)
# Source this file. Do NOT execute it directly.
# Exposes:
# skills_catalog_names — prints 24 skill names one-per-line (alpha sorted)
# skills_catalog_names — prints all catalog skill names one-per-line (alpha sorted)
# is_skill_installed <name> — returns 0 (installed) / 1 (not installed)
# skills_status_array — populates TUI_INSTALLED[] for install.sh --skills branch
# skills_install <name> [--force] — copies skill from mirror to target via cp -R
# Globals (write):
# SKILLS_CATALOG[] — 24 curated skill names (alpha order); populated at source time
# SKILLS_CATALOG[] — curated skill names (alpha order); populated at source time
# TUI_INSTALLED[] — populated by skills_status_array (parallel to SKILLS_CATALOG)
# Test seams:
# TK_SKILLS_HOME — override $HOME/.claude/skills/ probe path (used by is_skill_installed)
Expand All @@ -31,33 +31,75 @@
# shellcheck disable=SC2034
[[ -z "${NC:-}" ]] && NC='\033[0m'

# Curated 24-skill catalog — SKILL-01 source of truth.
# Alphabetical order. Do NOT add or remove without updating REQUIREMENTS.md SKILL-01.
# Curated skills catalog — must stay in sync with manifest.json:files.skills_marketplace.
# Alphabetical order. impeccable is an npm-installed skill (special-cased in
# _skills_description below) — not vendored under templates/skills-marketplace/.
# All other names map to a templates/skills-marketplace/<name>/ mirror dir.
# Total: 63 (62 mirrored skills + impeccable).
# shellcheck disable=SC2034
SKILLS_CATALOG=(
ab-testing
ad-creative
ads
ai-models
ai-seo
analytics
analytics-tracking
aso
chrome-extension-development
churn-prevention
co-marketing
cold-email
community-marketing
competitor-profiling
competitors
content-strategy
copy-editing
copywriting
cro
customer-research
directory-submissions
docx
emails
find-skills
firecrawl
free-tools
huashu-design
humanizer
i18n-localization
image
impeccable
launch
lead-magnets
marketing-ideas
marketing-psychology
memo-skill
next-best-practices
notebooklm
onboarding
paywalls
pdf
popups
pricing
product-marketing
programmatic-seo
referrals
resend
revops
sales-enablement
schema
seo-audit
shadcn
signup
site-architecture
social
stripe-best-practices
tailwind-design-system
typescript-advanced-types
ui-ux-pro-max
vercel-composition-patterns
vercel-react-best-practices
video
webapp-testing
)

Expand All @@ -74,7 +116,7 @@ _skills_default_mirror_path() {
echo "${TK_SKILLS_MIRROR_PATH:-${d}/../../templates/skills-marketplace}"
}

# skills_catalog_names — print all 24 skill names from SKILLS_CATALOG, one per line.
# skills_catalog_names — print all skill names from SKILLS_CATALOG, one per line.
skills_catalog_names() {
printf '%s\n' "${SKILLS_CATALOG[@]}"
}
Expand Down
2 changes: 1 addition & 1 deletion scripts/migrate-to-complement.sh
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ CYAN='\033[0;36m'
NC='\033[0m'

# Audit H5: TK_TOOLKIT_REF pins to a tag/SHA (default `main`).
TK_TOOLKIT_REF="${TK_TOOLKIT_REF:-v6.51.0}"
TK_TOOLKIT_REF="${TK_TOOLKIT_REF:-v6.51.1}"
# Audit INF-MED-2 (2026-04-30 deep): allowlist guard — TK_TOOLKIT_REF flows
# raw into curl URLs. Reject anything outside the tag/SHA charset, plus any
# `..` traversal sequence. Tags / branches / SHAs do not contain `..`.
Expand Down
2 changes: 1 addition & 1 deletion scripts/setup-council.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ CYAN='\033[0;36m'
NC='\033[0m'

# Audit H5: TK_TOOLKIT_REF pins to a tag/SHA (default `main`).
TK_TOOLKIT_REF="${TK_TOOLKIT_REF:-v6.51.0}"
TK_TOOLKIT_REF="${TK_TOOLKIT_REF:-v6.51.1}"
# Audit INF-MED-2 (2026-04-30 deep): allowlist guard — TK_TOOLKIT_REF flows
# raw into curl URLs. Reject anything outside the tag/SHA charset, plus any
# `..` traversal sequence. Tags / branches / SHAs do not contain `..`.
Expand Down
2 changes: 1 addition & 1 deletion scripts/setup-prompt-engineer.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ NC='\033[0m'

# TK_TOOLKIT_REF pins to a tag/SHA (default `main`). Mirrors setup-council.sh
# to keep allowlist + curl conventions identical.
TK_TOOLKIT_REF="${TK_TOOLKIT_REF:-v6.51.0}"
TK_TOOLKIT_REF="${TK_TOOLKIT_REF:-v6.51.1}"
if ! [[ "$TK_TOOLKIT_REF" =~ ^[A-Za-z0-9._/-]+$ ]] || [[ "$TK_TOOLKIT_REF" == *..* ]]; then
echo "Error: TK_TOOLKIT_REF must match [A-Za-z0-9._/-]+ and must not contain '..' (got: $TK_TOOLKIT_REF)" >&2
exit 1
Expand Down
2 changes: 1 addition & 1 deletion scripts/setup-security.sh
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ done
: "${YES}" # silence shellcheck SC2034 — YES consumed by future read blocks

# Audit H5: TK_TOOLKIT_REF pins to a tag/SHA (default `main`).
TK_TOOLKIT_REF="${TK_TOOLKIT_REF:-v6.51.0}"
TK_TOOLKIT_REF="${TK_TOOLKIT_REF:-v6.51.1}"
# Audit INF-MED-2 (2026-04-30 deep): allowlist guard — TK_TOOLKIT_REF flows
# raw into curl URLs. Reject anything outside the tag/SHA charset, plus any
# `..` traversal sequence. Tags / branches / SHAs do not contain `..`.
Expand Down
20 changes: 10 additions & 10 deletions scripts/tests/test-install-skills.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@
# test-install-skills.sh — Phase 26 hermetic integration test.
#
# Scenarios (target ≥12 assertions across 6 scenarios):
# S1_catalog_correctness — SKILLS_CATALOG has 24 entries; alphabetical order
# S1_catalog_correctness — SKILLS_CATALOG has 63 entries; alphabetical order
# S2_detection_two_state — is_skill_installed returns 0 (installed) / 1 (not installed)
# S3_skills_install_basic — skills_install copies one skill from mirror to TK_SKILLS_HOME via cp -R
# S4_idempotency_no_force — re-running skills_install on installed skill returns rc=2 (refused, no overwrite)
# S5_force_overwrite — skills_install --force on installed skill returns rc=0 (overwritten)
# S6_install_sh_dry_run — install.sh --skills --yes --dry-run produces 24 would-install rows; zero filesystem mutations
# S6_install_sh_dry_run — install.sh --skills --yes --dry-run produces 63 would-install rows; zero filesystem mutations
#
# Test seam env vars: TK_SKILLS_HOME, TK_SKILLS_MIRROR_PATH, TK_TUI_TTY_SRC
#
# Sample skills used in scenarios (3 of 24, per CONTEXT.md test strategy):
# Sample skills used in scenarios (3 of 63, per CONTEXT.md test strategy):
# ai-models, pdf, tailwind-design-system
#
# Usage: bash scripts/tests/test-install-skills.sh
Expand Down Expand Up @@ -59,17 +59,17 @@ echo "test-install-skills.sh: SKILL-03..05 hermetic suite"
echo ""

# ─────────────────────────────────────────────────
# S1_catalog_correctness — SKILLS_CATALOG has 24 entries; alphabetical order
# S1_catalog_correctness — SKILLS_CATALOG has 63 entries; alphabetical order
# SKILL-01
# ─────────────────────────────────────────────────
run_s1_catalog_correctness() {
echo " -- S1_catalog_correctness: 24 entries, alphabetical order, last is webapp-testing --"
echo " -- S1_catalog_correctness: 63 entries, alphabetical order, first ab-testing, last webapp-testing --"
SKILLS_CATALOG=()
# shellcheck source=/dev/null
source "${REPO_ROOT}/scripts/lib/skills.sh"
assert_eq "24" "${#SKILLS_CATALOG[@]}" "S1: catalog contains 24 entries"
assert_eq "ai-models" "${SKILLS_CATALOG[0]}" "S1: alphabetical first entry is ai-models"
assert_eq "webapp-testing" "${SKILLS_CATALOG[23]}" "S1: alphabetical last entry is webapp-testing"
assert_eq "63" "${#SKILLS_CATALOG[@]}" "S1: catalog contains 63 entries"
assert_eq "ab-testing" "${SKILLS_CATALOG[0]}" "S1: alphabetical first entry is ab-testing"
assert_eq "webapp-testing" "${SKILLS_CATALOG[62]}" "S1: alphabetical last entry is webapp-testing"
}

# ─────────────────────────────────────────────────
Expand Down Expand Up @@ -289,7 +289,7 @@ run_s5_force_overwrite() {
}

# ─────────────────────────────────────────────────
# S6_install_sh_dry_run — --skills --yes --dry-run: 24 would-install rows, zero mutations (SKILL-05)
# S6_install_sh_dry_run — --skills --yes --dry-run: 63 would-install rows, zero mutations (SKILL-05)
# ─────────────────────────────────────────────────
run_s6_install_sh_dry_run() {
local SANDBOX
Expand All @@ -313,7 +313,7 @@ run_s6_install_sh_dry_run() {

local would_count
would_count=$(printf '%s\n' "$output" | grep -c "would-install" || true)
assert_eq "24" "$would_count" "S6: dry-run prints 24 would-install rows"
assert_eq "63" "$would_count" "S6: dry-run prints 63 would-install rows"

# Zero filesystem mutations: SKILLS_HOME should still be empty.
local file_count
Expand Down
2 changes: 1 addition & 1 deletion scripts/uninstall.sh
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ fi

# ───────── constants + log helpers ─────────
# Audit H5: TK_TOOLKIT_REF pins to a tag/SHA (default `main`).
TK_TOOLKIT_REF="${TK_TOOLKIT_REF:-v6.51.0}"
TK_TOOLKIT_REF="${TK_TOOLKIT_REF:-v6.51.1}"
# Audit INF-MED-2 (2026-04-30 deep): allowlist guard — TK_TOOLKIT_REF flows
# raw into curl URLs. Reject anything outside the tag/SHA charset, plus any
# `..` traversal sequence. Tags / branches / SHAs do not contain `..`.
Expand Down
2 changes: 1 addition & 1 deletion scripts/update-claude.sh
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ CYAN='\033[0;36m'
NC='\033[0m'

# Audit H5: TK_TOOLKIT_REF pins to a tag/SHA (default `main`).
TK_TOOLKIT_REF="${TK_TOOLKIT_REF:-v6.51.0}"
TK_TOOLKIT_REF="${TK_TOOLKIT_REF:-v6.51.1}"
# Audit INF-MED-2 (2026-04-30 deep): allowlist guard — TK_TOOLKIT_REF flows
# raw into curl URLs. Reject anything outside the tag/SHA charset, plus any
# `..` traversal sequence. Tags / branches / SHAs do not contain `..`.
Expand Down
Loading