fix(pi): package warning-free skill mirror and docs
This commit is contained in:
Executable
+62
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
||||
TARGET_ROOT="${ROOT_DIR}/pi-package/skills"
|
||||
SKILL_FAMILIES=(
|
||||
"atlassian"
|
||||
"create-plan"
|
||||
"do-task"
|
||||
"implement-plan"
|
||||
"web-automation"
|
||||
)
|
||||
|
||||
extract_skill_name() {
|
||||
local skill_md=$1
|
||||
awk '/^name:/ { print $2; exit }' "$skill_md"
|
||||
}
|
||||
|
||||
replace_dir() {
|
||||
local source=$1
|
||||
local target=$2
|
||||
|
||||
if [[ -z "$target" || "$target" == "/" || "$target" == "." || "$target" == ".." ]]; then
|
||||
echo "Refusing to sync into unsafe target: $target" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$target" in
|
||||
"${ROOT_DIR}"/*) ;;
|
||||
*)
|
||||
echo "Refusing to remove target outside repo root: $target" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
rm -rf "$target"
|
||||
mkdir -p "$target"
|
||||
cp -R "${source}/." "$target/"
|
||||
}
|
||||
|
||||
rm -rf "$TARGET_ROOT"
|
||||
mkdir -p "$TARGET_ROOT"
|
||||
|
||||
for family in "${SKILL_FAMILIES[@]}"; do
|
||||
source_dir="${ROOT_DIR}/skills/${family}/pi"
|
||||
skill_md="${source_dir}/SKILL.md"
|
||||
|
||||
if [[ ! -f "$skill_md" ]]; then
|
||||
echo "Missing source SKILL.md: $skill_md" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
skill_name=$(extract_skill_name "$skill_md")
|
||||
if [[ -z "$skill_name" ]]; then
|
||||
echo "Could not derive skill name from $skill_md" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
replace_dir "$source_dir" "${TARGET_ROOT}/${skill_name}"
|
||||
done
|
||||
|
||||
echo "Synced pi package skill mirror into ${TARGET_ROOT}."
|
||||
@@ -5,6 +5,7 @@ REQUIRED_FILES=(
|
||||
"docs/PI-RESEARCH.md"
|
||||
"docs/PI.md"
|
||||
"docs/PI-SUPERPOWERS.md"
|
||||
"docs/PI-COMMON-REVIEWER.md"
|
||||
"skills/atlassian/pi/SKILL.md"
|
||||
"skills/create-plan/pi/SKILL.md"
|
||||
"skills/create-plan/pi/templates/continuation-runbook.md"
|
||||
@@ -16,6 +17,12 @@ REQUIRED_FILES=(
|
||||
"skills/web-automation/pi/SKILL.md"
|
||||
"skills/reviewer-runtime/pi/run-review.sh"
|
||||
"skills/reviewer-runtime/pi/notify-telegram.sh"
|
||||
"scripts/sync-pi-package-skills.sh"
|
||||
"pi-package/skills/atlassian/SKILL.md"
|
||||
"pi-package/skills/create-plan/SKILL.md"
|
||||
"pi-package/skills/do-task/SKILL.md"
|
||||
"pi-package/skills/implement-plan/SKILL.md"
|
||||
"pi-package/skills/web-automation/SKILL.md"
|
||||
"package.json"
|
||||
)
|
||||
|
||||
@@ -27,11 +34,35 @@ done
|
||||
|
||||
test -x skills/reviewer-runtime/pi/run-review.sh
|
||||
test -x skills/reviewer-runtime/pi/notify-telegram.sh
|
||||
test -x scripts/sync-pi-package-skills.sh
|
||||
find skills/web-automation/pi/scripts -type f -print -quit | grep -q .
|
||||
find skills/atlassian/pi/scripts -type f -print -quit | grep -q .
|
||||
|
||||
for file in skills/create-plan/pi/SKILL.md skills/do-task/pi/SKILL.md skills/implement-plan/pi/SKILL.md; do
|
||||
grep -q 'docs/PI-SUPERPOWERS.md' "$file"
|
||||
grep -q 'docs/PI-COMMON-REVIEWER.md' "$file"
|
||||
done
|
||||
|
||||
for family in atlassian create-plan do-task implement-plan web-automation; do
|
||||
source_dir="skills/${family}/pi"
|
||||
source_skill_md="${source_dir}/SKILL.md"
|
||||
skill_name=$(awk '/^name:/ { print $2; exit }' "$source_skill_md")
|
||||
mirror_dir="pi-package/skills/${skill_name}"
|
||||
mirror_skill_md="${mirror_dir}/SKILL.md"
|
||||
|
||||
test -d "$mirror_dir"
|
||||
test -f "$mirror_skill_md"
|
||||
test "$skill_name" = "$(basename "$mirror_dir")"
|
||||
test "$skill_name" = "$(awk '/^name:/ { print $2; exit }' "$mirror_skill_md")"
|
||||
|
||||
diff -qr --exclude '.DS_Store' "$source_dir" "$mirror_dir" >/dev/null
|
||||
|
||||
while IFS= read -r -d '' source_path; do
|
||||
rel_path=${source_path#"$source_dir"/}
|
||||
mirror_path="${mirror_dir}/${rel_path}"
|
||||
test -e "$mirror_path"
|
||||
test "$(stat -f '%Lp' "$source_path")" = "$(stat -f '%Lp' "$mirror_path")"
|
||||
done < <(find "$source_dir" -mindepth 1 -print0)
|
||||
done
|
||||
|
||||
! grep -nE 'update_plan|plan mode|sub-agent|subagents' \
|
||||
@@ -48,11 +79,48 @@ if (!pkg.pi || !Array.isArray(pkg.pi.skills) || pkg.pi.skills.length !== 5) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const expectedSkills = [
|
||||
"./pi-package/skills/atlassian",
|
||||
"./pi-package/skills/create-plan",
|
||||
"./pi-package/skills/do-task",
|
||||
"./pi-package/skills/implement-plan",
|
||||
"./pi-package/skills/web-automation",
|
||||
];
|
||||
|
||||
if (JSON.stringify(pkg.pi.skills) !== JSON.stringify(expectedSkills)) {
|
||||
console.error("package.json must point pi.skills at the pi-package mirror");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!Array.isArray(pkg.files) || pkg.files.length === 0) {
|
||||
console.error("package.json must define a non-empty files allowlist");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
for (const requiredFile of [
|
||||
"pi-package/skills",
|
||||
"docs/PI-COMMON-REVIEWER.md",
|
||||
"scripts/sync-pi-package-skills.sh",
|
||||
]) {
|
||||
if (!pkg.files.includes(requiredFile)) {
|
||||
console.error(`package.json files must include ${requiredFile}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
for (const forbiddenFile of [
|
||||
"skills/atlassian/pi",
|
||||
"skills/create-plan/pi",
|
||||
"skills/do-task/pi",
|
||||
"skills/implement-plan/pi",
|
||||
"skills/web-automation/pi",
|
||||
]) {
|
||||
if (pkg.files.includes(forbiddenFile)) {
|
||||
console.error(`package.json files must not include ${forbiddenFile}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Array.isArray(pkg.keywords) || !pkg.keywords.includes("pi-package")) {
|
||||
console.error("package.json must include the pi-package keyword");
|
||||
process.exit(1);
|
||||
|
||||
Reference in New Issue
Block a user