Files
CASAN/bin/casan
T

97 lines
4.1 KiB
Bash
Executable File

#!/usr/bin/env bash
# CASAN — lightweight CLI wrapper (Level 1 Core Harness).
#
# Locates the harness package relative to this script (works both in the full
# source hub and in an extracted casan-core / casan-devkit bundle) and dispatches
# to the harness bash entrypoints. No dependencies beyond bash + python3.
set -uo pipefail
# --- locate the harness root (dir containing scripts/bash/casan-harness.sh) ----
_self="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
_find_harness() {
# 1) sibling packages/casan-harness (source hub or bundle root layout)
local c
for c in "$_self/../packages/casan-harness" "$_self/../casan-harness" "$_self/packages/casan-harness"; do
[[ -f "$c/scripts/bash/casan-harness.sh" ]] && { (cd "$c" && pwd); return 0; }
done
# 2) walk up looking for it
local d="$_self"
while [[ "$d" != "/" ]]; do
[[ -f "$d/packages/casan-harness/scripts/bash/casan-harness.sh" ]] && { echo "$d/packages/casan-harness"; return 0; }
d="$(dirname "$d")"
done
return 1
}
HARNESS="${CASAN_HARNESS_ROOT:-$(_find_harness)}"
if [[ -z "${HARNESS:-}" || ! -d "$HARNESS" ]]; then
echo "casan: cannot locate packages/casan-harness (set CASAN_HARNESS_ROOT)" >&2
exit 1
fi
BASH_DIR="$HARNESS/scripts/bash"
TESTS_DIR="$HARNESS/tests"
CASAN_APP_ROOT="${CASAN_APP_ROOT:-$(cd "$HARNESS/../.." && pwd)}"
VERSION_FILE="$_self/../VERSION"
[[ -f "$VERSION_FILE" ]] || VERSION_FILE="$HARNESS/../../VERSION"
version() { printf 'casan %s\n' "$( [[ -f "$VERSION_FILE" ]] && cat "$VERSION_FILE" || echo 'unknown')"; }
usage() {
cat <<EOF
casan — CASAN governance harness CLI ($(version))
Usage: casan <command> [args]
Commands:
run <in> <out> [action] [-- cmd...] Run a step through the harness (H4→H5→H6→exec→H4-out)
gate Run the full CI harness gate (all suites)
test Run the core harness test suite (run-casan4)
verify Verify audit chain + tool audit + policy bundle
reuse Verify multi-project harness reuse (registry)
project validate [--manifest path] Validate a project manifest and quality profile
project init <scaffold args...> Create an idempotent NestJS/React project shell
pipeline [--manifest path] Run the manifest-driven SRS→test pipeline
dashboard [port] Serve the AgentOps dashboard (default 8787)
version Print version
help This help
Env: CASAN_HARNESS_ROOT overrides harness location.
Harness: $HARNESS
EOF
}
cmd="${1:-help}"; shift || true
case "$cmd" in
run) exec bash "$BASH_DIR/casan-harness.sh" "$@" ;;
gate)
if [[ -n "${CASAN_PROJECT_MANIFEST:-}${CASAN_PROJECT_ID:-}" ]]; then
exec bash "$BASH_DIR/project-gate.sh" "$@"
fi
exec bash "$BASH_DIR/ci-harness-gate.sh" "$@" ;;
test) exec bash "$TESTS_DIR/run-casan4-harness-tests.sh" "$@" ;;
verify)
rc=0
bash "$BASH_DIR/verify-audit-chain.sh" "$@" || rc=$?
bash "$BASH_DIR/verify-tool-audit.sh" || rc=$?
bash "$BASH_DIR/sign-policy-bundle.sh" verify || rc=$?
exit $rc ;;
reuse) exec bash "$BASH_DIR/verify-harness-reuse.sh" "$@" ;;
project)
sub="${1:-help}"; shift || true
case "$sub" in
validate) exec python3 "$BASH_DIR/project_manifest.py" validate --root "$CASAN_APP_ROOT" "$@" ;;
init)
DEVKIT="${CASAN_DEVKIT_ROOT:-$CASAN_APP_ROOT/packages/casan-devkit}"
[[ -f "$DEVKIT/project-scaffold.py" ]] || { echo "casan: project init requires the casan-devkit bundle" >&2; exit 1; }
exec python3 "$DEVKIT/project-scaffold.py" "$@" ;;
*) echo "casan: usage: casan project <validate|init>" >&2; exit 64 ;;
esac ;;
pipeline)
RUNNER="$CASAN_APP_ROOT/scripts/run-casan-pipeline.mjs"
[[ -f "$RUNNER" ]] || { echo "casan: pipeline runner is not installed" >&2; exit 1; }
exec node "$RUNNER" "$@" ;;
dashboard) exec bash "$BASH_DIR/dashboard-serve.sh" "$@" ;;
version|-v|--version) version ;;
help|-h|--help) usage ;;
*) echo "casan: unknown command '$cmd'" >&2; usage >&2; exit 64 ;;
esac