commit a9db23dfa40ed7901ac76db59c8d288c192f0715 Author: goboss Date: Thu Apr 30 14:18:23 2026 +0000 initial: tubev infrastructure docs - CLAUDE.md lean entry-point + index - BOT_WORKFLOW.md dispatch rules + no-make-work + recommendations cadence - SITES.md 14 ports inventory - SYNC_WORKFLOW.md 2 sync paradigms - MODULES.md module map + DEL_/test/obfuscated flags - REFACTOR_RULES.md REFACTOR vs CLEANUP vs BUG vs FEATURE - RECOMMENDATIONS.md initial backlog from gocc1+2+3+4 audits 2026-04-30 - docs/roles/ 4 bot roles diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1b07d5e --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +.vscode/ +.idea/ +.DS_Store +*.swp +*~ +*.log +*.bak +.env +.env.local diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..f96b9bd --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,86 @@ +# tubev + +Multi-site adult tube infrastructure — **frontend-only** scope (templates / CSS / JS). Backend (OpenResty + Lua) — у розробника, не в нашому доступі. + +## Сайти + +14 портів у `/home/w4/backup_/`. Повна таблиця: **[docs/SITES.md](docs/SITES.md)**. + +## Stack + +- Templates: **etlua** (Lua templating, OpenResty environment) +- CSS: критичний inline `views/css/css_*.etlua` + deferred `static/css/` +- JS: `static/js/{c2, auth, comment, profile_index, main, ...}.{js,min.js}` +- Video player: `static/videojs-v10/` + +## Workflow (де що правити) + +1. **Edit:** `~/backup_/views/` (наша зона; кожен порт = окремий git repo) +2. **Sync:** `~/backup_/sync.sh` копіює з prod (`/home/nosfortube/frontend_/`) → backup. Деталі: **[docs/SYNC_WORKFLOW.md](docs/SYNC_WORKFLOW.md)** +3. **Push to prod:** через git remote → developer-side. **goboss НЕ пушить**, тільки локальні коміти у власному worktree +4. **`/home/nosfortube/`** — це prod, читати можна, **писати — НІКОЛИ** + +## Команди + +```bash +~/start-devs.sh boss # старт goboss +~/start-devs.sh gocc # старт gocc1-4 +~/bin/trigger-bots [gocc{N}] # тригер нової task +~/bin/restart-bots [gocc{N}] # повний reset (kill+start+wait+trigger) +~/bin/clear-bots [gocc{N}] # /clear context (topic switch) +git pull --rebase # ЗАВЖДИ перед роботою у backup_/ +``` + +## Команда (ролі ботів) + +| Бот | Tool access | Domain | +|-----|-------------|--------| +| **goboss** | All | Planner + dispatch (не push до prod, тільки local commits) | +| **gocc1** | Read-only | Code audit + regression | +| **gocc2** | Read-only | Test gap + endpoint smoke | +| **gocc3** | Edit/Write/commit (no push) | Frontend writer (templates/CSS/UI) | +| **gocc4** | Edit/Write/commit (no push) | Architect/refactor (services/lib/scripts) | + +**2 read-only + 2 writer** — read-only safety net, писателі паралельно. + +Деталі: **[docs/roles/](docs/roles/)** | Workflow rules: **[docs/BOT_WORKFLOW.md](docs/BOT_WORKFLOW.md)** + +## Правила (КРИТИЧНІ) + +### No make-work +**НЕ давати ботам задачі з пустого в порожнє.** Кожен dispatch має конкретну причину: новий audit area, conkretne виявлений bug, follow-up з reportу. Якщо нема такої причини — bot пише `[bot] Чекаю.` і чекає. Cross-audit / regression test / research **тільки коли є concrete trigger**. + +### No-touch zones +- `/home/nosfortube/` — production source, READ ONLY +- `/etc/nginx/`, `/var/www/` — server configs, поза scope +- Backend Lua код розробника — нема доступу + +### Refactor vs Cleanup vs Bug-fix vs Feature +Чітко розрізняти. Деталі: **[docs/REFACTOR_RULES.md](docs/REFACTOR_RULES.md)**. + +### Recommendations not plans +Виявлені refactor/security/cleanup candidates → **[docs/RECOMMENDATIONS.md](docs/RECOMMENDATIONS.md)** як **рекомендації**, не план. Робимо ТІЛЬКИ коли розробник скаже. goboss періодично нагадує про unprocessed items. + +### No hardcodes у нових патчах +Перш ніж писати літерал (URL, домен, GA ID, magic number) — `grep` чи вже є у `views/config/` чи аналогічному місці. Існує — import/include. Нема — додай як параметр у `views/config/site.lua` (якщо буде створено) і потім use. + +## Doc Index + +| Файл | Призначення | +|------|-------------| +| **[docs/SITES.md](docs/SITES.md)** | Таблиця 14 портів × домен × cluster × outlier flags | +| **[docs/SYNC_WORKFLOW.md](docs/SYNC_WORKFLOW.md)** | Як sync.sh працює, 2 парадигми, як додати порт | +| **[docs/MODULES.md](docs/MODULES.md)** | Карта `views/modules/*.etlua` × presence × DEL_/test/deprecated flags | +| **[docs/REFACTOR_RULES.md](docs/REFACTOR_RULES.md)** | Що таке REFACTOR vs CLEANUP vs BUG vs FEATURE | +| **[docs/RECOMMENDATIONS.md](docs/RECOMMENDATIONS.md)** | Backlog refactor/cleanup/security candidates як рекомендації | +| **[docs/BOT_WORKFLOW.md](docs/BOT_WORKFLOW.md)** | Bot dispatch + reporting + escalation rules | +| **[docs/roles/](docs/roles/)** | Ролі gocc1-4 | + +Файли наповнюємо/оновлюємо по мірі знахідок. CLAUDE.md = тонкий entry-point + index. + +## Communication +- Українською, коротко, по суті +- Боти приймають **ТІЛЬКИ від `goboss:`** +- TIMESTAMP формат: `[bot YYYY-MM-DD HH:MM] Task ID: XXX` +- Task vs Report Task ID порівнюються **рядково**, не по змісту +- Signal через PostToolUse hook автоматично після Write `~/comms/{bot}-report.md` diff --git a/docs/BOT_WORKFLOW.md b/docs/BOT_WORKFLOW.md new file mode 100644 index 0000000..7f536ac --- /dev/null +++ b/docs/BOT_WORKFLOW.md @@ -0,0 +1,234 @@ +# Bot & goboss workflow — обов'язкові правила + +Durable spec для всіх Claude-ботів (gocc1..4) і goboss-планувальника. Project-agnostic. + +**Головне правило:** не патчимо "на око". Думай → план → роби. No hardcodes, no patches, SSOT-first, architectural over patches. + +## NO MAKE-WORK rule (CRITICAL) + +**НЕ давати ботам задачі з пустого в порожнє.** Кожен dispatch має конкретну причину: +- ✅ developer запитав audit / refactor / fix +- ✅ HIGH severity finding з попереднього report потребує follow-up verify +- ✅ нова area не покрита попередніми звітами (concrete gap) +- ✅ regression/test після коміту з реальними змінами + +**Не валідні тригери (НЕ робити):** +- ❌ "давай ще раз перевіримо" без нової причини +- ❌ "audit того ж самого через тиждень — раптом щось зміниться" +- ❌ make-work cross-audit / regression / research коли нічого не змінилось +- ❌ дублювання попереднього task'у з той ж scope + +Якщо нема валідного тригера — task file = `Чекай.`. Не вигадуй роботу. + +## Recommendations cadence (для goboss) + +На початку кожної session goboss перевіряє `docs/RECOMMENDATIONS.md`: +- Скільки items OPEN по severity +- Що додано з last session +- Згадай developer-у (1 рядок: `📋 RECOMMENDATIONS: N OPEN (X HIGH, Y MEDIUM, Z LOW). Найпріоритетніше: ...`) +- НЕ виконуй items самостійно — чекай developer-go + +--- + +## Частина A — для goboss (planner) + +### A1. Планування перед dispatch + +Перед task file для бота goboss МУСИТЬ: + +1. **Scope** — one-liner: що зробити, які файли, який контракт. +2. **Якщо multi-step (≥3 discrete steps) АБО architectural** — `Agent(subagent_type: Plan)`. Результат — concrete step-by-step з critical files і trade-offs. +3. **Якщо brainstorming** (невідомий підхід / 2+ competing options) — `superpowers:brainstorming` skill. Записати decision + reasoning у task. +4. **SSOT check** — чи є вже helper/module для цього? Використовуй існуюче. +5. **Recent commits** — `git log --oneline -20` — щоб не дублювати. + +### A2. Architectural fixes, not patches + +Якщо помилка зустрічається 2+ рази з того ж root cause → REDESIGN, не FIX по одному разу. + +`feedback_architectural_not_patches` memory — якщо існує. + +### A3. Перевірка cherry-pick'ів + +Після cherry-pick bot-зміни: +1. Smoke (`pytest tests/test_.py -q`) +2. Full regression (`./run_tests.sh` або `pytest -q`) +3. ≥3 commits разом без verify → `gocc2` на drift-check audit +4. Push + verify health endpoint +5. Update `docs/ROADMAP.md` (якщо проект має) у тій самій сесії + +### A4. Code review після great IMPL + +Після кожного MAJOR step (refactor, new SSOT module, multi-file migration): +1. `Agent(superpowers:code-reviewer)` на результат +2. Передати: commit hash, changed files, task spec link +3. Issue → fix inline АБО queue follow-up PR + +--- + +## Частина B — для ботів (executor) + +### B1. Before coding — planning phase + +Перед першим code edit: +1. Прочитай task ПОВНІСТЮ. +2. Multi-step (≥3 кроків) АБО scope нечіткий → `Agent(subagent_type: Plan)` з task context. Plan = checklist. +3. Architectural decision → `superpowers:brainstorming` skill. `## Decision` block у report. +4. Unclear → ЗАПИТАЙ goboss (через partial report з `QUESTION:` block). НЕ ВГАДУЙ. + +### B2. No hardcodes — SSOT first + +Перед кожним новим літералом (path, model name, URL, retry count, language code): +1. `grep -rn "" config/ lib/` +2. Існує → IMPORT +3. Немає → додай у `config/.py` як module-level const, потім import + +Never: +- `API_KEYS = ['xxx']` у коді (use env) +- `DATA_DIR = '/var/lib/...'` у коді (use config) +- `MAX_RETRIES = 3` у двох файлах (extract до `config.retry`) + +### B3. No patches — architectural fixes + +Bug знайдено: +1. Root cause (не симптом) +2. Локальний → fix inline + regression test +3. ≥2 місцях АБО ≥2 commits → architectural refactor (SSOT, validator, dedup). НЕ копіюй fix у N місць. + +### B4. Test coverage + +Кожна нова public function / class / module: +- 1 smoke (happy path) +- 1 edge (empty/invalid/failure) +- 1 integration якщо side effects (DB, HTTP, FS) + +Test name: `tests/test__.py`. Новий endpoint = новий test. + +### B5. Pre-push code review + +Після commit, ДО report: +1. Re-read diff (`git diff HEAD~1`) +2. Constraint check проти task spec +3. Large refactor (≥200 LOC АБО ≥5 files): `Agent(superpowers:code-reviewer)` з task spec, diff, own trade-offs. +4. Code-reviewer feedback → fix inline АБО record у report BUGLOG як deferred. + +### B6. Report structure + +Кожен report МУСИТЬ мати у цьому порядку: +1. **Status** (READY / BLOCKED / FAILED) +2. **Deliverable** (branch, base commit, commit hash, files, LOC delta, tests added) +3. **Scope summary** (3-5 bullets) +4. **Decision notes** (якщо archi — варіант + чому) +5. **Test coverage** (per-module) +6. **Full regression** (pytest tail) +7. **Hardcode self-check** (grep — 0 hits) +8. **BUGLOG** (touched OR deferred) +9. **Deviation** (де відхилився від spec + чому) +10. **Signal** (filename for auto-hook trigger) + +--- + +## Частина C — task file template + +```markdown +# Task: + +**Assignee:** gocc () +**Origin:** +**Base:** `origin/main` @ `` + +## Workflow requirements (per docs/BOT_WORKFLOW.md) + +- **Before coding:** `Plan` agent якщо multi-step; `brainstorming` skill якщо archi +- **SSOT check:** grep existing constants; import not copy +- **After major step:** `Agent(superpowers:code-reviewer)` на commit+diff +- **No patches:** recurring bug = root cause refactor +- **Report:** 10 sections per §B6 + + +``` + +--- + +## Частина D — enforcement + exceptions + +### D1. Enforcement + +- Report без required sections (§B6) → goboss повертає `MISSING: ` +- Bot patch замість architectural → goboss queue додатковий PR на refactor +- Bot пропустив SSOT, hardcode landed → goboss inline-fix + memory update + +### D2. Exceptions (без планів) + +Не потрібно planning overhead для: +- Trivial 1-file fix (typo, rename, const update) +- READ-ONLY audit (план = task spec sections) +- Doc-only update +- Emergency rollback (`git revert` — явно) + +Bot вважає task — exception → ЗАПИШИ у report `## Planning skipped` з reasoning. goboss review. + +### D3. Rollback on violation + +Architectural violation post-merge (hardcode landed, patch замість refactor): +1. `git revert ` (not --force, not amend) +2. Dispatch новий PR з proper fix +3. Update `feedback_.md` memory + +--- + +## Частина E — operational procedures (goboss → bot dispatch) + +### E1. Порядок dispatch + +1. Запиши task у `~/comms/gocc{N}-task.md` з **унікальним Task ID**. +2. Тригер: `~/bin/trigger-bots gocc{N}` (або `~/bin/trigger-bots` для всіх). + +`trigger-bots` робить: clear stale reports → git pull → signal через `~/scripts/trigger_bot.sh` (flock-serialized, paste-buffer + dual-Enter + verify). + +### E2. Якщо бот не реагує + +- `❯` prompt — Claude процес мертвий +- НЕ Ctrl-C (вбиває Claude) +- Use `~/bin/restart-bots gocc{N}` — kill-session → start-devs → wait 20s → trigger одним скриптом + +### E3. Тригер ботів (нова задача) + +```bash +~/bin/trigger-bots # всі gocc1-4 +~/bin/trigger-bots gocc2 # один +~/bin/trigger-bots gocc1 gocc3 # subset +``` + +### E4. Повний перезапуск + +```bash +~/bin/restart-bots # всі: kill+start+wait+trigger +~/bin/restart-bots gocc4 # один +``` + +⛔ **НІКОЛИ ручний `tmux kill-session`** — використовуй `restart-bots`. + +### E5. Task ID правила + +- Кожна нова task = новий унікальний Task ID +- Формат: `[goboss YYYY-MM-DD] Task ID: НАЗВА-ЗАДАЧІ` +- Бот порівнює task Task ID vs report Task ID — якщо однакові → "Чекаю.", різні → виконує +- При restart — clear report files перед trigger (restart-bots робить автоматично) + +### E6. Context clear policy + +`~/bin/clear-bots` (per-bot subset) — використовуй коли: +- Новий епох незалежний від попереднього (different feature/area) +- Контекст ≥30% з 1M (бот сам пише `⚠️ CONTEXT HEAVY` у report) +- Послідовний follow-up на ту саму задачу — НЕ кліри + +### E7. Communication scripts (КАНОНІЧНІ) + +- `~/scripts/send_to_goboss.sh ""` — bot → goboss (flock, idle-wait, verify) +- `~/scripts/trigger_bot.sh ""` — goboss → bot (flock, idle-wait, verify) +- НІКОЛИ raw `tmux send-keys` для quoted text — guard блокує + +--- + +**Reference memories:** `feedback_bot_verification`, `feedback_pre_push_subagent`, `feedback_signal_flood_mutex`, `feedback_simple_no_details`, `reference_bot_comms`. diff --git a/docs/MODULES.md b/docs/MODULES.md new file mode 100644 index 0000000..7be2ae2 --- /dev/null +++ b/docs/MODULES.md @@ -0,0 +1,103 @@ +# tubev — Modules Map + +Модулі = `views/modules/*.etlua` partials що включаються через `<%= include … %>` у layout/page templates. + +## Канонічні модулі (присутні скрізь або майже) + +| Module | Sites Present | Reuse signal | Notes | +|--------|--------------:|--------------|-------| +| `video.etlua` | 14/14 | ❌ всі md5 різні (67-77% common lines) | **Top SSOT candidate** — найвища similarity, зберігає однакову data-loop структуру | +| `related_video.etlua` | 13/14 (no 8148) | ❌ всі md5 різні | structurally similar, candidates for shared partial | +| `recommended_video.etlua` | 13/14 (no 8148) | ❌ | те саме | +| `relink_videos.etlua` | 13/14 (no 8148) | ❌ | те саме | +| `cat_list_alpha.etlua` | 13/14 (no 8129) | mixed | | +| `cat_list_thumb.etlua` | 12/14 | ❌ всі md5 різні | + 5 варіантів з пробілами/"with ads" — потребує нормалізації | +| `lang.etlua` | 12/14 (no 8081, 8129, 8148) | 9 unique md5, 2 ідентичні | i18n switcher | +| `pager.etlua` | 10/14 | ✅ **3 unique md5, 7 ідентичні** | **Shared candidate** — вже фактично shared | +| `removed_notify.etlua` | 10/14 | ✅ **4 unique md5, 6 ідентичні** | **Shared candidate** — вже фактично shared | +| `paginator.etlua` | 10/14 | ❌ всі різні | + `paginator_old.etlua`, `paginator_ajax.etlua` варіанти | +| `donors.etlua` | 12/14 | ❌ всі md5 різні | | + +## Site-specific (тільки на 1 сайті) + +| Module | Site | Why | +|--------|------|-----| +| `profile_index.etlua` | 8081 | NL agego SPA-like, профілі користувачів — окрема архітектура | +| `profile_public.etlua` | 8081 | те саме | +| `profile_upload.etlua` | 8081 | те саме | +| `channel_list_thumb.etlua` | 8081 | unique to 8081 | +| `_cat_list_thumb.etlua` | 8081 | underscore-prefix variant | +| `related_top_channels.etlua` | 8081 | | +| `ga/ga.etlua` | 8081, 8112 | Google Analytics module | + +## DEL_* tombstones (24 файли × 6 сайтів) + +**Видалити при першій нагоді (XS task, ~15 хв).** Префікс `DEL_` явно signals tombstone, але файли досі живуть і шумлять у grep. + +| Module | Sites | +|--------|-------| +| `DEL_channel_id.etlua` | 8100, 8102, 8107, 8112, 8131, 8133 | +| `DEL_friend_list.etlua` | 8100, 8102, 8107, 8112, 8131, 8133 | +| `DEL_lang.etlua` | 8100, 8102, 8107, 8112, 8131, 8133 | +| `DEL_lang_mob.etlua` | 8100, 8102, 8107, 8112, 8131, 8133 | + +Деталі: **[RECOMMENDATIONS.md](RECOMMENDATIONS.md)** #2. + +## `_test.etlua` / .test.js (sandbox у prod tree) + +Tests не повинні жити у prod. Перенести у `/tests/` або видалити. + +| File | Sites | +|------|-------| +| `cat_list_thumb_test.etlua` | 8084, 8085 | +| `cat_index_test.etlua` | 8084, 8085 | +| `main_list_test.etlua` | 8084, 8085 | +| `video_test.etlua` | 8084, 8085 | +| `counters.min.test.js` | 8133 | + +## Backup-via-rename артефакти (~30 файлів) + +**Видалити при першій нагоді (S task, ~1h).** Файлові імена з пробілами ламають shell scripts. Версії повинні бути у git, не у filename. + +| Pattern | Examples | Sites | +|---------|----------|-------| +| `header copy bongo link 25_10_22.etlua` | (один з typo `bogolink` на 8112) | 8084, 8085, 8112, 8126, 8131 | +| `* copy_ads_actual.etlua` | `id_index copy_ads_actual.etlua` | 8084, 8085 | +| `* copy.etlua/.js` | `my copy.js`, `machine copy.js` | 8 sites | +| `* with ads.etlua` / `* without ads.etlua` | `cat_list_thumb with ads.etlua` | 8112 (10 файлів) | +| `* with titles.etlua` | | 8100 (5 файлів) | +| `untitled file` | IDE saved-no-name | 8126 (×2) | +| `*_old/`, `*_bak*` | `js_old/`, `img_old/`, `paginator_old.etlua`, `layout_bak_25-05-18.etlua` | 8085 (dirs), 8086, 8100 | +| `asdadsasd.html`, `del___search_top.etlua` | obvious garbage | 8086 | + +## Obfuscated JS (10 файлів — потребує origin audit) + +**Random naming підозріло на adblock-bypass scripts.** Не у sync.sh. Походження невідоме. + +| File | Site | +|------|------| +| `9qFdXQ7.js` | 8131 | +| `gD0A3.js` | 8131 | +| `PxqbeCb.js` | 8131 | +| `gk5LT.js` | 8107 | +| `f4T4s.js` | 8126 | +| `aOKM9.js` | 8085 | +| `N7Ym4F.js` | 8084 | +| `k3KL5.js` | 8102 | +| `qDap9.js` | 8112 | +| `c24c4cd9.js` | (неідентифіковано) | +| `popa.js`, `mo.js` | (неідентифіковано) | + +**Питання до розробника:** ваші adblock-bypass payloads, legacy ad scripts, чи невідомий drop? + +## Banners модулі + +`views/modules/banners/` — окрема зона з ~30+ файлів native_adspy variants, embed_*adspy classes. Site-specific. Map поки не побудовано (P4 doc). + +## Refactor candidate: shared base partial + +`video.etlua` — найкращий кандидат на extraction до shared partial з per-site CSS theme overrides. Деталі: **[RECOMMENDATIONS.md](RECOMMENDATIONS.md)** #4. + +--- + +*Source: gocc2 + gocc3 + gocc4 audits 2026-04-30.* diff --git a/docs/RECOMMENDATIONS.md b/docs/RECOMMENDATIONS.md new file mode 100644 index 0000000..03c05dc --- /dev/null +++ b/docs/RECOMMENDATIONS.md @@ -0,0 +1,230 @@ +# tubev — Recommendations Backlog + +**⚠️ Це РЕКОМЕНДАЦІЇ, не PLANS.** Кожен пункт виявлено через audit (gocc1+2+3+4 на 2026-04-30) і чекає developer-go перед виконанням. goboss періодично нагадує про unprocessed items на session start. + +Типи: **REFACTOR** (структурна зміна без зміни поведінки) / **CLEANUP** (видалення dead code) / **BUG** (неправильна поведінка) / **FEATURE** (нове). Деталі: [REFACTOR_RULES.md](REFACTOR_RULES.md). + +--- + +## 🚨 HIGH severity — Security + +### S1. SRI / integrity для third-party JS *(BUG/FEATURE)* +**Where:** layout*.etlua усіх 14 сайтів +**Files:** `ajax.googleapis.com/.../jquery.min.js`, `cdn.jsdelivr.net/...flatpickr/pikaday`, `verifycdn.agego.com/v1/verify.js`, `https://a5.g--o.info`, `https://t1.tubev.sex/static/js/{interdata.min,sync}.js` +**Why:** Compromise CDN → arbitrary JS у браузері користувача. Особливо `agego.com`, `g--o.info` — third-party без вашого контролю. +**What:** pin-version + `integrity="sha384-..."` для кожного CDN script ABO self-host. +**Effort:** M (2-4h per site, batch'ами) +**Status:** OPEN. Чекає developer-go. + +### S2. Origin audit obfuscated JS *(BUG)* +**Where:** 10+ файлів random-name JS, не у sync.sh +**Files:** `c24c4cd9.js`, `N7Ym4F.js`, `popa.js`, `f4T4s.js`, `gD0A3.js`, `qDap9.js`, `mo.js`, `aOKM9.js`, `9qFdXQ7.js`, `gk5LT.js`, `PxqbeCb.js`, `k3KL5.js` +**Sites:** 8084, 8085, 8102, 8107, 8112, 8126, 8131 +**Why:** Підозріло на adblock-bypass payloads ABO malicious drop. Нема git track, нема sync.sh entry, обфусковані імена. +**What:** Audit походження. Якщо ваші → перейменувати + покласти у sync.sh + git track. Якщо невідомі → видалити після перевірки що active loading не залежить. +**Effort:** S (1-2h) +**Status:** OPEN. Питання до developer: ваші чи невідомі? + +--- + +## 🟡 MEDIUM severity + +### M1. 8112 — два GA properties в одному gtag *(BUG)* +**Where:** `backup_8112/views/modules/ga/ga.etlua` +**Why:** gtag config містить одночасно `G-CQN2KFSXSG` і `G-WW50B2EGSJ` → дані пишуться на 2 property. Imовірний bug — не сумісно з legitimate analytics workflow. +**What:** Підтвердити з developer який ID правильний. Видалити інший. +**Effort:** XS (15 min) +**Status:** OPEN. Питання до developer. + +### M2. site_domain / GA ID / CDN host → config *(REFACTOR)* +**Where:** layout/header `.etlua` всіх 14 сайтів +**Why:** Site domain hardcoded у CSP `form-action`, `preconnect`, partner logo links. GA IDs hardcoded. CDN hosts hardcoded. Зараз — по N літералів у кожному layout. Drift-prone. +**What:** Створити `views/config/site.lua` (або еквівалент Lua module) з constants: +```lua +return { + domain = "hdsexvideo.xxx", + ga_id = "G-CQN2KFSXSG", + cdn_pic = "cdn-pic.hdsexvideo.xxx", + cdn_video = "...", + partners = { "fulltube.xxx", "nu-bay.com", ... }, +} +``` +Layout uses `<%= site.domain %>`, `<%= site.ga_id %>`. +**Effort:** M (4-6h) +**Status:** OPEN. + +### M3. CSP — meta → HTTP header *(REFACTOR)* +**Where:** layout*.etlua з `` +**Why:** meta-CSP не може встановити `frame-ancestors` / `report-uri`, повільніший за HTTP header. Зараз 8084 (та інші) використовують meta. +**What:** Перенести у nginx config. Може треба developer-side change бо nginx config не наш scope. +**Effort:** S frontend-side / depends backend +**Status:** OPEN. Залежить від developer. + +### M4. modules/video.etlua → shared partial *(REFACTOR)* +**Where:** `views/modules/video.etlua` × 14/14 сайтів +**Why:** 67-77% common lines, найвища similarity з усіх модулів. 14 окремих копій що data-loop ідентичний, але class names + tweaks per site. +**What:** +- Extract base partial з `<%= include 'modules/video_base' %>` +- Per-site theme = CSS overrides (не template fork) +- Shared params: `<%= video, css_class, lazy_load %>` +**Effort:** M (4-6h) +**Status:** OPEN. **Найбільший SSOT win** з усіх refactor candidates. + +### M5. 8081 layout split *(REFACTOR)* +**Where:** `backup_8081/views/layout.etlua` (1223 рядки monolithом) +**Why:** Outlier. Median решти ~200 рядків. Усі profile_*.etlua унікальні тут — 8081 has different architecture (NL agego, premium fork). +**What:** Розбити на partials аналогічно іншим 13 сайтам (header.etlua + footer.etlua + bottom_block.etlua + main.etlua). +**Effort:** L (8-12h, ПІСЛЯ M4 — щоб 8081 теж пристосувався до shared video partial) +**Status:** OPEN. Залежність: M4. + +### M6. 8112 static/ duplicate tree *(CLEANUP/REFACTOR)* +**Where:** `backup_8112/static/{js,css,img,jsplayer,player,trade-th,tmp}` ↔ `backup_8112/views/static/...` +**Why:** Дві ідентичні копії (md5-confirmed). Один live, інший stale. +**What:** З'ясувати який referenced (читай OpenResty config якщо доступно, або питай developer). Видалити інший. +**Effort:** M (2-4h, потребує OpenResty config check) +**Status:** OPEN. Питання до developer. + +### M7. 8085 submodule drift *(BUG)* +**Where:** `backup_8085/views/static/js/lib` +**Why:** Modified submodule reference (`m` у git status). Submodule гілка drift'нула від трекованого коміту. Або локальний edit, або prod оновив submodule а tracking — ні. +**What:** З'ясувати з developer: rollback або commit поточний state. +**Effort:** XS (15 min) +**Status:** OPEN. Питання до developer. + +### M8. 8086 sync drift — 30+ legacy файлів *(CLEANUP)* +**Where:** `backup_8086/views/` +**Why:** Sync.sh селективно копіює ~25 файлів, але диск містить ~30+ legacy не у sync.sh: `asdadsasd.html`, `layout_bak_25-05-18.etlua`, `id_index_copy_with_cjannels.etlua`, `del___search_top.etlua`, `header_with_country_if.etlua`, `layout_copy_withads.etlua`, plus 24+ модулів. +**What:** +1. Audit чи щось з цього reference'ed у живому layout/modules +2. Unreferenced → видалити +3. Sync 8086 на rsync-парадигму (Group A) — `--delete` зачистить решту +**Effort:** S (1-2h) +**Status:** OPEN. + +### M9. 8112 untracked drift *(CLEANUP/BUG)* +**Where:** `backup_8112/{rotator/,lib/,nginx.conf,nginx.conf.compiled,redirect_*.nginx}` +**Why:** Untracked у git, але присутні на disk. `rotator/` має 40+ файлів `1_.txt` (i18n) + `cats.txt` symlink → `/home/nosfortube/frontend_8112/rotator/data/cats.txt`. backup mirror'ить prod app structure частково. +**What:** Or: +- Додати у sync.sh + git track (якщо потрібно у backup) +- Виключити (`gitignore` + не sync) (якщо не потрібно) +**Effort:** S (1h) +**Status:** OPEN. Питання до developer. + +--- + +## 🟢 LOW severity / cleanup + +### C1. Видалити DEL_* tombstones *(CLEANUP)* +**Where:** 24 файли × 6 сайтів +**Files:** `DEL_channel_id.etlua`, `DEL_friend_list.etlua`, `DEL_lang.etlua`, `DEL_lang_mob.etlua` +**Sites:** 8100, 8102, 8107, 8112, 8131, 8133 +**Why:** Префікс DEL_ явно signals tombstone, але файли досі живуть. Шум grep-у, ризик випадкового деплою. +**Effort:** XS (15 min) +**Status:** OPEN. + +### C2. Видалити backup-via-rename артефакти *(CLEANUP)* +**Where:** ~30 файлів з пробілами / " copy" / "with ads" / "without ads" / "with titles" +**Files:** Окремі категорії: +- `header copy bongo link 25_10_22.etlua` × 5 сайтів (8084, 8085, 8112, 8126, 8131; з typo `bogolink` на 8112) +- `id_index copy_ads_actual.etlua` × 2 (8084, 8085) +- `cat_list_thumb with ads.etlua` × 10 (8112) +- `* with titles.etlua` × 5 (8100) +- `untitled file` × 2 (8126) +- `my copy.js`, `machine copy.js`, etc. × 8 +**Why:** File names з пробілами ламають shell scripts. Версії повинні бути у git. +**Effort:** S (1h) +**Status:** OPEN. + +### C3. Видалити legacy `*_old/` dirs *(CLEANUP)* +**Where:** `backup_8085/views/static/{js_old/,img_old/}` (6+25 файлів) +**Why:** "_old" — explicit legacy marker. +**Verification:** `grep -rn "js_old\|img_old" backup_8085/` → 0 матчів = safe to delete. +**Effort:** XS (30 min) +**Status:** OPEN. + +### C4. Видалити legacy UA-* GA *(CLEANUP)* +**Where:** `views/modules/ga/ga.etlua`, `static/js/ga.js`, `layout-orig.etlua` +**Sites:** 8081, 8086, 8100, 8112, 8126 +**Why:** Universal Analytics EOL 2023-07-01. UA-* IDs не shipping data, але збільшують attack surface (extra script tag) і гасять performance. +**Files з UA-:** `UA-128492434-7`, `UA-109631925-*`, `UA-105546426-7` (7 унікальних) +**Effort:** XS (30 min) +**Status:** OPEN. + +### C5. Видалити paginator_old / video_test варіанти *(CLEANUP)* +**Where:** `views/modules/` +**Sites:** 8084 і 8085 +**Files:** `paginator_old.etlua`, `cat_list_thumb_test.etlua`, `cat_index_test.etlua`, `main_list_test.etlua`, `video_test.etlua`, `counters.min.test.js` (8133) +**Why:** Tests / older versions у prod tree. +**Effort:** XS (15 min) +**Status:** OPEN. + +### C6. Уніфікувати sync.sh на rsync *(REFACTOR)* +**Where:** 7 selective sites: 8081, 8086, 8112, 8120, 8129, 8133, 8148 +**Why:** 7 з 14 уже на ідентичному rsync template (74a6acb…). 7 інших роблять те саме через ad-hoc whitelists. Drift-magnet, важко synced модулі для нових сайтів. +**What:** Замінити selective `cp` allowlists на 12-line rsync template. Виняток — 8148 build-step (виносити окремо в `build.sh`). +**Effort:** S (1h) +**Status:** OPEN. + +### C7. 8148 — винести build з sync.sh *(REFACTOR)* +**Where:** `backup_8148/sync.sh` (виконує `sed -i` MUTATION на prod source) +**Why:** sync.sh не повинен мутувати джерело. Build step і sync — різні concerns. +**What:** +- `build.sh` робить ad-bundle build + md5 + sed +- `sync.sh` робить тільки rsync mirror +- Pipeline: `build.sh && sync.sh` — explicit ordering +**Effort:** S (1h) +**Status:** OPEN. + +### C8. Naming convention enforcement *(FEATURE/REFACTOR)* +**Where:** Pre-commit hook (per-repo) ABO server-side guard +**Why:** Запобігти повторного появи pробілів у file names, " copy", DEL_*, _test*, obfuscated random names. Інакше backlog буде відновлюватися. +**What:** +- Pre-commit script blocks: `[ a-zA-Z0-9_./-]` чорний список (тільки лат+цифри+`_./- `) +- Block `^DEL_`, `*test*` у production paths +- Document у [docs/NAMING.md](NAMING.md) (TODO P4) +**Effort:** S (1h script + 1h documentation) +**Status:** OPEN. + +### C9. Min/non-min JS policy *(REFACTOR)* +**Where:** `c2.{js,min.js}`, `main.{js,min.js}`, `my.{js,min.js}`, `jquery-3.2.1.{js,min.js}` etc. +**Why:** Production = тільки `.min.js`. Dev = source. Зараз обидва у репо — шумно. +**What:** Pre-commit minifier ABO build-step pipeline. Source у `src/`, minified у `static/js/`. +**Effort:** M (3-5h, build pipeline) +**Status:** OPEN. Потенційно потребує developer-side build infrastructure. + +### C10. CSS file naming standardization *(REFACTOR)* +**Where:** 8084 (no `views/css/` folder), 8086 (`styles.etlua` instead of `css_.etlua`), 8148 (no folder) +**Why:** 11/14 use `css_.etlua` pattern → решта 3 не вписуються. +**What:** Привести 8084/8086/8148 до `css_.etlua` convention. Якщо вони мають окрему причину (8148 — sprite-driven, не split per page) — задокументувати у [SITES.md](SITES.md) виняток. +**Effort:** S (1-2h) +**Status:** OPEN. + +### C11. Cross-site partner logos через config *(REFACTOR)* +**Where:** `header*.etlua`, layout footer-блоки 7 сайтів +**Sites:** 8084, 8085, 8086, 8100, 8102, 8126, 8131 +**Why:** Hardlinks на партнерські сайти (`fulltube.xxx`, `hdsexvideo.xxx`, `nu-bay.com`, `gaypornhd.xxx`, `xxxtube1.com`, `fullhdxxx.com`, `maturesexmovies.xxx`) — кожен layout має свої literals. +**What:** Винести у `views/config/partners.lua` як array. Layout iterates. +**Effort:** S (1-2h, після M2 site.lua) +**Status:** OPEN. Залежність: M2. + +--- + +## Reminders cadence + +goboss перевіряє цей файл **на початку кожної session** і нагадує developer-у: +- Скільки items OPEN (по severity) +- Що було додано з минулої session +- Найдешевші items (XS-S) — пропонувати спершу +- Найпріоритетніші (HIGH) — окремо помічати + +Items з статусом `DONE`, `WONTFIX`, `DEFERRED` переходять у footer цього файлу (history), щоб не плутатися з активним backlog. + +--- + +## DONE / WONTFIX / DEFERRED + +*(порожньо — поки нічого не виконано)* + +--- + +*Last update: 2026-04-30 (initial backlog from gocc1+2+3+4 audits)* diff --git a/docs/REFACTOR_RULES.md b/docs/REFACTOR_RULES.md new file mode 100644 index 0000000..2d30e04 --- /dev/null +++ b/docs/REFACTOR_RULES.md @@ -0,0 +1,127 @@ +# Refactor / Cleanup / Bug-fix / Feature — definitions + +**Чотири типи змін.** Кожна задача має ідентифікувати свій тип. Це визначає: +- Тригер (хто запитує: developer / audit / автоматичний) +- Scope (skill rough effort) +- Тестування (regression / smoke / нове) +- Як комітити (commit message prefix) + +--- + +## REFACTOR + +**Що це:** зміна **структури** коду без зміни поведінки. Goal — clearer code, less duplication, easier maintenance. + +**Не змінює:** +- HTTP responses (statuses, JSON shape, HTML output byte-for-byte для existing inputs) +- DB schema (без migration) +- API contracts +- Visual rendering for users + +**Приклади у tubev:** +- Винести `modules/video.etlua` у shared partial з per-site theme overrides → 14 сайтів дають однаковий HTML output, але код DRY (відсутнє ~60% дублювання) +- Розбити `8081/views/layout.etlua` 1223L монолітом на partials аналогічно іншим 13 сайтам → той же rendered HTML, чистіша структура +- Уніфікувати `sync.sh` на rsync-парадигму (7 selective → 7 rsync) → той же файловий результат, єдина mental model + +**Тестування:** +- **Regression smoke** — той же rendered HTML before/after на тестовому сайті +- **Diff snapshot** — `curl vs curl ` має бути identical +- Якщо diff — це BUG у refactor, треба фіксити + +**Комміт:** `refactor: : ` + +**Хто запитує:** developer (`go: refactor X`). НІКОЛИ боти/goboss самостійно — тільки коли явна директива. + +--- + +## CLEANUP + +**Що це:** видалення **dead code / dead files** які точно не використовуються. + +**Не змінює:** +- Нічого, бо видаляється тільки те що було не задіяне. + +**Приклади у tubev:** +- Видалити `DEL_*.etlua` (24 файли × 6 сайтів) — префікс DEL_ явно signals tombstone +- Видалити `*copy*.etlua`, `*_bak*.etlua`, `*_old/` папки — backup-via-rename артефакти +- Видалити `_test.etlua`, `.test.js` з prod tree — tests не у prod +- Видалити legacy UA-* GA snippets (Universal Analytics EOL 2023-07) + +**Verification перед видаленням:** +- `grep -rn "" backup_/` — чи десь reference? +- Якщо posicionado — re-classify як refactor (треба міняти reference спершу) +- Якщо unreferenced — safe to delete + +**Тестування:** +- Sync.sh re-run → backup ідентичний прод (для rsync mirror sites) +- Smoke render головних сторінок — нічого не зламалось + +**Комміт:** `cleanup: : remove ` + +**Хто запитує:** developer ("видали DEL_*"). Боти **знаходять** і **рекомендують** у RECOMMENDATIONS.md, але не видаляють самі без явного go. + +--- + +## BUG-FIX + +**Що це:** код **неправильно** працює, треба виправити. + +**Змінює поведінку — навмисно**, бо поведінка була некоректна. + +**Приклади у tubev:** +- 8112 має 2 GA properties у одному gtag — likely баг (gtag config записує на дві property) +- 8085 submodule `views/static/js/lib` drift — modified reference але не committed; treba decide rollback або commit +- Site domain hardcoded у CSP `` — правильніше через nginx HTTP header +- `header copy bogolink 25_10_22.etlua` (8112) — typo в назві файлу = drift від 4 інших сайтів + +**Тестування:** +- Reproducer test (показує проблему) +- Fix test (показує що пофіксено) +- Regression — нічого іншого не зламалось + +**Комміт:** `fix: : ` + +**Хто запитує:** будь-хто (developer, audit, користувач). Bots HIGH severity findings → goboss flagує developer-у. + +--- + +## FEATURE + +**Що це:** **нова поведінка** яка раніше не була доступна. + +**Приклади у tubev:** +- Винести `views/config/site.lua` (новий конфіг файл) → нова можливість централізованого управління site_domain / GA ID / CDN host +- SRI integrity для third-party scripts → нова security guarantee +- Build-step для 8148 (винести з sync.sh) → нова функція автоматизації + +**Тестування:** +- New tests для нової поведінки (smoke + edge + integration) +- Regression — нічого не зламалось + +**Комміт:** `feat: : ` + +**Хто запитує:** developer / product. Боти не пропонують features самостійно. + +--- + +## Як вибирати + +| Зміна | Type | +|-------|------| +| "Винести в shared module / extract / DRY-it" | **REFACTOR** | +| "Видали мертве" / "забрати DEL_*" / "wipe legacy" | **CLEANUP** | +| "Не працює як треба" / "неправильна відповідь" / "конфлікт даних" | **BUG-FIX** | +| "Додай нове" / "тепер можна X" / "нова кнопка/endpoint" | **FEATURE** | + +Якщо змішується — розбий на окремі коміти, **по одному типу на commit**. Mixed commits ламають revert / cherry-pick. + +--- + +## Recommendations vs Plans (важливо) + +**Recommendation** = "ось що варто зробити, ось чому, ось приблизний effort". +**Plan** = "ми зараз робимо наступне: ...". + +Боти створюють recommendations у [RECOMMENDATIONS.md](RECOMMENDATIONS.md). **Plans створюються тільки коли developer каже "зробити"**. + +goboss **не виконує** recommendations самостійно. Тільки нагадує developer-у періодично через session-start summary поки developer не скаже "роби X" або "видали X з backlog". diff --git a/docs/SITES.md b/docs/SITES.md new file mode 100644 index 0000000..ec05b9e --- /dev/null +++ b/docs/SITES.md @@ -0,0 +1,67 @@ +# tubev — Sites Inventory + +14 сайтів у `/home/w4/backup_/`. Кожен — окремий git repo. + +## Таблиця + +| Port | Domain | Status | Architecture | Sync | CSS | Brand | Notes | +|------|--------|--------|--------------|------|-----|-------|-------| +| 8081 | ? (NL agego) | active dev | **monolith** | selective (46L) | 449KB **outlier** | dark blue `#3162d8` | profile_*.etlua тільки тут; channel_list_thumb унікальний; SPA-like; CSS monolith style.css 221KB; layout 1223L | +| 8084 | hdsexvideo.xxx | live | legacy partials | rsync mirror (12L) | 172KB | light + orange `#ff8201` | SCSS + gulp build pipeline; **без `views/css/`** | +| 8085 | sexfreehd.xxx | live | legacy partials | rsync mirror (12L) | 252KB | dark + pink `#fe6661` | SCSS hybrid (style.scss 2421L); **submodule drift** `views/static/js/lib`; legacy `js_old/`, `img_old/` | +| 8086 | nu-bay.com | live | legacy partials | hybrid (36L) | 98KB | dark + green `#8bc215` | **outlier color** (зелений); 30+ legacy файлів `*copy*`, `*bak*`, `del___*`; single `styles.etlua` (не css_*.etlua) | +| 8100 | fulltube.xxx | live | legacy partials | rsync mirror (12L) | 147KB | red/brown `#c8280e` | багато файлів з пробілами та " copy"/"with titles" варіантами | +| 8102 | gaypornhd.xxx | live | legacy partials | rsync mirror (12L) | 106KB | dark + red `#fe1c5c` | DEL_* модулі; `my copy.js` dead | +| 8107 | maturesexmovies.xxx | live | legacy partials | rsync mirror (12L) | 104KB | gradient blue-violet | DEL_* + adspy banners cluster; obfuscated `gk5LT.js` | +| 8112 | hdpornvideo.xxx | live | **prod canonical** | selective (50L) | 209KB | dark + orange `#f45100` | **повна дублікація** static/ ↔ views/static/ (md5-identical); єдиний з git remote `git.tubev.sex`; 2 GA properties у одному gtag (потенційний bug); 7+ "with/without ads" варіантів; untracked `rotator/`, `lib/`, `nginx.conf` | +| 8120 | pornv.xxx | live | partial-modern | selective (46L) | 133KB | navy + orange | мінімальний (без `top_list`); HTML5 `
` semantic; обmodernized | +| 8126 | xxxtube1.com | live | legacy partials | rsync mirror (12L) | 103KB | dark + red `#ff0344` | мінімалістичні breakpoints (7 BP); HTML5 `
`; mobile menu з 8 aria-expanded; `untitled file` × 2 | +| 8129 | ? | active dev | minimal | hybrid (36L) | 69KB **smallest** | dark + orange `#fb671e` | **мінімаліст** (без model_list, top_list, header.etlua, footer.etlua, bottom_block.etlua); 7 модулів total | +| 8131 | fullhdxxx.com | live | legacy partials | rsync mirror (12L) | 111KB | dark + orange `#f47a20` | obfuscated JS: `PxqbeCb.js`, `gD0A3.js`, `9qFdXQ7.js` | +| 8133 | broxxx.com | live | legacy partials | hybrid (37L) | 127KB | light | `__main.js` underscore prefix; `counters.min.test.js` (test у prod) | +| 8148 | ? | **canonical lab** | minimal modern | selective (79L) + **build hook** | 82KB | sprite-driven, light | **288 commits/30d** (broadcast source); CSS vars system (24 tokens) — **єдиний з token system**; sync.sh викликає `build-ad-bundle.sh` + md5 hash bump через `sed -i`; `vast-preroll.js`, `ad-*` adstack | + +## Кластери + +### Архітектурні +- **Monolith outlier:** 8081 (1223L layout, profile pages, SPA-like) +- **Canonical lab:** 8148 (modern, CSS vars, ad-bundle automation, broadcast source) +- **Prod canonical:** 8112 (повна дублікація tree, untracked prod mirror) +- **Legacy partials majority:** 8084, 8085, 8086, 8100, 8102, 8107, 8126, 8131, 8133 (header.etlua + footer.etlua + bottom_block.etlua) +- **Minimalists:** 8120, 8129, 8148 (без top_list / без header.etlua) + +### Візуальні +- **Dark + Orange:** 8112, 8129, 8131, 8133 +- **Dark + Red/Pink:** 8085, 8086 (зелений), 8102, 8126 +- **Dark + Blue:** 8081 +- **Light + Orange:** 8084, 8133 +- **Hybrid/Modern:** 8107 (gradient), 8120 (navy+orange), 8148 (sprite light) +- **Outlier color:** 8086 (зелений `#8bc215`) + +### Sync патерни +- **Group A** (rsync mirror 12L, ідентично): 8084, 8085, 8100, 8102, 8107, 8126, 8131 +- **Group B** (selective cp): 8081, 8086, 8112, 8120, 8129, 8133, 8148 + +## Невідомі домени + +8081, 8129, 8148 — `lib//var.lua` відсутній у backup, домен не виводиться. **Питання до розробника:** які домени відповідають цим портам? + +## Test/staging + +`test.` НЕ налаштовано (DNS/connect-fail для всіх 11 known доменів). Усі live тільки на `www.` (HTTP/2 200, nginx 1.21.1, спільний backend `s=l8` cookie). + +**Питання до розробника:** як працює preview змін перед prod? Інший механізм (port-direct, VPN, feature branch deploy)? + +## Останні активності (станом на 2026-04-30) + +| Activity | Sites | +|----------|-------| +| **288 commits/30d** | 8148 (lab/dev) | +| **12 commits/30d** | 8081 (NL experiments) | +| **2-5 commits/30d** | решта 12 (broadcast рецепієнти) | + +Pattern: 8148 розробляється → коміти broadcast'яться по всіх 14 сайтах (cross-site batch commits типу `popunder cross-tab gate _asgGatedLoad on 12 sites`). + +--- + +*Source: gocc2 + gocc3 + gocc4 audits 2026-04-30. Update — коли додається/закривається сайт, або змінюється cluster.* diff --git a/docs/SYNC_WORKFLOW.md b/docs/SYNC_WORKFLOW.md new file mode 100644 index 0000000..749130a --- /dev/null +++ b/docs/SYNC_WORKFLOW.md @@ -0,0 +1,130 @@ +# tubev — Sync Workflow + +`sync.sh` копіює фронтенд з prod (`/home/nosfortube/frontend_/`) → backup (`~/backup_/`). + +## Дві парадигми + +### Group A — rsync mirror (7 сайтів) + +**Сайти:** 8084, 8085, 8100, 8102, 8107, 8126, 8131 + +**Шаблон (12 рядків, ідентичний після port-mask):** +```bash +#!/bin/bash +SRC="/home/nosfortube/frontend_" +DST="/home/w4/backup_" + +# Mirror views/ +rsync -a --delete --exclude='.git' "$SRC/views/" "$DST/views/" + +# Mirror lib// +mkdir -p "$DST/lib/" +rsync -a --delete "$SRC/lib//" "$DST/lib//" +``` + +**Властивості:** +- `--delete` → backup завжди = SRC. Drift=0. +- Підтягує ВСЕ під `views/`, включно зі сміттям (`*copy*`, `*bak*`, `_test`, `DEL_*`). +- Безпечно для drift. + +### Group B — selective cp (7 сайтів) + +**Сайти:** 8081, 8086, 8112, 8120, 8129, 8133, 8148 + +**Pattern:** explicit allowlist файлів через `cp` per-file. + +| Site | Lines | Особливість | +|------|-------|-------------| +| 8081 | 46 | Templates + JS allowlist; profile_* + videojs-v10 | +| 8086 | 36 | header/footer + ~14 modules + minimal css/js | +| 8112 | 50 | Templates з ad/no-ad варіантами + banners + player + var.lua | +| 8120 | 46 | Templates + 14 modules + 5 css + forms + dropzone JS | +| 8129 | 36 | Templates + 7 modules + 5 css + timeline JS | +| 8133 | 37 | Templates + 11 modules + 9 banners + static html | +| 8148 | **79** | + auto-rebuild ad-bundle (md5) + pjs/timeline-pjs/tests | + +**Властивості:** +- Drift-prone: якщо у prod з'являється файл якого нема у allowlist — backup його не знає. +- Швидко (sync лише потрібного). +- Жорсткий контроль що бекапиться. + +### 8148 — особливий + +`sync.sh` 8148 не лише копіює, а й **виконує MUTATION на prod source:** +```bash +# Builds ad-bundle, computes md5, replaces ?v=HASH у layout.etlua +build-ad-bundle.sh +HASH=$(md5sum ad-bundle.js | cut -d' ' -f1) +sed -i "s/ad-bundle.js?v=[a-f0-9]*/ad-bundle.js?v=$HASH/" layout.etlua +``` + +Це дельта sync ↔ build. Інші sync.sh — read-only operations. **Рекомендація** — винести build у окремий скрипт (див. RECOMMENDATIONS.md). + +## Як додати новий сайт + +1. **Створити `~/backup_/`:** + ```bash + mkdir -p ~/backup_ + cd ~/backup_ + git init + git remote add origin + ``` + +2. **Скопіювати rsync-template (Group A) — recommended:** + ```bash + cat > sync.sh <<'SHELL' + #!/bin/bash + SRC="/home/nosfortube/frontend_" + DST="/home/w4/backup_" + rsync -a --delete --exclude='.git' "$SRC/views/" "$DST/views/" + mkdir -p "$DST/lib/" + rsync -a --delete "$SRC/lib//" "$DST/lib//" + SHELL + chmod +x sync.sh + ./sync.sh + ``` + +3. **Закомітити перший snapshot:** + ```bash + git add . + git commit -m "Initial backup of frontend_" + ``` + +4. **Оновити `docs/SITES.md`** — додати рядок з портом, доменом, кластером. + +## Як зробити локальну зміну + +1. **Sync прод стан:** + ```bash + cd ~/backup_ + ./sync.sh + git status # перевір чи прод змінився під час твоєї роботи + ``` + +2. **Edit:** редагуй `views/`, `static/`, etc. **НЕ йди у `/home/nosfortube/`**. + +3. **Commit локально:** + ```bash + git add + git commit -m ": " + ``` + +4. **Push до prod:** **goboss НЕ пушить**. Це робить розробник через свій процес. Боти лишають коміти у власному worktree (`~/gocc{N}//`), goboss збирає через cherry-pick. + +5. **Verify:** preview/test domain механізм наразі не ідентифіковано (питання до розробника). + +## Git remote + +Тільки **8112** має `origin = git@git.tubev.sex:nosfotube/frontend.git`. Інші 13 — local-only repos. Це означає що pull/push між backup'ами не централізовано. + +**Рекомендація:** з'ясувати у розробника правильний git workflow (чи всі сайти ідуть через `git.tubev.sex`, чи інакше). + +## Рекомендація: уніфікація на rsync (S, ~1h) + +7 selective sync.sh роблять те саме що 7 rsync, але через ad-hoc allowlists. Це drift-magnet (gocc1 знайшов 8086: 30+ файлів на disk не у sync.sh; 8112: untracked `rotator/`, `lib/`, `nginx.conf`). + +Краще — один template на 14 сайтів. Деталі: **[docs/RECOMMENDATIONS.md](RECOMMENDATIONS.md)** #1. + +--- + +*Source: gocc1 + gocc2 + gocc4 audits 2026-04-30.* diff --git a/docs/roles/gocc1-auditor-code.md b/docs/roles/gocc1-auditor-code.md new file mode 100644 index 0000000..e360643 --- /dev/null +++ b/docs/roles/gocc1-auditor-code.md @@ -0,0 +1,87 @@ +# gocc1 — Аудитор коду (READ-ONLY) + +## Ідентифікація +Кожну відповідь починай з `[gocc1]`. + +## Тригер +Коли юзер пише `+`, `го`, `go` — прочитай `~/comms/gocc1-task.md`. Виконай. Результат — Write у `~/comms/gocc1-report.md` (перезаписуй). + +## Фоллбек +Якщо task порожній / не змінився / Task ID збігається з report → НЕ вигадуй роботу. Write у report: `[gocc1] Чекаю.` Юзеру: `Чекаю.` + +## Що робиш +- Hardcoded values (URLs, keys, magic numbers, paths) +- DRY violations (дублювання) +- Security issues (exposed secrets, injection patterns, unsafe defaults) +- Dead code (unused imports, unreachable branches) +- Config correctness (env vars, missing validation) +- Regression check проти попередніх findings (свій report — кожна нова task ПЕРШИМ ділом ретест) + +## Що ДОЗВОЛЕНО +- ✅ Read, Grep, Glob — читати/шукати +- ✅ Bash — тільки read-only (`grep`, `wc`, `find`, `curl`, `python3 -c "..."` для аналізу) +- ✅ Write — ТІЛЬКИ `~/comms/gocc1-report.md` + +## Що ЗАБОРОНЕНО +- ❌ Edit будь-якого файлу +- ❌ Write у будь-який інший файл крім свого report +- ❌ git commit, git push +- ❌ deploy.sh, systemctl +- ❌ Не виправляй код — тільки знаходь і звітуй + +## Верифікація (включай у звіт) + +Не "подивився на код" — запускай перевірки: + +```bash +# Python синтаксис +python3 -m py_compile .py && echo "✅ OK" + +# Unused imports +python3 -c " +import ast +tree = ast.parse(open('.py').read()) +imports = [n.module if isinstance(n, ast.ImportFrom) else n.names[0].name + for n in ast.walk(tree) if isinstance(n, (ast.Import, ast.ImportFrom))] +print(imports) +" + +# SQL sanity +python3 -c "import sqlite3; sqlite3.connect('').execute('EXPLAIN SELECT 1')" +``` + +## Ретест попередніх findings (ОБОВ'ЯЗКОВО) + +При кожній новій task: +1. Прочитай свій `~/comms/gocc1-report.md` +2. Якщо там issues — перевір кожен (git pull, file:line, чи пофіксено) +3. Таблиця `## Ретест` — FIXED / STILL OPEN +4. ТІЛЬКИ ПІСЛЯ — нова task + +## Формат звіту + +```markdown +[gocc1 YYYY-MM-DD HH:MM] Task ID: + +## Ретест +| # | Прев issue | Статус | + +## Аудит: <тема> +| # | Файл:рядок | Проблема | Severity | +|---|-----------|----------|----------| +| 1 | config.py:12 | SECRET_KEY hardcoded | HIGH | + +Severity: HIGH (security/crash) / MEDIUM (correctness) / LOW (style) +``` + +## Координація +- Задачі від goboss +- HIGH severity — на початок звіту + +## Signal goboss +Write `~/comms/gocc1-report.md` → PostToolUse hook `auto-signal-goboss.sh` автоматично шле `gocc1: done` до goboss. Ніяких ручних tmux send-keys не треба. + +Manual fallback (якщо hook fails): +```bash +tmux send-keys -t goboss "gocc1: done" Enter +``` diff --git a/docs/roles/gocc2-auditor-test.md b/docs/roles/gocc2-auditor-test.md new file mode 100644 index 0000000..6a7be93 --- /dev/null +++ b/docs/roles/gocc2-auditor-test.md @@ -0,0 +1,96 @@ +# gocc2 — Тест-аудитор (READ-ONLY) + +## Ідентифікація +Кожну відповідь починай з `[gocc2]`. + +## Тригер +Коли юзер пише `+`, `го`, `go` — прочитай `~/comms/gocc2-task.md`. Виконай. Результат — Write у `~/comms/gocc2-report.md` (перезаписуй). + +## Фоллбек +Якщо task порожній / не змінився / Task ID збігається з report → Write у report: `[gocc2] Чекаю.` Юзеру: `Чекаю.` + +## Що робиш +- Test gap analysis (які public функції / endpoints без покриття) +- API endpoints через `curl` (status codes, JSON shape, auth, edge cases) +- Prod smoke tests (live endpoints, response correctness) +- Cross-validation (`/api/stats.total == len(/api/items)`) +- Negative tests (missing auth → 401, invalid body → 400, 404 not 500) +- Regression проти попередніх FAIL items + +## Що ДОЗВОЛЕНО +- ✅ Bash — `curl`, `wget`, `python3 -c` (test scripts), `pytest --collect-only` +- ✅ Read, Grep, Glob +- ✅ Write — ТІЛЬКИ `~/comms/gocc2-report.md` + +## Що ЗАБОРОНЕНО +- ❌ Edit, Write у будь-який інший файл +- ❌ git commit, git push +- ❌ deploy.sh, systemctl +- ❌ Не виправляй код — тільки тестуй + +## Методологія тестування + +### Рівень 1 — Базовий +- HTTP status (200/400/401/404/500) +- Content-Type +- Non-empty body + +### Рівень 2 — Валідація +- Типи полів (число це число, not null де не має бути) +- Списки мають елементи з очікуваними ключами +- Числа ≥ 0 де доречно +- Дати у форматі ISO + +### Рівень 3 — Крос-валідація +- Stats == count(items) +- Після POST → GET підтверджує дію + +### Рівень 4 — Негативні +- Неіснуючий resource → 404 (не 500) +- Без auth → 401 +- Невалідний JSON → 400 +- Empty body де required → 400 + +### Рівень 5 — Regression +- Baseline (response shape + key values) +- Після рефакторингу — той самий output +- Відмічай навмисні зміни + +## Ретест попередніх findings (ОБОВ'ЯЗКОВО) + +При новій task: +1. Прочитай свій `~/comms/gocc2-report.md` +2. Якщо були FAIL/WARN — перетестуй кожен (curl/grep) +3. Таблиця `## Ретест` — FIXED / STILL OPEN +4. ТІЛЬКИ ПІСЛЯ — нова task + +## Формат звіту + +**FAIL на початку. Спочатку всі помилки, потім PASS.** + +```markdown +[gocc2 YYYY-MM-DD HH:MM] Task ID: + +## Ретест +| # | Прев FAIL | Статус | + +## ❌ FAIL (N) +| # | Endpoint / Test | Expected | Actual | Severity | +|---|----------------|----------|--------|----------| +| 1 | GET /check/bad.com | 404 | 500 | HIGH — crash | + +## ✅ PASS (M) +| # | Endpoint | Status | Validated | +``` + +Severity: HIGH (500/crash) / MEDIUM (wrong status/data) / LOW (cosmetic) + +## Координація +- Задачі від goboss +- HIGH severity — на початок звіту + +## Signal goboss +Write `~/comms/gocc2-report.md` → hook auto-signals. Manual fallback: +```bash +tmux send-keys -t goboss "gocc2: done" Enter +``` diff --git a/docs/roles/gocc3-frontend.md b/docs/roles/gocc3-frontend.md new file mode 100644 index 0000000..281590d --- /dev/null +++ b/docs/roles/gocc3-frontend.md @@ -0,0 +1,106 @@ +# gocc3 — Frontend WRITER (templates / CSS / UI) + +## Ідентифікація +Кожну відповідь починай з `[gocc3]`. + +## Тригер +Коли юзер пише `+`, `го`, `go` — прочитай `~/comms/gocc3-task.md`. Виконай. Результат — Write у `~/comms/gocc3-report.md`. + +## Фоллбек +Task порожній / Task ID збігається → `[gocc3] Чекаю.` + +## Що робиш +- Аудит + фікс inline CSS (`style="..."` → класи) +- HTML структура (семантика, accessibility, дублювання) +- Templates (Jinja2/React/Vue/etc) — компоненти, DRY, macros +- CSS architecture (variables, modules, BEM/utility classes) +- Frontend bundle hygiene (unused, duplicate styles) +- Live preview verification (curl/headless browser) + +## Що ДОЗВОЛЕНО +- ✅ Edit, Write — `templates/**`, `static/**`, `/**`, `/**` +- ✅ Bash — для CSS/build (якщо hook блокує Edit `.css`) +- ✅ git commit (НЕ push) — у власному worktree `~/gocc3//` +- ✅ Read, Grep, Glob + +## Що ЗАБОРОНЕНО +- ❌ git push — тільки commit. goboss перевіряє → пушить. +- ❌ deploy.sh, systemctl +- ❌ Backend code (routes, services, config, db) +- ❌ JavaScript app logic (бізнес-логіка, state management) — тільки UI behaviors / DOM +- ❌ Видалення файлів без явного дозволу у task + +## Верифікація (ОБОВ'ЯЗКОВО перед commit) + +```bash +# Templates parse +python3 -c " +from jinja2 import Environment, FileSystemLoader +env = Environment(loader=FileSystemLoader('templates')) +for t in ['.html']: + env.get_template(t) + print(f'✅ {t}') +" + +# CSS braces balance +python3 -c " +css = open('static/app.css').read() +o, c = css.count('{'), css.count('}') +print(f'{o}/{c}', '✅' if o == c else '❌ MISMATCH') +" + +# Smoke +curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:/ +# Має бути 200/302 +``` + +**Не комітити без верифікації. ❌ → пофікси.** + +## Ретест попередніх findings (ОБОВ'ЯЗКОВО) + +При новій task: +1. Прочитай свій `~/comms/gocc3-report.md` +2. Незавершені пункти — перевір кожен +3. Таблиця `## Ретест` — DONE / STILL OPEN +4. ТІЛЬКИ ПІСЛЯ — нова task + +## Worktree discipline +- Працюєш у `~/gocc3//` (не в production / не в `~/goboss//`) +- `git pull --rebase` перед роботою +- `git commit` локально → goboss cherry-pick'ає / push'ить + +## Формат звіту + +```markdown +[gocc3 YYYY-MM-DD HH:MM] Task ID: + +## Commit: +## Files: + +## Знайдено +| # | Файл:рядок | Проблема | Severity | + +## Виправлено +| # | Файл | Що зроблено | + +## Verification +- jinja parse: ✅ +- css braces: ✅ 1234/1234 +- smoke /: 200 + +## BUGLOG +- +``` + +## Pre-push subagent (для значних змін) +Перед `git commit` — якщо diff >50 LOC АБО architectural / нова integration — self-trigger `Agent(superpowers:code-reviewer)` на diff. Auto-fix high-priority issues. Skip = process violation. + +## Координація +- Задачі від goboss +- Після commit — чекай review/push від goboss + +## Signal goboss +Write `~/comms/gocc3-report.md` → hook auto-signals. Manual: +```bash +tmux send-keys -t goboss "gocc3: done" Enter +``` diff --git a/docs/roles/gocc4-architect.md b/docs/roles/gocc4-architect.md new file mode 100644 index 0000000..ac35d11 --- /dev/null +++ b/docs/roles/gocc4-architect.md @@ -0,0 +1,111 @@ +# gocc4 — Architect / Refactor WRITER (services / lib / scripts) + +## Ідентифікація +Кожну відповідь починай з `[gocc4]`. + +## Тригер +Коли юзер пише `+`, `го`, `go` — прочитай `~/comms/gocc4-task.md`. Виконай. Результат — Write у `~/comms/gocc4-report.md`. + +## Фоллбек +Task порожній / Task ID збігається → `[gocc4] Чекаю.` + +## Що робиш +- Architectural plans (READ-ONLY phase): SSOT design, module split, migration path +- IMPL (write): refactor, нові services/lib modules, scripts, DB migrations +- Multi-file changes — переглядати impact, atomic commits +- Tests — обов'язково для нового public API (smoke + edge + integration) +- SCHEMA versions / migrations +- Cross-module integration + +## Що ДОЗВОЛЕНО +- ✅ Read, Grep, Glob, Bash (pytest, grep, wc, find, python3) +- ✅ Edit, Write — services/, lib/, scripts/, config/, tests/ +- ✅ git commit локально (НЕ push) +- ✅ Створювати нові modules / SSOT helpers + +## Що ЗАБОРОНЕНО +- ❌ git push — тільки commit. goboss cherry-pick / push. +- ❌ deploy.sh, systemctl +- ❌ Frontend (templates, css) — це gocc3 territory +- ❌ Видалення критичних файлів без явного дозволу +- ❌ Зміна salts / hash-stability invariants без явної директиви + +## SSOT-first rule (КРИТИЧНО) +Перед новим літералом / function: +1. `grep -rn "" config/ lib/` — чи вже є? +2. Якщо є → IMPORT (не дублюй) +3. Якщо нема → додай до `config/.py` як module-level const + +Recurring bug = architectural fix, не патч у N місцях. + +## Pool / hash invariants (якщо проект має) +Якщо torchaєш salts / pool order: +- ZAVŽDY keep original salt suffix (`_v1`) +- Bump version тільки якщо reorder неминучий + sync `LOCKED_PICKS` / snapshot tests +- `pytest tests/test_*_snapshot.py -x` після — bit-identical verify + +## Верифікація + +```bash +# Targeted tests +pytest tests/test_.py -x -q + +# Smoke import +python3 -c "from import *; print('OK')" + +# Full suite (якщо доступно) +./run_tests.sh +``` + +## Ретест попередніх findings (ОБОВ'ЯЗКОВО) + +При новій task: +1. Прочитай свій `~/comms/gocc4-report.md` +2. Незавершені пункти — перевір +3. `## Ретест` — DONE / STILL OPEN +4. ТІЛЬКИ ПІСЛЯ — нова task + +## Worktree discipline +- Працюєш у `~/gocc4//` +- `git pull --rebase` перед +- `git commit` локально + +## Формат звіту + +```markdown +[gocc4 YYYY-MM-DD HH:MM] Task ID: + +## Commit: +## Files: +## LOC delta: +X / -Y + +## Decision (якщо archi) +- Варіант: +- Why: +- Trade-off: <тradoff> + +## Changes +| file:line | what | why | + +## Tests +- pytest output + +## SSOT self-check +- grep `` results — 0 hits proof + +## BUGLOG +- +``` + +## Pre-push subagent (ОБОВ'ЯЗКОВО для значних) +Diff >50 LOC АБО архітектурне → self-trigger `Agent(superpowers:code-reviewer)` на diff ПЕРЕД commit. Resolve high-priority. Skip = violation. + +## Координація +- Задачі від goboss +- Після commit — чекай review від goboss перед push + +## Signal goboss +Write `~/comms/gocc4-report.md` → hook auto-signals. Manual: +```bash +tmux send-keys -t goboss "gocc4: done" Enter +```