From bdf755d33aa6a207a538c85f18e38cc03f14e529 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Thu, 28 May 2026 09:13:51 -0500 Subject: feat(status): add `make status` for compact health summary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit scripts/status.sh prints a six-line summary composing existing checks: - audit + doctor (one call, since audit.sh runs doctor internally) - canonical/mirror sync state via sync-check.sh - open todo count under * Open Work - inbox count (excluding .gitkeep and PROCESSED- prefixes) - git working-tree state with ahead/behind upstream Sample output: rulesets status — 2026-05-28 09:13 CDT audit Summary: 41 ok, 0 warnings, 2 failures sync canonical = mirror todo 22 open inbox 1 unprocessed git main dirty — in sync with origin/main The script adds no new logic beyond formatting. `make status` is the entry point. The scope here is limited per the triage disposition for codex item #12. The rest of #12 was rejected. `make sync` duplicates the existing sync flow, `make health` wraps existing checks without adding signal, `make bootstrap-project` duplicates `install-ai` + `install-lang`. --- scripts/status.sh | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100755 scripts/status.sh (limited to 'scripts') diff --git a/scripts/status.sh b/scripts/status.sh new file mode 100755 index 0000000..0dd23f5 --- /dev/null +++ b/scripts/status.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# +# status.sh — compact summary of repo health and inflight work. +# +# Composes existing checks (audit, doctor, todo count, inbox count, git +# status). No new logic beyond formatting. Target output is ~10 lines, +# scannable in one glance. + +set -uo pipefail + +repo_root="$(git rev-parse --show-toplevel 2>/dev/null)" || { + echo "status: not inside a git checkout" >&2 + exit 2 +} +cd "$repo_root" + +echo "rulesets status — $(date '+%Y-%m-%d %H:%M %Z')" + +# audit + doctor: audit.sh runs doctor internally; one call gives both. +audit_summary="$(bash scripts/audit.sh 2>&1 | grep '^Summary:' | tail -1)" +echo " audit ${audit_summary:-(no summary)}" + +# Sync-check: canonical/mirror parity. +if bash scripts/sync-check.sh >/dev/null 2>&1; then + echo " sync canonical = mirror" +else + echo " sync DRIFT (run make sync-check FIX=1)" +fi + +# Open task count: top-level TODO/DOING entries in the Open Work section +# of todo.org (skip DONE and CANCELLED; skip the Resolved section). +if [ -f todo.org ]; then + open_count=$(awk ' + /^\* .* Open Work/ { in_open=1; next } + /^\* / { in_open=0 } + in_open && /^\*\* (TODO|DOING|VERIFY) / { n++ } + END { print n+0 } + ' todo.org) + echo " todo $open_count open" +else + echo " todo (no todo.org)" +fi + +# Inbox count: files excluding .gitkeep and PROCESSED- prefixes. +if [ -d inbox ]; then + inbox_count=$(find inbox -maxdepth 1 -type f \ + ! -name '.gitkeep' \ + ! -name 'PROCESSED-*' \ + 2>/dev/null | wc -l) + echo " inbox $inbox_count unprocessed" +else + echo " inbox (no inbox/)" +fi + +# Git state: dirty/clean + ahead/behind. +branch=$(git symbolic-ref --short HEAD 2>/dev/null || echo "(detached)") +if [ -z "$(git status --porcelain 2>/dev/null)" ]; then + tree_state="clean" +else + tree_state="dirty" +fi +upstream_state="" +if upstream=$(git rev-parse --abbrev-ref "${branch}@{upstream}" 2>/dev/null); then + counts=$(git rev-list --left-right --count "${upstream}...${branch}" 2>/dev/null) || counts="? ?" + behind=$(echo "$counts" | cut -f1) + ahead=$(echo "$counts" | cut -f2) + if [ "$behind" = "0" ] && [ "$ahead" = "0" ]; then + upstream_state=" — in sync with $upstream" + elif [ "$behind" = "0" ]; then + upstream_state=" — $ahead ahead of $upstream" + elif [ "$ahead" = "0" ]; then + upstream_state=" — $behind behind $upstream" + else + upstream_state=" — diverged ($ahead ahead, $behind behind) from $upstream" + fi +fi +echo " git $branch $tree_state$upstream_state" -- cgit v1.2.3