fb-post · diff

git:20260908.2ec1bf8 to v1.0.0

54 added, 55 removed. Audit A to A.

---
name: fb-post
- description: >-
- Publish an already-vetted post to a personal Facebook wall through the owner's real logged-in
- Chrome tab (a low-ban-risk path), rate-limit-guarded and draft-first: paste, verify what is
- actually in the composer, confirm after reload. Triggers: "/fb-post", "publish to facebook",
- "post this to my wall".
- license: MIT
+ description: "Facebook, стена Антона: Publish a VETTED post to Anton's personal Facebook wall through his real logged-in Chrome (Claude-in-Chrome MCP = the low-ban-risk “act in the live tab“ path), rate-limit-guarded and draft-first. Trigger on “/fb-post“, “запости в фб“, “опубликуй пост в facebook“, “выложи на стену“, “publish to facebook“, “post this to my wall“"
+ version: 1.0.0
---
- # /fb-post — publish a post to the owner's wall (safely, draft-first)
+ # /fb-post — опубликовать пост на стену Антона (безопасно, draft-first)
- **Why.** The content factory and the Facebook diary already WRITE posts in the owner's voice, but the draft still ends up parked in Saved Messages / the vault. The only missing piece was the "publish" button. This skill closes it — in the safest possible way (acting inside a live logged-in Chrome tab, not with a headless bot), with a hard volume counter.
+ > ⛔ **ЛИЧНОСТЬ БРАУЗЕРА (канон 30.08.2026).** Chrome профиля Default на хабе = личность Антона (claude.ai там под **[рабочий аккаунт]**, всегда).
+ > Робот здесь **ЧИТАЕТ и действует, но НЕ ТРОГАЕТ ЛОГИНЫ**: ни logout, ни смены аккаунта, ни «самолечения входа», ни инжекта кук.
+ > Увидел «не тот аккаунт» → доложи и работай из робо-профиля (`_chrome_profile_a2`, Firefox-профили). Канон: `reglament-hab-brauzernye-lichnosti-bb-i-roboty`.
- **Main rules (from Deep Research #32):**
- - Publishing = **OUTBOUND + PUBLIC = Tier-2** → show the final text to the owner and wait for an explicit `+` (or let him press "Publish" himself). Never publish silently.
- - **The owner's voice = the top-tier model.** Take the text from a ready draft (`content-factory`, `facebook-diary`, `episode`) or write it with the top model. Don't invent a new voice, and don't let a cheap model write authorial text.
- - **Keep the volume low:** `fb_guard` caps it at ≤8 posts/day. Don't repeat the same text (spam flag).
+ **Зачем.** Контент-фабрика и FB-дневник уже ПИШУТ посты голосом Антона, но черновик до сих пор оседает в Saved/волте. Не хватало только «кнопки публикации». Этот скилл закрывает её — и делает это самым безопасным способом (действуем в живой залогиненной вкладке Chrome, а не headless-ботом), с жёстким счётчиком объёма.
+ **Главные правила:**
+ - ⭐ **Публикую САМ, «+» не жду** (обновлено 11.08.2026). Гейт [коллега] снят приказом Антона 06.08, окно апрува = 0 часов с 05.08; правило Антона 11.08 дословно: «если за 24ч [коллега] не дала ОК — ты постишь сам». Прежняя строка «публикация = Tier-2, жди +» держала очередь: замер 11.08 — 25 готовых черновиков стояли до 6 дней при полностью открытых разрешениях. Tier-2 остаётся тем, чем был всегда: деньги, юр.обязательства, секреты 3-м лицам — не «наш пост в наш канал».
+ - **Выше меня остаются:** `paused` площадки (стоп-кран [коллега] и Антона) · приватность · правда в цифрах · матрица форматов · `slop_gate` FAIL · IP-гейт §7.2.
+ - ⭐ **Отложка вместо стены прямо сейчас** (проверено вживую 11.08): `facebook.com/professional_dashboard/content/content_library/` → **Scheduled / Drafts / Planner**, в композере **Create → Schedule post**. Разгребаю бэклог — размазываю по дням отложкой, а не вываливаю стеной.
+ - **Записать в реестр:** после публикации (или постановки в отложку) строка в `_imports\content-factory\registry\pub_ledger.jsonl`. Не записал = не постил.
+ - **Голос Антона = Opus.** Текст беру из готового черновика (`content-factory`, `facebook-diary`, `episode`) или пишу на Opus. Не выдумываю новый голос, не даю Sonnet писать авторское.
+ - **Объём низкий:** `fb_guard` режет на ≤8 постов/день. Не дублировать один и тот же текст (спам-флаг).
+
---
- ## 0. The fuse BEFORE the browser (mandatory)
+ ## 0. Предохранитель ПЕРЕД браузером (обязательно)
```bash
python "$USERPROFILE/.claude/scripts/fb_guard.py" check post
```
- - `OK post (...)` → you may continue.
- - `BLOCKED post: ...` (exit 3) → STOP. Tell the owner the daily post limit is used up, offer to schedule for tomorrow. Do not work around it.
+ - `OK post (...)` → можно продолжать.
+ - `BLOCKED post: ...` (exit 3) → СТОП. Скажи Антону, что дневной лимит постов исчерпан, предложи запланировать на завтра. Не обходи.
- ## 1. The text (owner's voice, top model)
- 1. If the owner gave a ready draft — use it. If he asks "make a post out of X" — write it with the top model in his voice (see `fb-diary-voice`: woven narrative, self-irony, ~4000 characters for a diary entry; shorter for an announcement).
- 2. Show the owner the **final text** and ask for a `+`. This is the Tier-2 gate — no explicit "yes", no next step.
+ ## 1. Текст (голос Антона, Opus)
+ 1. Если Антон дал готовый черновик — бери его. Если просит «оформи из X» — собери на Opus/Fable в его голосе (см. `fb-diary-voice`: вплетённо, с самоиронией, ~4000 знаков для дневникового; короче для анонса).
+ 2. Прогони `slop_gate.py` по тексту. FAIL = переписать **сейчас**, в этом же заходе. Пройден — публикуй, разрешения не жди.
- ## 2. The browser (Claude-in-Chrome, live tab)
- > Browser work is strictly LOCAL to this machine. Don't pull the Claude window to the front.
- > ⛔ IP gate (owner, 2026-07-16): posting/commenting on Facebook happens ONLY from the hub (a stable IP). On another machine? Do NOT post from here — send the job to the hub as text (bus / fleet log chat). Canon: `ip-sensitive-actions-hub-only`.
+ ## 2. Браузер (Claude-in-Chrome, живая вкладка)
+ > Браузерная работа — строго ЛОКАЛЬНО на этой машине (Антон за хабом). Не тащить окно Claude вперёд.
+ > ⛔ IP-гейт (anton 16.07): постинг/комментинг FB — ТОЛЬКО с хаба `[машина флота]` (постоянный IP). Ты на другой машине? НЕ постить отсюда — задачу текстом на хаб (шина/03). Канон: `reglament-ip-sensitive-deystviya-tolko-s-haba`.
- 1. Check that the Chrome MCP is connected: `mcp__Claude_in_Chrome__list_connected_browsers`. If not — ask the owner to open Chrome with the extension (don't fall back to Playwright).
- 2. Open/select the `facebook.com` tab (he is already logged in — do NOT touch login/password). If not logged in — that is a blocker, tell the owner.
- 3. Find the composer: `mcp__Claude_in_Chrome__find` with the query "What's on your mind — create post box". Click it to open the post creation dialog.
- 4. Type the text into the composer field (`form_input` on the ref from `find`). **Do NOT press "Publish"** yourself until the Tier-2 gate from §1 is cleared.
- 5. After the owner's explicit `+` — press the "Publish"/"Post" button (or ask him to press it, if he is nearby and wants to). ⚠️ The dialog is two-step: compose → "Next" → Post settings → "Post". Take a screenshot of the result (`computer` screenshot) so the owner SEES that the post went out.
- 6. **Footer as the 1st comment** (rule §7.7, the post body carries no links): open the published post → the "Comment" field → blocks B+C+E from `_imports\content-factory\_STYLE-footer.md` (live links only). ⚠️ Enter sends the comment — use Shift+Enter for line breaks.
- 7. **Self-like** (owner's rule 2026-07-05: "the first like is always the hard one"): like your own post right after the footer comment. A standard step, no separate asking.
- 8. Composer pitfall: the first click can land on Stories (the feed shifts while lazy-loading) — after navigating, wait ~2s, screenshot, then click on the fresh coordinates.
+ 1. Проверь, что Chrome-MCP подключён: `mcp__Claude_in_Chrome__list_connected_browsers`. Если нет — попроси Антона открыть Chrome с расширением (не падай в Playwright).
+ 2. Открой/выбери вкладку `facebook.com` (он уже залогинен — НЕ трогаем логин/пароль). Если не залогинен — это блок, скажи Антону.
+ 3. Найди композер: `mcp__Claude_in_Chrome__find` запросом «What's on your mind / Что у вас нового — create post box». Кликни, чтобы открыть окно создания поста.
+ 4. Введи текст в поле композера (`form_input` по ref из `find`). Перед отправкой перечитай, что РЕАЛЬНО легло в поле (§3.6: буфер обмена — общий ресурс машины, чужая вставка ловится только глазами).
+ 5. Жми «Опубликовать»/«Post» сам. ⚠️ Диалог двухшаговый: compose → «Next» → Post settings → «Post». Нужна отложка вместо стены — в том же меню **Schedule post**, дата/время, потом проверь вкладку `content_library/?filter=SCHEDULED`. Сделай скриншот результата (`computer` screenshot), чтобы Антон ВИДЕЛ, что пост ушёл.
+ 6. **Футер 1-м комментарием** (правило §7.7, тело поста без ссылок): открой опубликованный пост → поле «Comment» → блоки B+C+E из `_imports\content-factory\_STYLE-footer.md` (только живые ссылки). ⚠️ Enter отправляет коммент — переносы строк только Shift+Enter.
+ 7. **Лайк-хвост** (правило Антона 05.07 «первый лайк всегда тяжело ставить» + голосовая 04.08 «все наши посты и комментарии должны получать лайки»): сразу после футер-коммента поставь Like (а) на свой пост, (б) на свой футер-коммент, (в) на КАЖДЫЙ комментарий под постом и на наши ответы в тредах. Штатный шаг, отдельно не спрашивать. Полный порядок, гейт темпа и запись в счётчик — скилл `/fb-likes` ЛЕЙН 1 (перед серией `fb_guard.py check like_own`, после каждого лайка `record like_own`).
+ 7-бис. **Кнопки модалки жми по `ref`, не по координатам** (пережито 15.09.2026, пост касбука): клик по координатам «Next» закрыл диалог вместо перехода, черновик остался в композере и в ленте выглядел как опубликованный пост. Порядок: `find` «Next button in Create post dialog» -> клик по `ref` -> `find` «Post button in Post settings» -> клик по `ref`. И не верь `find` про реакции: он возвращает счётчики ЧУЖИХ постов той же страницы; число отклика бери из текста страницы рядом с телом СВОЕГО поста. `Page.captureScreenshot` на FB виснет пачками по 30с — доказательство публикации собирай перезагрузкой пермалинка и чтением текста, а не скриншотом.
+ 7-тер. ⚠️ **ВТОРОЙ ЭКРАН `Post settings` НЕСЁТ ДВЕ КНОПКИ, И `find` ПУТАЕТ ИХ** (пережито 20.09.2026, пост касбука — это ПОПРАВКА к 7-бис, чей совет «клик по ref на Post» и привёл к провалу). За `Next` открывается экран `Post settings` с Post preview и ДВУМЯ кнопками в ряд: `Save` (слева, серая — сохраняет ЧЕРНОВИК) и `Post` (справа, синяя). Экран несколько секунд висит скелетом, и `find` в этот момент честно возвращает «Post button (submit)», который на деле оказывается сохранением. Итог 20.09: композер закрылся, текст остался в `region[Create a post]`, пост выглядел опубликованным, а на стене сверху стоял вчерашний.
+ Рабочий порядок: `Next` по `ref` -> ЖДАТЬ 6с -> СКРИНШОТ и убедиться глазами, что видны Post preview и ОБЕ кнопки -> клик по `Post` координатами из ЭТОГО свежего скриншота (здесь координаты ПРАВИЛЬНЕЕ, чем `ref`, потому что различают соседние кнопки).
+ Как отличить публикацию от черновика (наличие текста в `document.body.innerText` НЕ доказывает ничего, черновик лежит там же): текст обязан найтись внутри `div[role="article"]`, а у страницы обязан появиться пермалинк `.../posts/pfbid...`. Диалог браузера «Leave site? unsaved changes» при уходе со страницы = висит черновик.
+ Футер первым комментом: Enter в поле комментария ОТПРАВЛЯЕТ — переносы строк только `shift+Return`; пермалинк поста удобнее всего снять из `location.href` сразу после клика по «Leave a comment».
- ## 3. Record it in the counter (AFTER a successful publication)
+ 8. Грабли композера: первый клик может попасть в Stories (лента сдвигается при ленивой подгрузке) — после навигации подожди ~2с, скриншот, потом клик по свежим координатам.
+
+ ## 3. Зафиксируй в счётчике (ПОСЛЕ успешной публикации)
```bash
python "$USERPROFILE/.claude/scripts/fb_guard.py" record post
```
- ## 4. Report
- One line: what was published + link/screenshot + "posts today N/8".
-
- ---
-
- ## Kill switches (account safety)
- - Any Facebook warning (checkpoint, "you're doing this too often", an identity confirmation request) → **STOP immediately**, report to the owner, do NOT retry-spam (retries are exactly the road to a ban).
- - Don't republish identical text.
- - Don't touch login/password/2FA — if the session is logged out, that is a blocker for the owner.
-
- ## Related
- - `/fb-reply` — replying to comments (Phase 1, the same guard).
- - The counter engine: `~/.claude/scripts/fb_guard.py` (shared across post/reply/dm).
- - Texts: `content-factory`, `facebook-diary`, `episode`; the voice — `fb-diary-voice`.
- - Canon: Decision Memo 2026-06-28 (the Facebook skill set), `chrome-autonomy-self-drive`, `browser-work-on-peers-not-hub`.
-
- ---
-
-
- <!--kit-footer-->
+ ## 4. Доложи
+ Одной строкой: что опубликовано + ссылка/скрин + «сегодня постов N/8».
---
- **Like this skill?** It is one of 100 in [second-brain-starter-kit](https://github.com/tonydzi/second-brain-starter-kit): the second brain we built for ourselves and run every day at Palo Alto AI Research Lab. Install the whole set with `npx skills add tonydzi/second-brain-starter-kit`. Everything is open source and free, so take what you need.
-
- Flagships worth a look on their own: [secondop-panel](https://github.com/tonydzi/secondop-panel) (a second opinion from a panel of external models), [claude-memory-tidy](https://github.com/tonydzi/claude-memory-tidy) (stop your agent's memory from rotting), [telegram-mcp-kit](https://github.com/tonydzi/telegram-mcp-kit) (your own Telegram over MCP in about 15 minutes).
+ ## Стоп-краны (account safety)
+ - Любое предупреждение FB (checkpoint, «вы делаете это слишком часто», запрос подтверждения личности) → **немедленно СТОП**, доложи Антону, НЕ ретрай-спам (ретраи и есть путь в бан).
+ - Не публиковать идентичный текст повторно.
+ - Не трогать логин/пароль/2FA — если не залогинен, это блок для Антона.
- Author: **Anton Dziatkovskii**, Palo Alto AI Research Lab. Telegram [@tonydzi](https://t.me/tonydzi) - WhatsApp [+1 341 222 9178](https://wa.me/13412229178) - X [@Tony_Stef_](https://x.com/Tony_Stef_)
+ ## Связанное
+ - 🗺 **Общая карта FB-рельсы (читать первой при любой FB-задаче):** `~/.claude/scripts/docs/fb-rails.md` — где лежат данные, все капы `fb_guard`, IP-гейт, общие грабли браузера, кто из `fb-*` за что отвечает.
+ - `/fb-likes` — лайк-хвост шага 7 целиком + ежедневный обход лидов.
+ - `/fb-reply` — ответы на комментарии (Фаза 1, тот же guard).
+ - Движок-счётчик: `~/.claude/scripts/fb_guard.py` (общий на post/reply/dm).
+ - Тексты: `content-factory`, `facebook-diary`, `episode`, голос — `fb-diary-voice`.
+ - Канон: Decision Memo 2026-06-28 (набор FB-скиллов), `chrome-autonomy-self-drive`, `browser-work-on-peers-not-hub`.
- **Engineers: want to test-drive this setup?** Message me. I hand out free starter seeds to engineers who test and report back, and custom skill requests are welcome.
+ ## Анти-слоп гейт (anton 14.08)
+ Любой ИИ-написанный текст наружу из этого скилла перед отправкой - финальный проход `/ai-slop` (ban-лист + ритм). Исключения ровно три: текст с плашкой Майкрофта (§3.3) · машиночитаемое (GitHub/техдока/dev-log/journey-machine) · текст, написанный Антоном руками. Канон: `reglament-posty-ot-lica-antona-tolko-cherez-ai-slop`.