feat(kyberforge): add instructions-author skill for .apm/instructions files
Scaffolds and revises apm instructions files, with a throwaway-package verification recipe because `apm compile --validate` always exits 0 and Claude Code drops `description`. Routed from forge and linked from apm-workflow's compile reference. Bumps kyberforge to 2.1.0 and the catalog to 0.5.2. Fixes #148 Co-Authored-By: Claude Code <[email protected]> Claude-Session: https://claude.ai/code/session_01KkT7RSDwDbmrM9T34b6sTi
This commit is contained in:
1 parent
529ed31cef
commit
c52e351954
20 files changed
+719
-16
No files matched your search
@@ -0,0 +1,3 @@
|
||||
# scripts/
|
||||
|
||||
- **`new-instructions.sh <name> <root>`** — scaffolds `<package-root>/.apm/instructions/<name>.instructions.md` from `assets/templates/instructions.md`. Walks up from `<root>` for the nearest `type:`-bearing `apm.yml`; exits 1 with a pointer to `/apm-workflow configure` when there is none. Never overwrites an existing file. Run `--help` for the full contract.
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
TEMPLATE="$SKILL_DIR/../assets/templates/instructions.md"
|
||||
|
||||
usage() {
|
||||
cat <<USAGE
|
||||
Usage: new-instructions.sh <name> <root>
|
||||
|
||||
Scaffold an apm instructions file from the bundled template.
|
||||
|
||||
Arguments:
|
||||
name Kebab-case stem. Becomes <name>.instructions.md and, after install,
|
||||
the deployed rule's filename.
|
||||
root Existing path at or below the target package. The script walks up for
|
||||
the nearest apm.yml with a top-level type: field (instructions, skill,
|
||||
hybrid or prompts); an apm.yml without type: is a marketplace-only
|
||||
manifest and is skipped. Creates
|
||||
<package-root>/.apm/instructions/<name>.instructions.md
|
||||
|
||||
Exit codes:
|
||||
0 File created, or already existed (no-op)
|
||||
1 Invalid arguments, missing root, no package found, or template not found
|
||||
USAGE
|
||||
}
|
||||
|
||||
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
|
||||
usage
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ $# -lt 2 ]]; then
|
||||
echo "Error: name and root are required." >&2
|
||||
echo "" >&2
|
||||
usage >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
NAME="$1"
|
||||
ROOT="${2/#\~/$HOME}"
|
||||
|
||||
if ! grep -qE '^[a-z0-9]+(-[a-z0-9]+)*$' <<< "$NAME"; then
|
||||
echo "Error: name must use lowercase letters, numbers, and hyphens only." >&2
|
||||
echo " No leading, trailing, or consecutive hyphens." >&2
|
||||
echo " Received: '$NAME'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -f "$TEMPLATE" ]]; then
|
||||
echo "Error: template not found at '$TEMPLATE'." >&2
|
||||
echo " Run this script from its original location inside the instructions-author skill." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$ROOT" ]]; then
|
||||
echo "Error: root directory '$ROOT' does not exist." >&2
|
||||
exit 1
|
||||
fi
|
||||
ROOT="$(cd "$ROOT" && pwd)"
|
||||
|
||||
# Same marker as agent-author's new-agent.sh: a top-level type: naming one of
|
||||
# the four package types, with matching quotes if quoted.
|
||||
is_apm_package_manifest() {
|
||||
local apm_yml="$1" line
|
||||
while IFS= read -r line || [[ -n "$line" ]]; do
|
||||
if [[ "$line" =~ ^type:[[:space:]]*(instructions|skill|hybrid|prompts)([[:space:]]|$) ]]; then
|
||||
return 0
|
||||
fi
|
||||
if [[ "$line" =~ ^type:[[:space:]]*([\"\'])(instructions|skill|hybrid|prompts)([\"\'])([[:space:]]|$) ]] \
|
||||
&& [[ "${BASH_REMATCH[1]}" == "${BASH_REMATCH[3]}" ]]; then
|
||||
return 0
|
||||
fi
|
||||
done < "$apm_yml"
|
||||
return 1
|
||||
}
|
||||
|
||||
PACKAGE_ROOT=""
|
||||
current="$ROOT"
|
||||
while true; do
|
||||
if [[ -f "$current/apm.yml" ]] && is_apm_package_manifest "$current/apm.yml"; then
|
||||
PACKAGE_ROOT="$current"
|
||||
break
|
||||
fi
|
||||
if [[ -e "$current/.git" ]]; then
|
||||
break
|
||||
fi
|
||||
parent="$(dirname "$current")"
|
||||
[[ "$parent" == "$current" ]] && break
|
||||
current="$parent"
|
||||
done
|
||||
|
||||
if [[ -z "$PACKAGE_ROOT" ]]; then
|
||||
echo "Error: no apm package found at or above '$ROOT'." >&2
|
||||
echo " Instructions only deploy from a package's .apm/instructions/. Run" >&2
|
||||
echo " /apm-workflow configure (apm plugin init) there first, then retry." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
DEST_DIR="$PACKAGE_ROOT/.apm/instructions"
|
||||
DEST="$DEST_DIR/$NAME.instructions.md"
|
||||
|
||||
if [[ -f "$DEST" ]]; then
|
||||
echo "Skipping '$DEST' — already exists." >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mkdir -p "$DEST_DIR"
|
||||
cp "$TEMPLATE" "$DEST"
|
||||
echo "Created: $DEST" >&2
|
||||
echo "" >&2
|
||||
echo "Next steps:" >&2
|
||||
echo " 1. Fill in $DEST — replace every FILL IN: placeholder and delete the comments." >&2
|
||||
echo " 2. Check '$NAME' does not collide with a hand-authored rule: install overwrites" >&2
|
||||
echo " <target>/rules/$NAME.* on most targets without warning." >&2
|
||||
echo " 3. Verify with a real compile, not --validate: apm compile --dry-run --target <target>" >&2
|
||||
Reference in new issue
Block a user