♻️ refactor(agent): streamline skills and rulesets
This commit is contained in:
@@ -293,7 +293,26 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Remove snapshot directories that were managed by an older manifest.
|
||||
# Managed snapshots are identified by their root SOURCE.md marker.
|
||||
declare -A active_snapshots=()
|
||||
while IFS=$'\x1f' read -r source_id upstream_repo upstream_ref snapshot_dir sync_mode remove_paths; do
|
||||
[ -n "$source_id" ] || continue
|
||||
active_snapshots["$snapshot_dir"]=1
|
||||
done < "$sources_file"
|
||||
|
||||
changed=0
|
||||
for source_marker in */SOURCE.md; do
|
||||
[ -f "$source_marker" ] || continue
|
||||
stale_snapshot="${source_marker%/SOURCE.md}"
|
||||
if [ -z "${active_snapshots[$stale_snapshot]:-}" ]; then
|
||||
echo "Removing orphaned third-party snapshot: $stale_snapshot"
|
||||
rm -rf -- "$stale_snapshot"
|
||||
git add -A -- "$stale_snapshot"
|
||||
changed=1
|
||||
fi
|
||||
done
|
||||
|
||||
while IFS=$'\x1f' read -r source_id upstream_repo upstream_ref snapshot_dir sync_mode remove_paths; do
|
||||
[ -n "$source_id" ] || continue
|
||||
remove_paths_md="${remove_paths//$'\x1e'/,}"
|
||||
@@ -377,8 +396,9 @@ jobs:
|
||||
echo "📌 Current $THIRDPARTY_BRANCH: $after_ref"
|
||||
|
||||
if [ "$after_ref" = "$before_ref" ]; then
|
||||
echo "✅ No thirdparty snapshot change; skip main sync."
|
||||
exit 0
|
||||
echo "✅ No thirdparty snapshot change; continue with manifest-driven main sync."
|
||||
else
|
||||
echo "📌 Updated $THIRDPARTY_BRANCH: $before_ref -> $after_ref"
|
||||
fi
|
||||
|
||||
echo "========================================"
|
||||
@@ -428,6 +448,8 @@ jobs:
|
||||
entry.get("data_dir", ""),
|
||||
entry.get("scripts_dir", ""),
|
||||
"\x1e".join(entry.get("include_skill_dirs", [])),
|
||||
entry.get("overlay_patch", ""),
|
||||
"\x1e".join(entry.get("include_paths", [])),
|
||||
]
|
||||
)
|
||||
)
|
||||
@@ -521,6 +543,96 @@ jobs:
|
||||
return 1
|
||||
}
|
||||
|
||||
apply_overlay_patch() {
|
||||
local source_id="$1"
|
||||
local patch_file="$2"
|
||||
|
||||
[ -n "$patch_file" ] || return 0
|
||||
if [ ! -f "$patch_file" ]; then
|
||||
echo "ERROR: overlay patch not found for $source_id: $patch_file" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! git apply --check "$patch_file"; then
|
||||
echo "ERROR: overlay patch no longer applies for $source_id: $patch_file" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
git apply "$patch_file"
|
||||
echo "Applied overlay patch for $source_id: $patch_file"
|
||||
}
|
||||
|
||||
copy_skill_root() {
|
||||
local snapshot_root="$1"
|
||||
local output_dir="$2"
|
||||
local include_paths="$3"
|
||||
|
||||
python3 - "$snapshot_root" "$output_dir" "$include_paths" <<'PY'
|
||||
import os
|
||||
import pathlib
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
snapshot_root = pathlib.Path(sys.argv[1]).resolve(strict=True)
|
||||
output_dir = pathlib.Path(sys.argv[2])
|
||||
raw_paths = [value for value in sys.argv[3].split("\x1e") if value]
|
||||
|
||||
if not raw_paths:
|
||||
raise SystemExit("ERROR: copy_skill_root requires include_paths")
|
||||
|
||||
sources = []
|
||||
seen = set()
|
||||
for value in raw_paths:
|
||||
relative = pathlib.PurePosixPath(value)
|
||||
if (
|
||||
relative.is_absolute()
|
||||
or not relative.parts
|
||||
or any(part in ("", ".", "..") for part in relative.parts)
|
||||
):
|
||||
raise SystemExit(f"ERROR: unsafe copy_skill_root include path: {value}")
|
||||
if value in seen:
|
||||
raise SystemExit(f"ERROR: duplicate copy_skill_root include path: {value}")
|
||||
seen.add(value)
|
||||
|
||||
source_path = snapshot_root / pathlib.Path(*relative.parts)
|
||||
if not source_path.exists():
|
||||
raise SystemExit(
|
||||
f"ERROR: copy_skill_root include path not found: {value}"
|
||||
)
|
||||
source = source_path.resolve(strict=True)
|
||||
try:
|
||||
source.relative_to(snapshot_root)
|
||||
except ValueError:
|
||||
raise SystemExit(
|
||||
f"ERROR: copy_skill_root include path escapes snapshot: {value}"
|
||||
)
|
||||
if not source.is_file() and not source.is_dir():
|
||||
raise SystemExit(
|
||||
f"ERROR: unsupported copy_skill_root source type: {value}"
|
||||
)
|
||||
sources.append((relative, source))
|
||||
|
||||
if os.path.lexists(output_dir):
|
||||
if output_dir.is_symlink() or output_dir.is_file():
|
||||
output_dir.unlink()
|
||||
else:
|
||||
shutil.rmtree(output_dir)
|
||||
output_dir.mkdir(parents=True)
|
||||
|
||||
for relative, source in sources:
|
||||
destination = output_dir.joinpath(*relative.parts)
|
||||
destination.parent.mkdir(parents=True, exist_ok=True)
|
||||
if source.is_dir():
|
||||
shutil.copytree(source, destination)
|
||||
else:
|
||||
shutil.copy2(source, destination)
|
||||
|
||||
if not (output_dir / "SKILL.md").is_file():
|
||||
raise SystemExit(
|
||||
f"ERROR: copy_skill_root output is missing SKILL.md: {output_dir}"
|
||||
)
|
||||
PY
|
||||
}
|
||||
|
||||
|
||||
cd "$REPO_DIR"
|
||||
|
||||
@@ -546,19 +658,39 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while IFS=$'\x1f' read -r source_id snapshot_dir sync_mode source_list skills_subdirs output_name platform_config template_root data_dir scripts_dir include_skill_dirs; do
|
||||
# Clean skill directories and source lists left by sources removed from
|
||||
# the manifest. Active lists are cleared below before being rewritten.
|
||||
declare -A active_source_lists=()
|
||||
while IFS=$'\x1f' read -r source_id snapshot_dir sync_mode source_list skills_subdirs output_name platform_config template_root data_dir scripts_dir include_skill_dirs overlay_patch include_paths; do
|
||||
[ -n "$source_id" ] || continue
|
||||
active_source_lists["$source_list"]=1
|
||||
done < "$sources_file"
|
||||
|
||||
for source_list in skills/thirdparty/.sources/*.list; do
|
||||
[ -f "$source_list" ] || continue
|
||||
if [ -z "${active_source_lists[$source_list]:-}" ]; then
|
||||
echo "Removing orphaned third-party source list: $source_list"
|
||||
while IFS= read -r name; do
|
||||
[ -n "$name" ] || continue
|
||||
rm -rf -- "skills/thirdparty/$name"
|
||||
done < "$source_list"
|
||||
rm -f -- "$source_list"
|
||||
fi
|
||||
done
|
||||
|
||||
while IFS=$'\x1f' read -r source_id snapshot_dir sync_mode source_list skills_subdirs output_name platform_config template_root data_dir scripts_dir include_skill_dirs overlay_patch include_paths; do
|
||||
[ -n "$source_id" ] || continue
|
||||
|
||||
if [ -f "$source_list" ]; then
|
||||
while IFS= read -r name; do
|
||||
[ -n "$name" ] || continue
|
||||
rm -rf "skills/$name"
|
||||
rm -rf "skills/thirdparty/$name"
|
||||
done < "$source_list"
|
||||
fi
|
||||
done < "$sources_file"
|
||||
|
||||
declare -A owners=()
|
||||
while IFS=$'\x1f' read -r source_id snapshot_dir sync_mode source_list skills_subdirs output_name platform_config template_root data_dir scripts_dir include_skill_dirs; do
|
||||
while IFS=$'\x1f' read -r source_id snapshot_dir sync_mode source_list skills_subdirs output_name platform_config template_root data_dir scripts_dir include_skill_dirs overlay_patch include_paths; do
|
||||
[ -n "$source_id" ] || continue
|
||||
|
||||
git archive --format=tar "origin/${THIRDPARTY_BRANCH}" "$snapshot_dir" | tar -xf - -C "$tmp_dir"
|
||||
@@ -615,12 +747,28 @@ jobs:
|
||||
names+=("$name")
|
||||
owners["$name"]="$source_id"
|
||||
;;
|
||||
copy_skill_root)
|
||||
name="$output_name"
|
||||
if [ -n "${owners[$name]:-}" ] && [ "${owners[$name]}" != "$source_id" ]; then
|
||||
echo "ERROR: duplicate third-party skill name: $name" >&2
|
||||
exit 1
|
||||
fi
|
||||
if tracked_skill_exists "$name"; then
|
||||
echo "ERROR: skill name conflict with tracked skill: $name" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
copy_skill_root "$snapshot_root" "skills/thirdparty/$name" "$include_paths"
|
||||
names+=("$name")
|
||||
owners["$name"]="$source_id"
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: unsupported sync mode: $sync_mode" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
apply_overlay_patch "$source_id" "$overlay_patch"
|
||||
printf "%s\n" "${names[@]}" | sort > "$source_list"
|
||||
done < "$sources_file"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user