diff --git a/.windsurf/workflows/audit-repo-health.md b/.windsurf/workflows/audit-repo-health.md new file mode 100644 index 00000000..5625a79b --- /dev/null +++ b/.windsurf/workflows/audit-repo-health.md @@ -0,0 +1,268 @@ +--- +description: Cross-repo health audit — verify pnpm config, Dockerfiles, next.config.ts, and workspace consistency +--- + +# Cross-Repo Health Audit + +Systematically verify consistency across all ByteLyst product repos. Catches drift in pnpm config, Dockerfiles, next.config.ts, and workspace setup. + +**Run this after:** pnpm migrations, Dockerfile changes, @bytelyst/\* package additions, or periodic maintenance. + +## 1. Check packageManager field in all root package.json files + +// turbo + +```bash +REPOS_DIR="/Users/sd9235/code/mygh" +echo "=== packageManager in root package.json ===" +for repo in \ + learning_ai_common_plat \ + learning_voice_ai_agent \ + learning_ai_clock \ + learning_ai_fastgap \ + learning_ai_jarvis_jr \ + learning_ai_peakpulse \ + learning_ai_notes \ + learning_ai_flowmonk \ + learning_ai_trails \ + learning_ai_local_memory_gpt; do + printf "%-40s " "$repo:" + grep '"packageManager"' "$REPOS_DIR/$repo/package.json" 2>/dev/null || echo "MISSING" +done +``` + +Expect: all repos show `"packageManager": "pnpm@10.6.5"`. Fix any MISSING entries. + +## 2. Check node_modules in .gitignore + +// turbo + +```bash +REPOS_DIR="/Users/sd9235/code/mygh" +echo "=== node_modules in .gitignore ===" +for repo in \ + learning_ai_common_plat \ + learning_voice_ai_agent \ + learning_ai_clock \ + learning_ai_fastgap \ + learning_ai_jarvis_jr \ + learning_ai_peakpulse \ + learning_ai_notes \ + learning_ai_flowmonk \ + learning_ai_trails \ + learning_ai_local_memory_gpt; do + printf "%-40s " "$repo:" + grep -c 'node_modules' "$REPOS_DIR/$repo/.gitignore" 2>/dev/null || echo "MISSING" +done +``` + +Expect: all repos have at least 1 match. Fix any with 0 or MISSING. + +## 3. Check .dockerignore exists and does NOT exclude .docker-deps + +// turbo + +```bash +REPOS_DIR="/Users/sd9235/code/mygh" +echo "=== .dockerignore health ===" +for repo in \ + learning_voice_ai_agent \ + learning_ai_clock \ + learning_ai_fastgap \ + learning_ai_jarvis_jr \ + learning_ai_peakpulse \ + learning_ai_notes \ + learning_ai_flowmonk \ + learning_ai_trails \ + learning_ai_local_memory_gpt; do + di="$REPOS_DIR/$repo/.dockerignore" + if [ ! -f "$di" ]; then + echo "$repo: MISSING .dockerignore" + elif grep -q 'docker-deps' "$di"; then + echo "$repo: BUG — .dockerignore excludes .docker-deps" + else + echo "$repo: OK" + fi +done +``` + +Expect: all OK. Any BUG entries will break Docker builds. + +## 4. Check stale package-lock.json files + +// turbo + +```bash +REPOS_DIR="/Users/sd9235/code/mygh" +echo "=== Stale package-lock.json ===" +for repo in \ + learning_voice_ai_agent \ + learning_ai_clock \ + learning_ai_fastgap \ + learning_ai_jarvis_jr \ + learning_ai_peakpulse \ + learning_ai_notes \ + learning_ai_flowmonk \ + learning_ai_trails \ + learning_ai_local_memory_gpt; do + found=$(find "$REPOS_DIR/$repo" -name "package-lock.json" -not -path "*/node_modules/*" 2>/dev/null) + if [ -n "$found" ]; then echo "STALE: $found"; fi +done +echo "(empty = all clean)" +``` + +Expect: no output. Remove any stale lockfiles found. + +## 5. Check Dockerfiles use node:22-slim and have NODE_TLS + +// turbo + +```bash +REPOS_DIR="/Users/sd9235/code/mygh" +echo "=== Dockerfile base image + NODE_TLS ===" +for repo in \ + learning_voice_ai_agent \ + learning_ai_clock \ + learning_ai_fastgap \ + learning_ai_jarvis_jr \ + learning_ai_peakpulse \ + learning_ai_notes \ + learning_ai_flowmonk \ + learning_ai_trails \ + learning_ai_local_memory_gpt; do + for df in $(git -C "$REPOS_DIR/$repo" ls-files '*/Dockerfile' 2>/dev/null); do + full="$REPOS_DIR/$repo/$df" + base=$(grep -m1 '^FROM' "$full" | awk '{print $2}') + tls=$(grep -c 'NODE_TLS_REJECT_UNAUTHORIZED' "$full" 2>/dev/null) + status="OK" + [[ "$base" == *alpine* ]] && status="WARN:alpine" + [[ "$tls" == "0" && "$df" != *python* ]] && status="$status WARN:no-NODE_TLS" + echo "$repo/$df: base=$base tls=$tls $status" + done +done +``` + +Expect: all use `node:22-slim`, all have `NODE_TLS` refs > 0. Fix any WARN entries. + +## 6. Check next.config.ts has transpilePackages + symlinks + +// turbo + +```bash +REPOS_DIR="/Users/sd9235/code/mygh" +echo "=== next.config.ts: transpilePackages + symlinks ===" +for repo in \ + learning_voice_ai_agent \ + learning_ai_clock \ + learning_ai_fastgap \ + learning_ai_jarvis_jr \ + learning_ai_notes \ + learning_ai_trails \ + learning_ai_local_memory_gpt; do + for cfg in $(find "$REPOS_DIR/$repo" -maxdepth 2 -name "next.config.ts" -not -path "*/node_modules/*" 2>/dev/null); do + relpath="${cfg#$REPOS_DIR/}" + tp=$(grep -c 'transpilePackages' "$cfg") + sl=$(grep -c 'symlinks' "$cfg") + status="OK" + [[ "$tp" == "0" ]] && status="MISSING:transpilePackages" + [[ "$sl" == "0" ]] && status="$status MISSING:symlinks" + echo "$relpath: transpile=$tp symlinks=$sl $status" + done +done +``` + +Expect: all show transpile>0 and symlinks>0. Fix any MISSING entries. + +## 7. Check pnpm-workspace.yaml includes common-plat packages + +// turbo + +```bash +REPOS_DIR="/Users/sd9235/code/mygh" +echo "=== pnpm-workspace.yaml includes common-plat ===" +for repo in \ + learning_voice_ai_agent \ + learning_ai_clock \ + learning_ai_fastgap \ + learning_ai_jarvis_jr \ + learning_ai_peakpulse \ + learning_ai_notes \ + learning_ai_flowmonk \ + learning_ai_trails \ + learning_ai_local_memory_gpt; do + ws="$REPOS_DIR/$repo/pnpm-workspace.yaml" + if [ ! -f "$ws" ]; then + echo "$repo: MISSING pnpm-workspace.yaml" + elif grep -q 'common_plat' "$ws"; then + echo "$repo: OK" + else + echo "$repo: MISSING common-plat in workspace" + fi +done +``` + +Expect: all OK. Fix any MISSING entries. + +## 8. Check docker-prep.sh uses shared prep-consumer + +// turbo + +```bash +REPOS_DIR="/Users/sd9235/code/mygh" +echo "=== docker-prep.sh uses shared prep-consumer ===" +for repo in \ + learning_voice_ai_agent \ + learning_ai_clock \ + learning_ai_fastgap \ + learning_ai_jarvis_jr \ + learning_ai_peakpulse \ + learning_ai_notes \ + learning_ai_flowmonk \ + learning_ai_trails \ + learning_ai_local_memory_gpt; do + script="$REPOS_DIR/$repo/scripts/docker-prep.sh" + if [ ! -f "$script" ]; then + echo "$repo: NO docker-prep.sh" + elif grep -q 'prep-consumer' "$script"; then + echo "$repo: OK (shared wrapper)" + else + echo "$repo: WARN — legacy docker-prep.sh" + fi +done +``` + +Expect: all OK. Legacy scripts should be replaced with the shared wrapper. + +## 9. Check verify scripts reference correct package filter names + +// turbo + +```bash +REPOS_DIR="/Users/sd9235/code/mygh" +echo "=== Root verify scripts ===" +for repo in \ + learning_voice_ai_agent \ + learning_ai_clock \ + learning_ai_fastgap \ + learning_ai_jarvis_jr \ + learning_ai_peakpulse \ + learning_ai_notes \ + learning_ai_flowmonk \ + learning_ai_trails \ + learning_ai_local_memory_gpt; do + printf "%-40s " "$repo:" + node -e "const p=require('$REPOS_DIR/$repo/package.json'); console.log(p.scripts?.verify || 'NONE')" 2>/dev/null +done +``` + +Review output manually — ensure `--filter` names match actual package names in sub-packages. + +## 10. Summarize findings and fix + +For each issue found: + +1. Fix the file in the affected repo +2. Commit with message: `fix(repo): ` +3. Push to origin + +Run `/gitea-ci` after all fixes to verify full CI passes. diff --git a/.windsurf/workflows/docker-smoke-test.md b/.windsurf/workflows/docker-smoke-test.md new file mode 100644 index 00000000..806a8605 --- /dev/null +++ b/.windsurf/workflows/docker-smoke-test.md @@ -0,0 +1,69 @@ +--- +description: Docker smoke test — prep, build, and verify all Dockerfiles in the current repo +--- + +# Docker Smoke Test + +Build and verify all Dockerfiles in the current product repo. Runs docker-prep, builds each image, then restores package.json files. + +**Prerequisite:** Docker Desktop must be running. The current repo must have `scripts/docker-prep.sh`. + +## 1. Identify the repo and its Dockerfiles + +// turbo + +```bash +REPO_DIR="$(pwd)" +REPO_NAME="$(basename "$REPO_DIR")" +echo "Repo: $REPO_NAME" +echo "Dockerfiles:" +find "$REPO_DIR" -maxdepth 2 -name "Dockerfile" -not -path "*/node_modules/*" | sort +``` + +## 2. Run docker-prep to pack @bytelyst/\* tarballs + +```bash +bash scripts/docker-prep.sh +``` + +## 3. Build each Dockerfile + +Build each Dockerfile found in the repo. The build context is always the repo root (`.`). +Tag images as `:smoke-test` for easy cleanup. + +For each Dockerfile found in step 1, run: + +```bash +# Example for backend: +docker build -f backend/Dockerfile -t "$(basename $(pwd))-backend:smoke-test" . 2>&1 | tail -20 + +# Example for web: +docker build -f web/Dockerfile -t "$(basename $(pwd))-web:smoke-test" . 2>&1 | tail -20 +``` + +Adapt the `-f` path based on actual Dockerfile locations from step 1. +If a build fails, stop and investigate the error before continuing. + +## 4. Restore package.json files + +```bash +bash scripts/docker-prep.sh --restore +``` + +## 5. Report results + +Summarize which images built successfully and which failed. +If all passed, the repo's Docker setup is healthy. + +## 6. (Optional) Cleanup smoke-test images + +```bash +docker images --filter "reference=*:smoke-test" --format "{{.Repository}}:{{.Tag}}" | xargs -r docker rmi +``` + +## Common Failures + +- **`.docker-deps` not found:** Run step 2 first, and ensure `.dockerignore` does NOT exclude `.docker-deps` +- **Google Fonts / TLS error:** Ensure `ENV NODE_TLS_REJECT_UNAUTHORIZED=0` is in the builder stage +- **Native module build failure:** Add `python3 make g++` to `RUN apt-get install` in the builder stage +- **`public/` not found:** Remove the `COPY public` line if the web app has no `public/` directory diff --git a/.windsurf/workflows/verify-all-backends.md b/.windsurf/workflows/verify-all-backends.md new file mode 100644 index 00000000..fdbbd45b --- /dev/null +++ b/.windsurf/workflows/verify-all-backends.md @@ -0,0 +1,110 @@ +--- +description: Quick local typecheck + test + build across all product backends (fast complement to /gitea-ci) +--- + +# Verify All Backends (Local) + +Run typecheck, test, and build across all product backends locally — without needing Gitea. +Use this for fast pre-push validation. For full CI verification, use `/gitea-ci` instead. + +**When to use:** + +- After modifying a `@bytelyst/*` shared package +- Before a bulk push to all repos +- Quick health check without waiting for Gitea runner queue + +## 1. Build common-plat packages first (dependency for all backends) + +```bash +cd /Users/sd9235/code/mygh/learning_ai_common_plat && pnpm build +``` + +## 2. Verify all product backends + +Run typecheck + test + build for each backend. Stops on first failure. + +```bash +REPOS_DIR="/Users/sd9235/code/mygh" +PASSED=0 +FAILED=0 +FAILURES="" + +for entry in \ + "learning_ai_notes:@notelett/backend" \ + "learning_ai_local_memory_gpt:@localmemgpt/backend" \ + "learning_ai_trails:@actiontrail/backend" \ + "learning_ai_fastgap:@nomgap/backend" \ + "learning_ai_clock:@chronomind/backend" \ + "learning_ai_jarvis_jr:@jarvisjr/backend" \ + "learning_ai_peakpulse:@peakpulse/backend" \ + "learning_voice_ai_agent:@lysnrai/backend" \ + "learning_ai_flowmonk:@flowmonk/backend" \ + "learning_ai_notes:@notelett/backend"; do + + repo="${entry%%:*}" + filter="${entry##*:}" + echo "" + echo "━━━ $repo ($filter) ━━━" + + cd "$REPOS_DIR/$repo" + if pnpm --filter "$filter" run typecheck 2>&1 | tail -3 && \ + pnpm --filter "$filter" run test 2>&1 | tail -5 && \ + pnpm --filter "$filter" run build 2>&1 | tail -3; then + echo "✅ $repo PASSED" + PASSED=$((PASSED + 1)) + else + echo "❌ $repo FAILED" + FAILED=$((FAILED + 1)) + FAILURES="$FAILURES\n - $repo" + fi +done + +echo "" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "✅ Passed: $PASSED" +echo "❌ Failed: $FAILED" +if [ -n "$FAILURES" ]; then + echo -e "Failures:$FAILURES" +fi +``` + +## 3. (Optional) Verify all web apps too + +Web builds take longer. Only run if you suspect web-side breakage. + +```bash +REPOS_DIR="/Users/sd9235/code/mygh" + +for entry in \ + "learning_ai_notes:@notelett/web" \ + "learning_ai_local_memory_gpt:@localmemgpt/web" \ + "learning_ai_trails:@actiontrail/web" \ + "learning_ai_fastgap:@nomgap/web" \ + "learning_ai_clock:web" \ + "learning_ai_jarvis_jr:jarvisjr-web" \ + "learning_voice_ai_agent:user-dashboard-web" \ + "learning_ai_flowmonk:@flowmonk/web"; do + + repo="${entry%%:*}" + filter="${entry##*:}" + echo "" + echo "━━━ $repo web ($filter) ━━━" + + cd "$REPOS_DIR/$repo" + if pnpm --filter "$filter" run typecheck 2>&1 | tail -3 && \ + pnpm --filter "$filter" run build 2>&1 | tail -5; then + echo "✅ $repo web PASSED" + else + echo "❌ $repo web FAILED" + fi +done +``` + +## 4. After fixing issues + +If any backend/web failed: + +1. Fix the issue in the affected repo +2. Re-run the failing step only to confirm +3. Commit with: `fix(scope): description` +4. Run `/gitea-ci` for full CI verification