#!/usr/bin/env bash # Roster generator for spire:adepts — derived metadata from adept domain folders. # Called via skill shell injection: !`bash "${CLAUDE_SKILL_DIR}/roster.sh"` # # Design principle: adepts write knowledge; tooling derives metadata. This # script reads frontmatter declared once and journal filenames that already # exist. No adept ever maintains an index, a counter, or a timestamp by hand. # Resolve workpad — same chain as spire:workpad, minus interactive steps. WP="${WORKPAD_FOLDER:-$(just workpad-folder 2>/dev/null)}" if [ -z "$WP" ]; then # Try .claude/spire/project.md for an explicit Workpad: line if [ -f .claude/spire/project.md ]; then WP=$(sed -n 's/^- \*\*Workpad\*\*: *`\{0,1\}\([^` ]*\).*/\1/p' .claude/spire/project.md | head -1) fi fi [ -z "$WP" ] && { [ -d docs/workpad ] && WP=docs/workpad || WP=.workpad; } [ -d "$WP/adepts" ] || { echo "## Adept roster — none (no $WP/adepts/)"; exit 0; } echo "## Adept roster — $WP/adepts/ ($(date +%F))" for dir in "$WP"/adepts/*/; do [ -d "$dir" ] || continue slug=$(basename "$dir") [ "$slug" = "_template" ] && continue # FC-6: Skip files without frontmatter early — avoid full-file reads through sed. if ! head -1 "$dir/CLAUDE.md" 2>/dev/null | grep -q '^---$'; then newest=$(ls "$dir"/journal/ "$dir" 2>/dev/null | grep -E '^[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{2}' | sort | tail -1 | cut -c1-13) echo "- **$slug** — (unmigrated: no frontmatter) · last active ${newest:-never}" continue fi fm=$(sed -n '2,/^---$/p' "$dir/CLAUDE.md" 2>/dev/null) summary=$(echo "$fm" | sed -n 's/^summary: *//p') status=$(echo "$fm" | sed -n 's/^status: *//p') related=$(echo "$fm" | sed -n 's/^related: *//p') # Recency and session count derived from journal filenames — nothing to maintain. newest=$(ls "$dir"/journal/ "$dir" 2>/dev/null | grep -E '^[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{2}' | sort | tail -1 | cut -c1-13) sessions=$(ls "$dir"/journal/ "$dir" 2>/dev/null | grep -Eo '^[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{2}' | sort -u | wc -l) if [ -z "$summary" ]; then echo "- **$slug** — (unmigrated: no frontmatter) · last active ${newest:-never}" else echo "- **$slug** — $summary · last active ${newest:-never} · $sessions session(s) · ${status:-active}${related:+ · related: $related}" fi done