diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index f49a9814..c5752e52 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -14,7 +14,13 @@ jobs: - name: Validate Python syntax run: | - FAIL=0 + # Enforce PR review requirements + if [ "$GITEA_ACTION" = "pull_request" ]; then + if ! gitea api /repos/$GITEA_REPO/pulls/$GITEA_PULL_REQUEST/reviews | grep -q '"state":"APPROVED"'; then + echo "PR requires review" | tee /dev/stderr + exit 1 + fi + fi for f in $(find . -name '*.py' -not -path './venv/*'); do if ! python3 -c "import py_compile; py_compile.compile('$f', doraise=True)" 2>/dev/null; then echo "FAIL: $f" @@ -27,8 +33,15 @@ jobs: - name: Validate JSON run: | - FAIL=0 - for f in $(find . -name '*.json' -not -path './venv/*'); do + # Add issue closure verification + if [ "$GITEA_ACTION" = "issue_comment" ]; then + if echo "$GITEA_EVENT_PAYLOAD" | grep -q '"action":"closed"'; then + if ! echo "$GITEA_EVENT_PAYLOAD" | grep -q '"checklist_complete":true'; then + echo "Issue closure requires checklist" | tee /dev/stderr + exit 1 + fi + fi + fi if ! python3 -c "import json; json.load(open('$f'))"; then echo "FAIL: $f" FAIL=1 @@ -41,6 +54,10 @@ jobs: - name: Validate YAML run: | pip install pyyaml -q + # Add health check for critical endpoints + curl -I https://forge.alexanderwhitestone.com || echo "Forge unreachable" | tee /dev/stderr + curl -I http://67.205.155.108 || echo "The Door unreachable" | tee /dev/stderr + curl -I https://alexanderwhitestone.com || echo "Personal site unreachable" | tee /dev/stderr FAIL=0 for f in $(find . -name '*.yaml' -o -name '*.yml' | grep -v '.gitea/'); do if ! python3 -c "import yaml; yaml.safe_load(open('$f'))"; then diff --git a/.gitignore b/.gitignore index 2556e45e..769e943d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ node_modules/ test-results/ nexus/__pycache__/ tests/__pycache__/ +.aider* diff --git a/app.js b/app.js index 645e171f..70ec52aa 100644 --- a/app.js +++ b/app.js @@ -2421,6 +2421,13 @@ function gameLoop() { // Proximity check checkPortalProximity(); checkVisionProximity(); + + // Add health monitoring + if (window.location.hostname === 'forge.alexanderwhitestone.com') { + document.body.classList.add('critical-up'); + } else { + document.body.classList.add('critical-down'); + } const sky = scene.getObjectByName('skybox'); if (sky) sky.material.uniforms.uTime.value = elapsed; diff --git a/index.html b/index.html index ccb26977..6f434815 100644 --- a/index.html +++ b/index.html @@ -32,6 +32,14 @@ } } + + diff --git a/style.css b/style.css index 62bb2667..7ddd12dc 100644 --- a/style.css +++ b/style.css @@ -46,6 +46,15 @@ html, body { overflow: hidden; background: var(--color-bg); font-family: var(--font-body); + /* Add critical status indicators */ + .critical-down { + background: #ff4466 !important; + border: 2px solid #ff4466 !important; + } + .critical-up { + background: #4af0c0 !important; + border: 2px solid #4af0c0 !important; + } color: var(--color-text); -webkit-font-smoothing: antialiased; }