feat(ctx7): coverage extension — fast-libs single source + reminder hook + executor briefs (BDR-078)
- lib/fast-libs.sh: detect/cache-status verbs, JS+Python manifests, 7-day cache freshness, LC_ALL=C sort — replaces 3 hardcoded lists (ship-feature 0c, init-project 5c, onboard 3.5) - hooks/ctx7-reminder.sh: once-per-session UserPromptSubmit nudge when the project carries fast-libs and .ctx7-cache/ is missing/stale - find-docs: before-writing-code trigger + cache-first rule; dist is machine-owned (gitignored) so the durable patch lives in install-plugins.sh STEP ctx7 (idempotent, grep-guarded) - feater/bugfixer briefs: fast-lib docs rule (fresh cache read, else 2-topic ctx7 fetch, else NOTES cache miss + proceed) - tests: lib/tests/fast-libs.test.sh (11 checks); shellcheck + full make test green (review-guards 5/0)
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env bash
|
||||
# fast-libs.sh — single source of truth for "fast-moving library" detection.
|
||||
#
|
||||
# Fast-moving = API churns faster than model training data (React, Next.js,
|
||||
# Prisma…) → consult ctx7 (find-docs) before coding against it. Stable techs
|
||||
# (C, C++98, POSIX sh, SQL…) never match: no ctx7 needed (BDR-078).
|
||||
#
|
||||
# Consumers: hooks/ctx7-reminder.sh, /ship-feature STEP 0c, /init-project
|
||||
# STEP 5c, /onboard STEP 3.5, feater/bugfixer executor briefs.
|
||||
#
|
||||
# Verbs:
|
||||
# fast-libs.sh detect [dir] detected libs, one/line; exit 1 if none
|
||||
# fast-libs.sh cache-status [dir] fresh|stale|missing; exit 0 only if fresh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Exact npm dependency keys (unscoped). Anchored full-key match — "react"
|
||||
# must not drag react-icons along.
|
||||
NPM_EXACT='next|react|react-dom|react-native|expo|prisma|supabase'
|
||||
NPM_EXACT+='|drizzle-orm|astro|svelte|vue|nuxt|tailwindcss|vite|next-auth'
|
||||
NPM_EXACT+='|motion|framer-motion|ai|openai|langchain|remix|fastify'
|
||||
# Scoped npm orgs (@org/…).
|
||||
NPM_SCOPED='prisma|supabase|astrojs|sveltejs|tanstack|clerk|anthropic-ai'
|
||||
NPM_SCOPED+='|langchain|remix-run|nestjs|tailwindcss'
|
||||
# Python distributions (requirements.txt / pyproject.toml).
|
||||
PY_LIBS='fastapi|pydantic|sqlalchemy|langchain'
|
||||
|
||||
CACHE_MAX_AGE_DAYS=7
|
||||
|
||||
npm_fast_libs() { # $1=dir — matching dependency keys, one per line
|
||||
[ -f "$1/package.json" ] || return 0
|
||||
jq -r '((.dependencies // {}) + (.devDependencies // {})) | keys[]' \
|
||||
"$1/package.json" 2>/dev/null \
|
||||
| grep -E "^(${NPM_EXACT})\$|^@(${NPM_SCOPED})/" || true
|
||||
}
|
||||
|
||||
py_fast_libs() { # $1=dir — matching distributions, one per line
|
||||
grep -hoiE "\b(${PY_LIBS})\b" \
|
||||
"$1/requirements.txt" "$1/pyproject.toml" 2>/dev/null \
|
||||
| tr '[:upper:]' '[:lower:]' | LC_ALL=C sort -u || true
|
||||
}
|
||||
|
||||
detect() { # $1=dir — union, sorted unique; exit 1 when empty
|
||||
local libs
|
||||
# LC_ALL=C: deterministic order whatever the caller's locale.
|
||||
libs="$(printf '%s\n%s\n' "$(npm_fast_libs "$1")" "$(py_fast_libs "$1")" \
|
||||
| sed '/^$/d' | LC_ALL=C sort -u)"
|
||||
[ -n "$libs" ] || return 1
|
||||
printf '%s\n' "$libs"
|
||||
}
|
||||
|
||||
cache_status() { # $1=dir — fresh|stale|missing; exit 0 only when fresh
|
||||
[ -d "$1/.ctx7-cache" ] || { echo missing; return 1; }
|
||||
if [ -n "$(find "$1/.ctx7-cache" -name '*.md' \
|
||||
-mtime "-${CACHE_MAX_AGE_DAYS}" -print -quit 2>/dev/null)" ]; then
|
||||
echo fresh; return 0
|
||||
fi
|
||||
echo stale; return 1
|
||||
}
|
||||
|
||||
case "${1:-}" in
|
||||
detect) detect "${2:-.}" ;;
|
||||
cache-status) cache_status "${2:-.}" ;;
|
||||
*) echo "usage: fast-libs.sh detect|cache-status [dir]" >&2; exit 2 ;;
|
||||
esac
|
||||
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env bash
|
||||
# lib/tests/fast-libs.test.sh — fast-libs.sh verbs + ctx7-reminder hook (BDR-078)
|
||||
set -u
|
||||
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||
L="$ROOT/lib/fast-libs.sh"
|
||||
H="$ROOT/hooks/ctx7-reminder.sh"
|
||||
pass=0; fail=0
|
||||
check() { if [ "$2" = "$3" ]; then pass=$((pass+1)); else fail=$((fail+1));
|
||||
printf 'FAIL %s: got[%s] want[%s]\n' "$1" "$2" "$3"; fi; }
|
||||
|
||||
tmp="$(mktemp -d)"; trap 'rm -rf "$tmp"' EXIT
|
||||
|
||||
# --- detect: JS fast-libs matched, stable deps ignored ---
|
||||
mkdir -p "$tmp/js"
|
||||
cat > "$tmp/js/package.json" <<'EOF'
|
||||
{"dependencies":{"react":"^19","express":"^5","@tanstack/react-query":"^5"},
|
||||
"devDependencies":{"vite":"^6","lodash":"^4"}}
|
||||
EOF
|
||||
check T1-js-detect "$(bash "$L" detect "$tmp/js" | tr '\n' ' ')" \
|
||||
"@tanstack/react-query react vite "
|
||||
|
||||
# react-icons must NOT ride the react match (anchored full-key)
|
||||
mkdir -p "$tmp/near"
|
||||
printf '{"dependencies":{"react-icons":"^5","express":"^5"}}' \
|
||||
> "$tmp/near/package.json"
|
||||
check T2-near-miss "$(bash "$L" detect "$tmp/near" >/dev/null 2>&1; echo $?)" 1
|
||||
|
||||
# --- detect: python manifest + stable-tech project (exit 1) ---
|
||||
mkdir -p "$tmp/py"
|
||||
printf 'fastapi==0.115\nrequests>=2\n' > "$tmp/py/requirements.txt"
|
||||
check T3-py-detect "$(bash "$L" detect "$tmp/py")" "fastapi"
|
||||
mkdir -p "$tmp/cpp"
|
||||
check T4-none "$(bash "$L" detect "$tmp/cpp" >/dev/null 2>&1; echo $?)" 1
|
||||
|
||||
# --- cache-status: missing / fresh / stale ---
|
||||
check T5-missing "$(bash "$L" cache-status "$tmp/js" || true)" missing
|
||||
mkdir -p "$tmp/js/.ctx7-cache"; touch "$tmp/js/.ctx7-cache/react-core.md"
|
||||
check T6-fresh "$(bash "$L" cache-status "$tmp/js")" fresh
|
||||
touch -d '10 days ago' "$tmp/js/.ctx7-cache/react-core.md"
|
||||
check T7-stale "$(bash "$L" cache-status "$tmp/js" || true)" stale
|
||||
|
||||
# --- hook: fires once per session, silent on stable projects ---
|
||||
hook() { printf '{"prompt":"add a hook","session_id":"%s","cwd":"%s"}' \
|
||||
"$1" "$2" | TMPDIR="$tmp" bash "$H"; }
|
||||
check H1-fires "$(hook s1 "$tmp/js" | grep -c 'Fast-moving')" 1
|
||||
check H2-once "$(hook s1 "$tmp/js" | wc -l)" 0
|
||||
check H3-cpp-quiet "$(hook s2 "$tmp/cpp" | wc -l)" 0
|
||||
check H4-notif-quiet \
|
||||
"$(printf '{"prompt":"<task-notification>x","session_id":"s3","cwd":"%s"}' \
|
||||
"$tmp/js" | TMPDIR="$tmp" bash "$H" | wc -l)" 0
|
||||
|
||||
printf 'PASS=%s FAIL=%s\n' "$pass" "$fail"; [ "$fail" -eq 0 ]
|
||||
Reference in New Issue
Block a user