#!/usr/bin/env bash # project-audit.sh — stack & phased-readiness probe for the Conversion Architect. # # Prints: project root, version-control state, detected manifests, domain # hints, existing .agent/ artifacts, test tooling, and the next free phase # number NN (counting .agent/phases/todo/ and complete/ together, # zero-padded to 2 digits). # # Usage: bash project-audit.sh # from anywhere in the project tree set -uo pipefail root="$(pwd)" if git rev-parse --show-toplevel >/dev/null 2>&1; then root="$(git rev-parse --show-toplevel)" fi echo "project root: $root" echo echo "version control:" if [[ -d "$root/.git" ]]; then branch="$(git -C "$root" branch --show-current 2>/dev/null || echo unknown)" dirty="$(git -C "$root" status --porcelain 2>/dev/null | wc -l | tr -d ' ')" echo " git repository (branch: ${branch:-detached}, uncommitted changes: ${dirty})" else echo " (not a git repository — the conversion must git init)" fi echo echo "manifests:" found=0 for m in pyproject.toml uv.lock package.json pnpm-lock.yaml go.mod Cargo.toml requirements.txt setup.py setup.cfg pom.xml build.gradle; do if [[ -f "$root/$m" ]]; then echo " $m" found=1 fi done for c in compose.yaml docker-compose.yml Containerfile Dockerfile; do if [[ -f "$root/$c" ]]; then echo " $c" found=1 fi done if (( ! found )); then echo " (none detected)"; fi echo echo "domain hints:" hint=0 if [[ -f "$root/pyproject.toml" ]]; then if grep -q '^\[project\.scripts\]' "$root/pyproject.toml"; then echo " cli ([project.scripts] entry points)" hint=1 fi if grep -qiE 'fastapi|flask|django|starlette|aiohttp' "$root/pyproject.toml"; then echo " web (web framework dependency)" hint=1 fi fi if [[ -f "$root/py.typed" ]]; then echo " library (py.typed marker)" hint=1 fi if [[ -d "$root/templates" ]]; then echo " web (templates/ directory)" hint=1 fi if [[ -f "$root/package.json" ]] && grep -q '"bin"' "$root/package.json"; then echo " cli (package.json \"bin\")" hint=1 fi if (( ! hint )); then echo " (none — classify from the manifests above)"; fi echo echo ".agent state:" a=0 if [[ -f "$root/.agent/PLAN.md" ]]; then echo " .agent/PLAN.md: present" a=1 fi if [[ -f "$root/AGENTS.md" ]]; then echo " AGENTS.md: present" a=1 fi if [[ -f "$root/.agent/validate.sh" ]]; then echo " .agent/validate.sh: present" a=1 fi for d in workflows features user_stories; do if [[ -d "$root/.agent/$d" ]]; then n="$(find "$root/.agent/$d" -maxdepth 1 -name '*.md' 2>/dev/null | wc -l | tr -d ' ')" echo " .agent/$d/: present ($n file(s))" a=1 fi done todo_dir="$root/.agent/phases/todo" complete_dir="$root/.agent/phases/complete" if [[ -d "$todo_dir" ]]; then echo " .agent/phases/todo:" any=0 for f in "$todo_dir"/*.md; do if [[ -e "$f" ]]; then echo " $(basename "$f")" any=1 fi done if (( ! any )); then echo " (empty)"; fi a=1 fi if [[ -d "$complete_dir" ]]; then echo " .agent/phases/complete:" any=0 for f in "$complete_dir"/*.md; do if [[ -e "$f" ]]; then echo " $(basename "$f")" any=1 fi done if (( ! any )); then echo " (empty)"; fi a=1 fi if (( ! a )); then echo " (no .agent/ artifacts — full conversion needed)"; fi max=0 for d in "$todo_dir" "$complete_dir"; do for f in "$d"/*.md; do if [[ ! -e "$f" ]]; then continue; fi n="$(basename "$f" .md)" if [[ "$n" =~ ^([0-9]+) ]]; then n=$((10#${BASH_REMATCH[1]})) if (( n > max )); then max=$n; fi fi done done echo " next phase number: $(printf '%02d' $((max + 1)))" echo echo "test tooling:" t=0 if [[ -f "$root/pytest.ini" ]] || { [[ -f "$root/pyproject.toml" ]] && grep -q '\[tool\.pytest' "$root/pyproject.toml"; }; then echo " pytest configured" t=1 fi if [[ -f "$root/conftest.py" ]] || [[ -d "$root/tests" ]]; then echo " tests/ or conftest.py present" t=1 fi n_py="$(find "$root" \( -name 'test_*.py' -o -name '*_test.py' \) -not -path '*/.git/*' -not -path '*/node_modules/*' -not -path '*/.venv/*' -not -path '*/venv/*' 2>/dev/null | wc -l | tr -d ' ')" if (( n_py > 0 )); then echo " $n_py python test file(s)"; t=1; fi if [[ -f "$root/package.json" ]] && grep -q '"test"' "$root/package.json"; then echo " npm test script" t=1 fi if [[ -f "$root/ruff.toml" ]] || { [[ -f "$root/pyproject.toml" ]] && grep -q '\[tool\.ruff\]' "$root/pyproject.toml"; }; then echo " ruff configured" t=1 fi if [[ -f "$root/pyrightconfig.json" ]] || { [[ -f "$root/pyproject.toml" ]] && grep -q '\[tool\.pyright\]' "$root/pyproject.toml"; }; then echo " pyright configured" t=1 fi if [[ -f "$root/.coveragerc" ]] || { [[ -f "$root/pyproject.toml" ]] && grep -qE '\[tool\.(coverage|pytest-cov)\]' "$root/pyproject.toml"; }; then echo " coverage configured" t=1 fi if (( ! t )); then echo " (none detected — the foundation phase must establish a test baseline)"; fi