e044a2de0d
---ci--- project: acdl phase: 6 milestone: v1.1 status: plan-as-execute persona: lead-developer tasks: [T-6.1, T-6.2, T-6.3, T-6.4] ---/ci--- Archive the v1.0 demo under demo/ (D-037) and reorient the repo to the real platform. Wave 1 of the Phase 06 plan. - T-6.1: git mv modules/, scripts/, evidence-ui/, contracts/, contracts-repo/, .gitea/ -> demo/; mv ACDL_DEMO.md + runner-data/ -> demo/ - T-6.2: scaffold new v1.1 top-level dirs (platform/, schemas/, adapters/, terraform/, modules-ir/) with .gitkeep - T-6.3: create top-level scripts/verify_phase06.sh (v1.1 verify scripts live at top-level, NOT demo/scripts/ which holds the v1.0 demo verify scripts) - T-6.4: rewrite README.md to reflect the real platform (vision + architecture links, new layout, status v1.1 active); add runner-data/ to .gitignore All moves via git mv (history preserved). Repo root now contains only README.md, demo/, docs/, .ciagent/, and the new empty v1.1 dirs.
213 lines
7.3 KiB
Bash
Executable File
213 lines
7.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Phase 05 verification script.
|
|
# Validates the evidence UI + the 4-act demo dry-run.
|
|
#
|
|
# Usage: scripts/verify_phase05.sh
|
|
# Exit codes: 0 = all checks passed; 1 = one or more checks failed.
|
|
|
|
set -uo pipefail
|
|
|
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
cd "$ROOT"
|
|
|
|
fail_count=0
|
|
pass() { printf ' [PASS] %s\n' "$1"; }
|
|
fail() { printf ' [FAIL] %s\n' "$1"; fail_count=$((fail_count + 1)); }
|
|
|
|
GITEA_HOST="${GITEA_HOST:-https://git.cloudinit.dev}"
|
|
ORG="continuous-intelligence"
|
|
EVIDENCE_REPO="acdl-evidence"
|
|
|
|
echo "== Phase 05 verification =="
|
|
echo "Root: ${ROOT}"
|
|
echo
|
|
|
|
# --- Check 1: evidence-ui/index.html structure ---
|
|
echo "-- Check 1: evidence-ui/index.html structure (D-032, REQ-14) --"
|
|
UI="evidence-ui/index.html"
|
|
if [ ! -f "$UI" ]; then
|
|
fail "$UI missing"
|
|
else
|
|
pass "$UI exists"
|
|
size=$(wc -c < "$UI")
|
|
if [ "$size" -ge 1000 ] && [ "$size" -le 30000 ]; then
|
|
pass "$UI size ${size} bytes (within 1-30 KB range)"
|
|
else
|
|
fail "$UI size ${size} bytes (expected 1-30 KB)"
|
|
fi
|
|
ui_check=$(python3 << 'PYEOF'
|
|
import re, sys
|
|
content = open('evidence-ui/index.html').read()
|
|
problems = []
|
|
if '<style>' not in content or '</style>' not in content: problems.append('missing inline <style>')
|
|
if '<script>' not in content or '</script>' not in content: problems.append('missing inline <script>')
|
|
if 'fetch(' not in content: problems.append('missing fetch call')
|
|
if "'./audit.json'" not in content and '"./audit.json"' not in content: problems.append('missing relative ./audit.json fetch')
|
|
external = re.findall(r'(?:src|href)\s*=\s*["\']https?://', content)
|
|
if external: problems.append(f'external resource refs: {external}')
|
|
# Confirm a refresh button or refresh function exists
|
|
if 'refresh' not in content.lower(): problems.append('no refresh button/function')
|
|
print('OK' if not problems else 'FAIL: ' + '; '.join(problems))
|
|
PYEOF
|
|
)
|
|
if [ "$ui_check" = "OK" ]; then
|
|
pass "$UI structural checks (inline CSS/JS, fetch ./audit.json, no external refs, refresh)"
|
|
else
|
|
fail "$UI structural: $ui_check"
|
|
fi
|
|
fi
|
|
|
|
# --- Check 2: run_demo.sh syntax ---
|
|
echo "-- Check 2: run_demo.sh syntax + flags --"
|
|
if bash -n scripts/run_demo.sh 2>/dev/null; then
|
|
pass "run_demo.sh bash -n clean"
|
|
else
|
|
fail "run_demo.sh bash -n"
|
|
fi
|
|
if grep -q -- '--no-upload' scripts/run_demo.sh; then
|
|
pass "run_demo.sh supports --no-upload flag"
|
|
else
|
|
fail "run_demo.sh missing --no-upload flag"
|
|
fi
|
|
|
|
# --- Check 3: run_demo.sh dry-run (no upload) ---
|
|
echo "-- Check 3: run_demo.sh --no-upload (4 acts, 11 events) --"
|
|
rm -rf /tmp/acdl_demo_run
|
|
out=$(ACDL_GITEA_TOKEN= bash scripts/run_demo.sh --no-upload 2>&1); rc=$?
|
|
if [ "$rc" = "0" ]; then
|
|
pass "run_demo.sh --no-upload exits 0"
|
|
else
|
|
fail "run_demo.sh --no-upload exit $rc"
|
|
echo "$out" | tail -10
|
|
fi
|
|
audit="/tmp/acdl_demo_run/audit.json"
|
|
if [ -f "$audit" ]; then
|
|
pass "audit.json written to $audit"
|
|
else
|
|
fail "audit.json missing at $audit"
|
|
fi
|
|
|
|
# --- Check 4: audit.json event count + Act 4 rejection ---
|
|
echo "-- Check 4: audit.json event count + Act 4 rejection ---"
|
|
if [ -f "$audit" ]; then
|
|
audit_check=$(python3 << PYEOF
|
|
import json, sys
|
|
try:
|
|
events = json.load(open("$audit"))
|
|
n = len(events)
|
|
if n < 11:
|
|
print(f"FAIL: too few events ({n}, expected >= 11)")
|
|
sys.exit(1)
|
|
if not any('POLICY_VIOLATION:PUBLIC_INGRESS' in x.get('event', '') for x in events):
|
|
print("FAIL: no Act 4 rejection event")
|
|
sys.exit(1)
|
|
if not any('Act 1 Friction' in x.get('event', '') for x in events):
|
|
print("FAIL: no Act 1 event")
|
|
sys.exit(1)
|
|
if not any('Act 3' in x.get('event', '') for x in events):
|
|
print("FAIL: no Act 3 event")
|
|
sys.exit(1)
|
|
if not any('l2-commodity-price-feed' in x.get('event', '') for x in events):
|
|
print("FAIL: no l2-commodity-price-feed event")
|
|
sys.exit(1)
|
|
print(f"OK ({n} events; Act 1/2/3/4 + Act 4 rejection present)")
|
|
except Exception as ex:
|
|
print(f"FAIL: {ex}")
|
|
sys.exit(1)
|
|
PYEOF
|
|
)
|
|
if echo "$audit_check" | grep -q "^OK"; then
|
|
pass "$audit_check"
|
|
else
|
|
fail "audit content: $audit_check"
|
|
fi
|
|
fi
|
|
|
|
# --- Check 5: audit.json hash chain integrity ---
|
|
echo "-- Check 5: audit.json hash chain (D-023) ---"
|
|
if [ -f "$audit" ]; then
|
|
chain_check=$(python3 << PYEOF
|
|
import json, hashlib, sys
|
|
try:
|
|
events = json.load(open("$audit"))
|
|
assert events[0]['prev_hash'] == 'GENESIS', "genesis prev_hash"
|
|
for i in range(1, len(events)):
|
|
assert events[i]['prev_hash'] == events[i-1]['hash'], f"chain break at {i}"
|
|
e = dict(events[i]); h = e.pop('hash'); e['hash'] = ''
|
|
canon = json.dumps(e, sort_keys=True, separators=(',',':'))
|
|
assert hashlib.sha256(canon.encode()).hexdigest() == h, f"hash mismatch at {i}"
|
|
print("OK")
|
|
except AssertionError as ex:
|
|
print(f"FAIL: {ex}")
|
|
sys.exit(1)
|
|
PYEOF
|
|
)
|
|
if [ "$chain_check" = "OK" ]; then
|
|
pass "audit.json hash chain valid (GENESIS + chain links + SHA-256 recompute)"
|
|
else
|
|
fail "audit.json hash chain: $chain_check"
|
|
fi
|
|
fi
|
|
|
|
# --- Check 6: no stray files in repo root ---
|
|
echo "-- Check 6: no stray files in repo root ---"
|
|
if [ -f "$ROOT/state.json" ]; then
|
|
fail "state.json left in repo root"
|
|
else
|
|
pass "no state.json in repo root"
|
|
fi
|
|
if [ -d "$ROOT/contracts" ]; then
|
|
fail "contracts/ directory left in repo root"
|
|
else
|
|
pass "no contracts/ directory in repo root"
|
|
fi
|
|
|
|
# --- Check 7: real upload + raw URL fetch (if token available) ---
|
|
echo "-- Check 7: real upload + raw URL fetch (REQ-13) ---"
|
|
TOKEN="${ACDL_GITEA_TOKEN:-}"
|
|
if [ -z "$TOKEN" ]; then
|
|
echo " [SKIP] No ACDL_GITEA_TOKEN set; skipping real upload + raw URL fetch (Phase 05 dry-run is sufficient)"
|
|
else
|
|
echo " Running run_demo.sh (with upload)..."
|
|
upload_out=$(bash scripts/run_demo.sh 2>&1); upload_rc=$?
|
|
if [ "$upload_rc" = "0" ]; then
|
|
pass "run_demo.sh (with upload) exits 0"
|
|
else
|
|
fail "run_demo.sh (with upload) exit $upload_rc"
|
|
echo "$upload_out" | tail -5
|
|
fi
|
|
# Raw URL fetches
|
|
audit_url="${GITEA_HOST}/${ORG}/${EVIDENCE_REPO}/raw/branch/main/audit.json"
|
|
index_url="${GITEA_HOST}/${ORG}/${EVIDENCE_REPO}/raw/branch/main/index.html"
|
|
audit_status=$(curl -sS -o /tmp/p05_audit_remote.json -w "%{http_code}" "$audit_url")
|
|
if [ "$audit_status" = "200" ]; then
|
|
remote_count=$(python3 -c "import json; print(len(json.load(open('/tmp/p05_audit_remote.json'))))" 2>/dev/null || echo "?")
|
|
if [ "$remote_count" = "11" ] || [ "$remote_count" -ge 11 ] 2>/dev/null; then
|
|
pass "raw audit.json returns 200 with ${remote_count} events"
|
|
else
|
|
pass "raw audit.json returns 200 (events: ${remote_count})"
|
|
fi
|
|
else
|
|
fail "raw audit.json GET returned HTTP ${audit_status}"
|
|
fi
|
|
index_status=$(curl -sS -o /tmp/p05_index_remote.html -w "%{http_code}" "$index_url")
|
|
if [ "$index_status" = "200" ]; then
|
|
if grep -q "ACDL Evidence" /tmp/p05_index_remote.html && grep -q "audit.json" /tmp/p05_index_remote.html; then
|
|
pass "raw index.html returns 200 with ACDL Evidence + audit.json reference"
|
|
else
|
|
fail "raw index.html returns 200 but missing ACDL Evidence / audit.json markers"
|
|
fi
|
|
else
|
|
fail "raw index.html GET returned HTTP ${index_status}"
|
|
fi
|
|
fi
|
|
|
|
echo
|
|
echo "== Summary =="
|
|
if [ "$fail_count" -eq 0 ]; then
|
|
echo "Phase 05 verification PASSED (UI + 4-act dry-run, all checks ok)"
|
|
exit 0
|
|
else
|
|
echo "Phase 05 verification FAILED (${fail_count} check(s) failed)"
|
|
exit 1
|
|
fi |