mirror of
https://github.com/boshu2/agentops.git
synced 2026-09-14 15:08:13 +08:00
f8bc3f5b6f
check-goal-staleness.sh was written against the legacy GOALS.yaml format with machine-readable `added:` and `check:` fields. After the repo migrated to GOALS.md (see CLAUDE.md §Agent Goals) the script errors with 'GOALS.yaml not found at GOALS.yaml' — which misleads readers into thinking a real gate is broken. When GOALS.yaml is absent AND GOALS.md is present, skip with exit 0 and a clear message that names the migration. Preserve the existing error behavior when neither file exists (that is still a genuine misconfiguration). Document the migration in the script header so the skip path is discoverable. No downstream gate depends on this script today, so this is a correctness + signal-noise fix, not a contract change.
163 lines
5.1 KiB
Bash
Executable File
163 lines
5.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Checks GOALS.yaml for stale goals with simple grep-based checks that pass trivially.
|
|
#
|
|
# A goal is "stale" if its `added` date is older than 90 days.
|
|
# A goal has a "simple grep pattern" check if it uses only basic file inspection
|
|
# commands (grep, test -f, head, tail, wc, xargs test, tr) and does NOT invoke
|
|
# shell scripts (.sh), go test, go build, go vet, go test -race, ./tests/, ./scripts/.
|
|
#
|
|
# Flagged candidates (stale + simple check + passes) are printed to stderr.
|
|
# Exits non-zero if there are >5 flagged candidates.
|
|
#
|
|
# Usage: ./scripts/check-goal-staleness.sh
|
|
# Requires: yq (YAML processor), date (macOS compatible)
|
|
#
|
|
# GOALS.md migration (see CLAUDE.md §Agent Goals): this repo converted
|
|
# GOALS.yaml -> GOALS.md, so machine-readable `added:` / `check:` fields are no
|
|
# longer present. If GOALS.yaml is absent, the script skips with exit 0 rather
|
|
# than erroring, because no downstream gate depends on its output and erroring
|
|
# misleads readers about a real problem.
|
|
|
|
set -uo pipefail
|
|
|
|
# macOS-compatible cutoff date: 90 days ago as YYYY-MM-DD
|
|
CUTOFF_DATE=$(date -v-90d +%Y-%m-%d 2>/dev/null)
|
|
if [ -z "$CUTOFF_DATE" ]; then
|
|
# GNU date fallback
|
|
CUTOFF_DATE=$(date -d "90 days ago" +%Y-%m-%d 2>/dev/null)
|
|
fi
|
|
|
|
if [ -z "$CUTOFF_DATE" ]; then
|
|
echo "ERROR: Could not compute cutoff date. Ensure macOS or GNU date is available." >&2
|
|
exit 1
|
|
fi
|
|
|
|
GOALS_FILE="${1:-GOALS.yaml}"
|
|
|
|
if [ ! -f "$GOALS_FILE" ]; then
|
|
# Post-GOALS.md migration: GOALS.yaml is the legacy YAML format. When it is
|
|
# absent we skip because this script has no way to apply its staleness
|
|
# heuristics against the current narrative markdown format.
|
|
if [ -f "GOALS.md" ]; then
|
|
echo "SKIP: GOALS.yaml not found; repo uses GOALS.md (post-migration). Nothing to check." >&2
|
|
exit 0
|
|
fi
|
|
echo "ERROR: GOALS.yaml not found at $GOALS_FILE" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# is_simple_grep_check <check_string>
|
|
# Returns 0 (true) if the check is a simple grep/file-inspection pattern.
|
|
# Returns 1 (false) if the check invokes scripts or go commands.
|
|
is_simple_grep_check() {
|
|
local check="$1"
|
|
|
|
# Reject if the check contains any of these patterns
|
|
if echo "$check" | grep -qE '\.(sh)(\s|$|"|'"'"')'; then
|
|
return 1
|
|
fi
|
|
if echo "$check" | grep -qE '\bgo (test|build|vet)\b'; then
|
|
return 1
|
|
fi
|
|
if echo "$check" | grep -qE '\./tests/'; then
|
|
return 1
|
|
fi
|
|
if echo "$check" | grep -qE '\./scripts/'; then
|
|
return 1
|
|
fi
|
|
# Reject bash -c wrappers that could contain complex logic
|
|
if echo "$check" | grep -qE '^bash\s+-c\s+|^bash\s+"'; then
|
|
return 1
|
|
fi
|
|
# Reject "cd && go ..." or "cd ... && go ..." patterns
|
|
if echo "$check" | grep -qE 'cd\s+\S+\s+&&\s+(go|npm|python|ruby|cargo)'; then
|
|
return 1
|
|
fi
|
|
# Reject node, jq -e (structured queries), for loops (complex multi-step)
|
|
if echo "$check" | grep -qE '\bnode\b|\bjq\s+-e\b|\bfor\s+\w+\s+in\b|\bawk\b'; then
|
|
return 1
|
|
fi
|
|
|
|
# Accept: must only contain allowed primitives
|
|
# grep, test, head, tail, wc, xargs test, tr, &&, ||, |, quotes, paths, -q/-c/-r flags
|
|
# We confirm by checking it does NOT use any shell execution beyond these
|
|
# (Already checked above for disallowed commands)
|
|
return 0
|
|
}
|
|
|
|
# date_is_older_than_cutoff <date_string>
|
|
# Returns 0 if date_string < CUTOFF_DATE (i.e. goal is stale/old)
|
|
date_is_older_than_cutoff() {
|
|
local goal_date="$1"
|
|
|
|
# Validate date format YYYY-MM-DD
|
|
if ! echo "$goal_date" | grep -qE '^[0-9]{4}-[0-9]{2}-[0-9]{2}$'; then
|
|
return 1
|
|
fi
|
|
|
|
# Lexicographic comparison works for ISO 8601 dates
|
|
if [[ "$goal_date" < "$CUTOFF_DATE" ]]; then
|
|
return 0
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
FLAGGED_COUNT=0
|
|
FLAGGED_IDS=()
|
|
|
|
# Get the count of goals
|
|
GOAL_COUNT=$(yq e '.goals | length' "$GOALS_FILE" 2>/dev/null)
|
|
|
|
if [ -z "$GOAL_COUNT" ] || [ "$GOAL_COUNT" -eq 0 ]; then
|
|
echo "No goals found in $GOALS_FILE" >&2
|
|
exit 0
|
|
fi
|
|
|
|
for i in $(seq 0 $((GOAL_COUNT - 1))); do
|
|
# Extract fields for this goal
|
|
GOAL_ID=$(yq e ".goals[$i].id" "$GOALS_FILE" 2>/dev/null)
|
|
ADDED=$(yq e ".goals[$i].added" "$GOALS_FILE" 2>/dev/null)
|
|
CHECK=$(yq e ".goals[$i].check" "$GOALS_FILE" 2>/dev/null)
|
|
|
|
# Skip goals without an `added` field (yq returns "null" for missing fields)
|
|
if [ -z "$ADDED" ] || [ "$ADDED" = "null" ]; then
|
|
continue
|
|
fi
|
|
|
|
# Skip goals without a check
|
|
if [ -z "$CHECK" ] || [ "$CHECK" = "null" ]; then
|
|
continue
|
|
fi
|
|
|
|
# Only process goals older than 90 days
|
|
if ! date_is_older_than_cutoff "$ADDED"; then
|
|
continue
|
|
fi
|
|
|
|
# Only process simple grep-pattern checks
|
|
if ! is_simple_grep_check "$CHECK"; then
|
|
continue
|
|
fi
|
|
|
|
# Run the check and see if it passes (exit 0 = trivially true candidate)
|
|
if bash -c "$CHECK" >/dev/null 2>&1; then
|
|
FLAGGED_COUNT=$((FLAGGED_COUNT + 1))
|
|
FLAGGED_IDS+=("$GOAL_ID")
|
|
echo "TRIVIALLY TRUE CANDIDATE: $GOAL_ID (added: $ADDED, check: $CHECK)" >&2
|
|
fi
|
|
done
|
|
|
|
if [ "$FLAGGED_COUNT" -gt 0 ]; then
|
|
echo "" >&2
|
|
echo "Summary: $FLAGGED_COUNT trivially-true stale goal(s) flagged." >&2
|
|
echo "These goals were added >90 days ago and their simple checks pass — they may need raising or retiring." >&2
|
|
else
|
|
echo "No trivially-true stale goals found." >&2
|
|
fi
|
|
|
|
if [ "$FLAGGED_COUNT" -gt 5 ]; then
|
|
exit 1
|
|
fi
|
|
|
|
exit 0
|