Second half of #29. The index was hand-maintained and had already drifted once: dream and experiment-spec shipped with no row, their rows lost to a squash-merge after a directory reorg. bin/check-index caught that after the fact; generating removes the class. The curated summary and trigger move into each SKILL.md as `summary:` and `use_when:`, carried over verbatim from the existing table rather than derived from `description:` — description is a paragraph written for model selection, and truncating it would have produced a worse table than the one it replaced. Knowledge now lives once, next to the skill it describes, which is the argument that made a hand-maintained index the wrong shape to begin with. The table is written between markers, so the wiring docs, the relationships tree and the trigger table below it are untouched — those are prose, not data. Rows are alphabetical now; the conceptual grouping the old order carried lives in the relationships tree, which is the better place for it. A fourth column shows each skill's surfaces, which is what makes #29's field visible rather than merely enforced. bin/check-index and its test are deleted: a generated table cannot drift in either direction, so `generate-index --check` subsumes both of its assertions. Verified by mutation — deleting the tdd row turns `task check` red with "SKILLS_INDEX.md is out of date". Closes #29 Bump-Type: minor
86 lines
2.7 KiB
Bash
Executable File
86 lines
2.7 KiB
Bash
Executable File
#!/bin/sh
|
|
# generate-index — rebuild SKILLS_INDEX.md's table from skill frontmatter.
|
|
#
|
|
# The index was hand-maintained and drifted: `dream` and `experiment-spec`
|
|
# shipped with no row at all, because their rows lived on branches that were
|
|
# squash-merged after a directory reorg (#15). A gate catches that after the
|
|
# fact; generating removes the class (#29).
|
|
#
|
|
# The curated summary and trigger live in each SKILL.md as `summary:` and
|
|
# `use_when:` rather than being derived from `description:` — description is a
|
|
# paragraph written for model selection, and truncating it produces a worse
|
|
# table than the one being replaced.
|
|
#
|
|
# Everything outside the markers is left untouched: the wiring docs, the
|
|
# relationships tree and the trigger table are prose, not data.
|
|
#
|
|
# generate-index [root] rewrite the table in place
|
|
# generate-index --check [root] exit 1 if the table is out of date
|
|
|
|
set -u
|
|
|
|
CHECK=0
|
|
if [ "${1:-}" = "--check" ]; then CHECK=1; shift; fi
|
|
ROOT=${1:-$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)}
|
|
INDEX="$ROOT/SKILLS_INDEX.md"
|
|
|
|
BEGIN='<!-- BEGIN skills-table -->'
|
|
END='<!-- END skills-table -->'
|
|
|
|
[ -f "$INDEX" ] || { echo "ERROR: missing $INDEX" >&2; exit 1; }
|
|
grep -qF "$BEGIN" "$INDEX" || { echo "ERROR: $INDEX has no $BEGIN marker" >&2; exit 1; }
|
|
grep -qF "$END" "$INDEX" || { echo "ERROR: $INDEX has no $END marker" >&2; exit 1; }
|
|
|
|
# field <file> <key> — a scalar frontmatter value, quotes stripped.
|
|
field() {
|
|
sed -n "s/^$2:[[:space:]]*//p" "$1" | head -1 | sed 's/^"//; s/"$//'
|
|
}
|
|
|
|
table=$(mktemp)
|
|
fail=0
|
|
|
|
{
|
|
printf '| Skill | Description | Use when | Surfaces |\n'
|
|
printf '|-------|-------------|----------|----------|\n'
|
|
} > "$table"
|
|
|
|
for dir in "$ROOT"/skills/*/; do
|
|
[ -f "$dir/SKILL.md" ] || continue
|
|
name=$(basename "$dir")
|
|
summary=$(field "$dir/SKILL.md" summary)
|
|
use_when=$(field "$dir/SKILL.md" use_when)
|
|
surfaces=$(field "$dir/SKILL.md" surfaces | tr -d '[]')
|
|
|
|
if [ -z "$summary" ] || [ -z "$use_when" ]; then
|
|
echo "ERROR: skills/$name has no 'summary:'/'use_when:' — the index table is generated from them" >&2
|
|
fail=1
|
|
continue
|
|
fi
|
|
printf '| `%s` | %s | %s | %s |\n' "$name" "$summary" "$use_when" "$surfaces" >> "$table"
|
|
done
|
|
|
|
if [ "$fail" -ne 0 ]; then
|
|
rm -f "$table"
|
|
exit 1
|
|
fi
|
|
|
|
out=$(mktemp)
|
|
awk -v begin="$BEGIN" -v end="$END" -v tablefile="$table" '
|
|
$0 == begin { print; while ((getline line < tablefile) > 0) print line; skip = 1; next }
|
|
$0 == end { print; skip = 0; next }
|
|
!skip { print }
|
|
' "$INDEX" > "$out"
|
|
rm -f "$table"
|
|
|
|
if [ "$CHECK" -eq 1 ]; then
|
|
if cmp -s "$out" "$INDEX"; then
|
|
rm -f "$out"
|
|
exit 0
|
|
fi
|
|
rm -f "$out"
|
|
echo "ERROR: SKILLS_INDEX.md is out of date — run 'task index' and commit the result" >&2
|
|
exit 1
|
|
fi
|
|
|
|
mv "$out" "$INDEX"
|