#!/bin/sh # check-session-log — a skill that documents a session_log call must document a # call the tool would actually accept. # # Nine skills documented the payload and none named `session_id`, which is the # tool's only REQUIRED field. An agent following any of them either failed the # call or invented an id — and invented ids do not group, so the pass-rate the # endpoint computes was being assembled from entries that could not be joined # (#36, found by a pressure test against `debug`). # # Also rejected: `duration_ms: `. An agent does not observe a clock. # A documented field nobody can honestly populate gets fabricated or silently # dropped, and fabricated numbers in a metrics stream are worse than no numbers. # # Usage: check-session-log [checkout-root] set -u ROOT=${1:-$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)} fail=0 for dir in "$ROOT"/skills/*/; do [ -f "$dir/SKILL.md" ] || continue name=$(basename "$dir") grep -q 'session_log' "$dir/SKILL.md" || continue # Read the PAYLOAD, not the file. The first version of this gate grepped the # whole SKILL.md for "session_id", so a payload missing the field passed as # long as the word appeared anywhere — including in prose explaining that the # field is required. A traceability probe demonstrated it in one sed. payloads=$(grep -n 'session_log' "$dir/SKILL.md" | grep '{' || true) if [ -z "$payloads" ]; then # Mentions the tool but documents no call. Nothing to check, and nothing to # get wrong. continue fi printf '%s\n' "$payloads" | while IFS= read -r line; do [ -n "$line" ] || continue body=$(printf '%s' "$line" | sed 's/^[0-9]*://') lineno=$(printf '%s' "$line" | cut -d: -f1) printf '%s' "$body" | grep -q 'session_id' \ || echo "ERROR: skills/$name:$lineno documents a session_log payload with no session_id — the tool's only required field" >&2 # Any spelling of the key, quoted or not, followed by anything that is not a # bare number. A placeholder nobody can fill gets fabricated or dropped; a # real measurement is fine. if printf '%s' "$body" | grep -Eq '"?duration_ms"?[[:space:]]*:[[:space:]]*[^0-9,}[:space:]]'; then echo "ERROR: skills/$name:$lineno documents duration_ms as something other than a real measurement — an agent does not observe a clock; omit it" >&2 fi done > "$ROOT/.session_log_errors.$$" 2>&1 if [ -s "$ROOT/.session_log_errors.$$" ]; then cat "$ROOT/.session_log_errors.$$" >&2 fail=1 fi rm -f "$ROOT/.session_log_errors.$$" done exit $fail