diff --git a/.gitea/workflows/lint-build.yml b/.gitea/workflows/lint-build.yml new file mode 100644 index 0000000..c9b82ad --- /dev/null +++ b/.gitea/workflows/lint-build.yml @@ -0,0 +1,40 @@ +name: Lint and Build Checks + +on: + push: + branches: [main] + paths: + - 'src/**' + schedule: + # 5:00 PM CST daily. Gitea schedules use UTC. + # CST (UTC-6): 23:00 UTC. + # During CDT this runs at 6:00 PM America/Chicago unless the cron is adjusted. + - cron: '0 23 * * *' + workflow_dispatch: + +jobs: + lint-test-build: + name: Lint, Test, and Build + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '24' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Lint + run: npm run lint + + - name: Test + run: npm run test -- --runInBand + + - name: Build web and Electron assets + run: npm run electron:build diff --git a/.gitea/workflows/nightly-architectural-sweep.yml b/.gitea/workflows/nightly-architectural-sweep.yml new file mode 100644 index 0000000..50990dd --- /dev/null +++ b/.gitea/workflows/nightly-architectural-sweep.yml @@ -0,0 +1,119 @@ +name: Nightly Architectural Sweep + +on: + schedule: + # 4:00 AM CST daily, inspired by the Aarete DocyAI architectural sweep cadence. + # Gitea schedules use UTC. CST (UTC-6): 10:00 UTC. + # During CDT this runs at 5:00 AM America/Chicago unless the cron is adjusted. + - cron: '0 10 * * *' + workflow_dispatch: + +jobs: + create-architectural-sweep-issue: + name: Create Architectural Sweep Issue + runs-on: ubuntu-latest + + steps: + - name: Create architectural sweep issue + run: | + python3 - <<'PYEOF' + import json + import urllib.request + from datetime import datetime, timezone + + gitea_api = "http://100.79.253.19:3000/api/v1" + repo = "${{ gitea.repository }}" + token = "${{ gitea.token }}" + run_url = "http://100.79.253.19:3000/${{ gitea.repository }}/actions/runs/${{ gitea.run_id }}" + today = datetime.now(timezone.utc).strftime("%Y-%m-%d") + + body = f"""## Architectural Sweep - {today} + + Daily architecture review for **Throne of the Bone King**. + + This follows the Aarete DocyAI sweep pattern: each domain should be reviewed independently, findings should be posted as separate comments, and critical issues should become focused follow-up tickets before moving on. + + **Action run:** {run_url} + + --- + + > Agent instructions: + > + > Post a separate comment for each domain as soon as that domain is complete. + > Title comments with the domain and date, for example `Architecture Findings - {today}`. + > Link follow-up issues from this sweep and include file paths or commands where relevant. + + --- + + ### 1. Shared App Architecture + + - [ ] Review `App.tsx`, `src/navigation/AppNavigator.tsx`, and `src/components/GameViewport.tsx`. + - [ ] Confirm shared React Native code is still platform-safe and free of DOM-only APIs. + - [ ] Check whether navigation, transitions, safe area, and fixed landscape viewport boundaries remain cleanly separated. + - [ ] Identify any component that is taking on too many responsibilities. + + ### 2. State and Persistence + + - [ ] Review Zustand stores in `src/state/`. + - [ ] Confirm persisted route and settings state can recover from stale or legacy values. + - [ ] Check that platform storage remains isolated to `persistStorage.ts` and `persistStorage.web.ts`. + - [ ] Look for race conditions between route transitions, socket connection updates, and Toolkit content refreshes. + + ### 3. Toolkit and Socket Sync + + - [ ] Review `src/screens/ToolkitScreen.tsx`, `src/socket/toolkitSocketClient.ts`, and `socket/server.mjs`. + - [ ] Confirm Toolkit access is still Browser-resolution and socket-gated. + - [ ] Verify content read/save/change/error paths remain typed and tested. + - [ ] Identify the next volatile gameplay content area that should use the socket-backed JSON pattern. + + ### 4. Data, Content, and Gameplay Loops + + - [ ] Review `src/data/`, `wiki/`, and Toolkit route coverage. + - [ ] Check that petitioners, rulings, seed logic, resources, factions, flags, story arcs, lore, audio, endings, and references still map to future gameplay loops. + - [ ] Identify mismatches between wiki expectations and app/toolkit scaffolding. + - [ ] Recommend one schema or fixture that should be formalized next. + + ### 5. UI, Layout, and Assets + + - [ ] Inspect Home, Settings, Policies, Credits, and Toolkit layouts against fixed landscape resolutions. + - [ ] Check for accidental scrolling, clipped text, oversized controls, or insufficient contrast. + - [ ] Review `src/assets/` usage, font loading, favicon, menu art, and background music. + - [ ] Flag any asset size or bundling risk that affects web/Electron builds. + + ### 6. Test and Build Health + + - [ ] Run or review `npm run lint`. + - [ ] Run or review `npm run test -- --runInBand`. + - [ ] Run or review `npm run electron:build`. + - [ ] Identify missing tests for any recent architecture change. + - [ ] Scan for TODO/FIXME/HACK/TEMP, empty catches, broad casts, dead exports, or stale docs. + + ### 7. Technical Debt and Next Actions + + - [ ] List concrete architecture risks with severity and owner recommendation. + - [ ] Estimate effort for each fix as S, M, or L. + - [ ] Create follow-up issues for any item that should not wait for the next sweep. + - [ ] Pick the single most valuable architecture improvement for the next work session. + + --- + + _Auto-generated nightly by Gitea Actions._""" + + payload = { + "title": f"Architectural Sweep - {today}", + "body": body, + } + + req = urllib.request.Request( + f"{gitea_api}/repos/{repo}/issues", + data=json.dumps(payload).encode("utf-8"), + headers={ + "Authorization": f"token {token}", + "Content-Type": "application/json", + }, + method="POST", + ) + with urllib.request.urlopen(req, timeout=20) as response: + result = json.loads(response.read()) + print(f"Created issue #{result['number']}: {result['html_url']}") + PYEOF diff --git a/.gitea/workflows/weekly-regression-review.yml b/.gitea/workflows/weekly-regression-review.yml new file mode 100644 index 0000000..5392962 --- /dev/null +++ b/.gitea/workflows/weekly-regression-review.yml @@ -0,0 +1,110 @@ +name: Weekly Regression and Review + +on: + schedule: + # Friday 5:00 AM CST. Gitea schedules use UTC. + # CST (UTC-6): 11:00 UTC. + # During CDT this runs at 6:00 AM America/Chicago unless the cron is adjusted. + - cron: '0 11 * * 5' + workflow_dispatch: + +jobs: + create-regression-review-issue: + name: Create Regression & Review Issue + runs-on: ubuntu-latest + + steps: + - name: Create weekly review issue + run: | + python3 - <<'PYEOF' + import json + import urllib.request + from datetime import datetime, timezone + + gitea_api = "http://100.79.253.19:3000/api/v1" + repo = "${{ gitea.repository }}" + token = "${{ gitea.token }}" + run_url = "http://100.79.253.19:3000/${{ gitea.repository }}/actions/runs/${{ gitea.run_id }}" + today = datetime.now(timezone.utc).strftime("%Y-%m-%d") + + body = f"""## Regression & Review - {today} + + Weekly checkpoint for moving **Throne of the Bone King** forward without letting regressions or vague design debt accumulate. + + **Action run:** {run_url} + + --- + + > Agent instructions: + > + > Post a separate comment for each completed section below. + > If any section exposes a concrete bug, create a focused follow-up issue and link it from this review. + > Keep notes practical: include affected files, screenshots when useful, and the next smallest shippable action. + + --- + + ### 1. Regression Smoke Pass + + - [ ] Run `npm run lint`. + - [ ] Run `npm run test -- --runInBand`. + - [ ] Run `npm run web:build`. + - [ ] Run `npm run electron:build`. + - [ ] Start `npm run dev:all` and confirm the browser app loads. + - [ ] Confirm Toolkit becomes clickable only when resolution is Browser and socket is connected. + - [ ] Confirm route persistence survives refresh on Home, Settings, Policies, Credits, and Toolkit. + + ### 2. Game Loop Readiness + + - [ ] Review New Game and Saves placeholders and identify the next implementation slice. + - [ ] Verify the planned daily loop is still represented in Toolkit sections: Opening, Petitioners, Rulings, Seed, Resources, Map, Factions, Flags, Story, Lore, Audio, Credits, Endings, References. + - [ ] Identify one gameplay loop that can be made testable with JSON fixtures this week. + - [ ] Check whether content should stay in JSON or move toward a stronger schema. + + ### 3. Settings, Resolution, and Audio + + - [ ] Test Browser and phone-like resolution modes. + - [ ] Verify mute, master, music, ambience, speech, and SFX settings persist. + - [ ] Check that background music loops and respects mute/master/music values. + - [ ] Identify any layout that scrolls or clips in fixed landscape sizes. + + ### 4. Toolkit Content Review + + - [ ] Review `src/data/credits.json` and the Toolkit Credits display. + - [ ] Confirm socket read/save/change behavior is still covered by tests. + - [ ] Identify the next Toolkit content resource that should get typed JSON support. + - [ ] List any authoring forms that are now justified, but do not implement them from this issue. + + ### 5. Art, Fonts, and Presentation + + - [ ] Confirm the menu background, landing background, favicon, fonts, and audio assets render correctly. + - [ ] Identify any oversized assets that should be optimized. + - [ ] Check the main menu hierarchy, button contrast, and Toolkit distinction. + + ### 6. Backlog Decisions + + - [ ] Pick the top three follow-up issues that most directly advance the playable game. + - [ ] Close or rewrite stale issues that no longer match current architecture. + - [ ] Make sure each new issue has a small, testable outcome. + + --- + + _Auto-generated weekly by Gitea Actions._""" + + payload = { + "title": f"Regression & Review - {today}", + "body": body, + } + + req = urllib.request.Request( + f"{gitea_api}/repos/{repo}/issues", + data=json.dumps(payload).encode("utf-8"), + headers={ + "Authorization": f"token {token}", + "Content-Type": "application/json", + }, + method="POST", + ) + with urllib.request.urlopen(req, timeout=20) as response: + result = json.loads(response.read()) + print(f"Created issue #{result['number']}: {result['html_url']}") + PYEOF