contrib-watch · v1.0.0 · 2026-10-07 · sha256 bd5cbcfbfac42661
contrib-watch v1.0.0A
Immutable. This exact content never changes and is served at /api/v1/blob/bd5cbcfbfac42661.
--- name: contrib-watch description: "- СТОРОЖ ВХОДЯЩЕГО ФИДБЭКА: кто из посторонних инженеров пришёл к НАШИМ репозиториям, что написал, сколько часов ждёт… Триггеры: “/contrib-watch“, “/cw“, “кто нам написал“, “проверь входящий фидбэк“, “что там на гитхабе“, “есть ли новые контрибьюторы“, “кто пришёл“, “долги по PR“, “check inbound feedback“, “who contributed“, а также САМ в начале любой сессии, где речь про GitHub, флагман" version: 1.0.0 --- # /contrib-watch — кто пришёл к нам сам, и почему мы обязаны ответить сегодня ## Закон **Молчание в живом треде = провал, а не осторожность** (CLAUDE.md §4.7). Ответ на GitHub я даю САМ, без «+» Антона и без гейта [коллега]. Мерж кода — по [[github-publish-autonomous]] + leak-scan. **Порог: 24 часа.** Дольше — красное. Обоснование не теоретическое: 05.08 замерено, что четырёхдневное молчание случилось не из-за занятости, а из-за отсутствия прибора. ## Шаг 1 — снять картину (0 токенов) ``` python ~/.claude/scripts/contrib_watch.py --html "$OBSIDIAN_VAULT/_Dashboards/Contrib-Inbox.html" ``` Обходит все наши публичные репозитории, находит треды, где ПОСЛЕДНИМ говорил внешний человек, считает часы ожидания, отмечает 🆕 тех, кого не видели ни разу. Exit 3 = есть просрочка. ## Шаг 1-бис — «последним сказал чужой» ≠ долг: разговор мог уехать в PR Эвристика «последний говоривший в треде» ловит ДОЛГ и МИГРАЦИЮ одинаково, а это разные вещи. Нормальный цикл выглядит так: человек пишет в issue «claiming this» или «I opened PR #N» — и дальше по существу говорят уже в PR. В issue его строка так и остаётся последней НАВСЕГДА, даже когда мы разобрали, отревьюили и смержили. Долга там нет, мяч не наш. Поэтому на КАЖДЫЙ хит спрашиваю ещё один вопрос, прежде чем идти отвечать: ``` gh api "/repos/tonydzi/<repo>/issues/<N>/timeline" --paginate --jq '.[]|select(.event=="cross-referenced")|.source.issue.number' gh api "/repos/tonydzi/<repo>/issues/<PR>/comments" --paginate --jq '.[]|"\(.user.login) @ \(.created_at)"' gh api "/repos/tonydzi/<repo>/pulls/<PR>/reviews" --paginate --jq '.[]|"\(.state) \(.user.login) @ \(.submitted_at)"' ``` Наш ответ в связанном PR ПОЗЖЕ его последней строки в issue = касание обслужено, хит закрыт. ⚠️ ЗАМЕР 21.09.2026: скан дал 4 хита (`sqlite-graph-memory` #13 #9 #5 #4), и ВСЕ ЧЕТЫРЕ оказались миграцией: #13→PR #14, #9→PR #10, #5→PR #8, #4→PR #6, каждый смержен с письменным ревью Майкрофта ПОСЛЕ их последней реплики. Долгов было 0. Без этого шага рутина пошла бы писать четырём инженерам «извините за молчание» в треды, где мы им уже развёрнуто ответили, — то есть сама сломала бы репутацию, которую сторожит. ⛔ Обратное упрощение запрещено: «есть связанный PR» само по себе хит НЕ закрывает — закрывает именно НАШ ответ в нём с датой позже. Смерженный молча PR без единого нашего слова — это долг (§4.7: молчание в живом треде = провал), и он идёт в Шаг 4 как обычное касание. ## Шаг 2-ноль — «наш он или нет» решается ДВУМЯ селекторами, а не одним ⛔ Прежде чем сказать «этот новый логин не наш, карточку не завожу» (так закрыли [человек]-KUKLEVA и dudididjdje-tech 13.09) — спроси GitHub ОБОИМИ вопросами: ``` gh api "search/issues?q=commenter:<login>+user:tonydzi" --jq '.total_count' # он у нас ГОВОРИЛ gh api "search/issues?q=involves:<login>+user:tonydzi" --jq '.total_count' # он у нас АВТОР/упомянут ``` ⚠️ ЗАМЕР 21.09.2026: по `commenter:` оба новых логина дали **0** — вывод «не наши» был готов и был бы ЛОЖНЫМ. `involves:` дал по **1**: [человек] и b7n0de оказались АВТОРАМИ самоподач PR #4 и #5 в `tonydzi/awesome-verified-agents`. Автор PR, который не написал ни одного комментария, для `commenter:` невидим. Правило: ноль по одному селектору = «этим селектором не видно», а не «человека нет» (§5.4, [[check-all-places-not-one]]). Хоронить контакт можно только когда молчат ОБА. ## Шаг 2 — ПРОВЕРИТЬ МОТИВ, прежде чем радоваться ⛔ Самая дорогая ошибка этого скилла — принять массового контрибьютора за фаната. По каждому новому человеку обязательно: ``` curl -s -H "Authorization: Bearer $GITHUB_FLEET_FULL_PAT" \ "https://api.github.com/users/<login>/events/public?per_page=100" ``` и посчитать: сколько PR за 90 дней, в сколько РАЗНЫХ репозиториев, повторяется ли один и тот же патч у всех адресатов. Три класса, и вести себя с ними надо по-разному: | Класс | Как выглядит | Что это значит | Наш ход | |---|---|---|---| | 🟢 глубокий | мало репо, много касаний в одном | человек реально пользуется | триаж-права, соавторство, звонок | | 🟡 массовый качественный | 40+ PR в 20 репо, но патчи настоящие | конвейер репутации, идёт вглубь ТУДА, ГДЕ ОТВЕЧАЮТ | ответить в тот же день — скорость и есть весь рычаг | | 🔴 массовый агентский | 40+ PR, текст сгенерирован, факты не сходятся | прогон чужого агента по случайным целям | честное «нет» с разбором + приглашение вернуться по существу | Мотив пишем в карточку СЛОВАМИ и с уликой. «Пришёл сам» ≠ «мы ему нравимся» ([[prichina-kak-claim]]: причина — такой же claim, как вывод). ⭐ Первый вопрос про КАЖДОГО — **«мы туда стучались?»** (правило `external-signal-vs-reply-to-our-knock`, замер 06.08). Три кучи, и они НЕ равны: (1) непрошеное — назвал нас в ЧУЖОМ треде, куда мы не приходили → настоящий сигнал; (2) подали-приняли — мы отправили PR/заявку, редактор согласился → считаем, но называем отдельно; (3) ⛔ ответ под НАШИМ собственным PR/issue → это отклик на наш стук, за входящий интерес НЕ засчитывать. Наша исходящая работа физически рождает ответы, и они попадают под тот же поиск, что органика — метрика внешней тяги ломается всегда вверх, в приятную сторону. ## Шаг 3 — проверить ЗАЯВЛЕННОЕ, а не поверить Патч утверждает цифры (звёзды, лицензия, бенчмарк, «чинит X») — проверяю каждую своим прибором до мержа. Мы лаборатория про проверяемость; смержить непроверенное утверждение о себе = сжечь собственный тезис. Тесты гоняю ЛОКАЛЬНО на объединённой ветке, не доверяя зелёному CI: ``` git fetch origin 'refs/pull/*/head:refs/remotes/pr/*' git checkout -B try<N> master && git merge pr/<N> && pytest -q ``` ⭐ **Проверяю ТРИ вещи, а не одну** (боль 13.09 + 15.09, оба раза на sqlite-graph-memory): 1. **патч** — делает ли он то, что заявлено; 2. **тесты патча** — мутацией: откатываю починку и смотрю, КРАСНЕЮТ ли его тесты. 13.09 все 12 остались зелёными на возвращённом баге: фикс был верный, тесты его НЕ держали. Мержу всё равно (двигать ворота после выполнения = обман), но свой красный тест дописываю сам; 3. ⭐ **не протух ли САМ ПАТЧ, пока лежал** — репозиторий едет под ним. 15.09: PR#7 чинил строку «no tests», а за пять дней ожидания PR#6 добавил 42 теста в соседний модуль, и написанная автором строка стала ложной ровно в момент мержа. Третье поколение одного дефекта в одном абзаце. Правило: патч, пролежавший дольше суток, перечитывается против ТЕКУЩЕГО состояния репозитория, а не против того, каким оно было при его отправке. Если протух — это не повод не мержить и не повод винить автора. Мержим его работу под его авторством, а дрейф чиним follow-up'ом сверху и НАЗЫВАЕМ его в треде: человек узнаёт то, чего не мог знать, и это самая ценная часть ответа. ## Шаг 4 — ответить (голос Майкрофта, §3.3) Первой строкой называюсь: «hi, this is Mycroft, Anton's synthetic co-founder». Один раз на тред. Строчными, без ваты. Структура ответа, которая работает: 1. **Извиниться за задержку конкретно и назвать причину** — не «sorry for the delay», а что именно у нас не работало. Люди прощают поломку и не прощают отписку. 2. **Назвать, ЧТО ИМЕННО он поймал**, своими словами и по существу — доказательство, что читали код. 3. **Вердикт**: смержено / нужен ребейз с точной резолюцией конфликта / не берём и почему. 4. **Следующий шаг с датой** и один открытый вопрос. 5. ⭐ **Подпись-CTA последней строкой** (anton 10.09, голосовая hub:6539; supersedes прежнее «без подписи» в этом шаге). Одна строка со ссылкой `github.com/tonydzi`, формулировку варьировать. Источник текста — `$OBSIDIAN_VAULT/08-Templates/github-touch-signature.md`, карта поверхностей — `$OBSIDIAN_VAULT/08-Templates/outbound-signature.md`. Здесь это особенно дёшево и особенно окупается: человек УЖЕ пришёл к нам сам и уже читал наш код — это самый тёплый входящий, какой у нас бывает, а он уходил, не увидев, что рядом лежит ещё 60 репо. Carve-out против спама: одна подпись на тред — подписался, в следующих репликах того же треда можно без неё. Раскрытие Майкрофта = СВЕРХУ (первая строка), подпись = СНИЗУ; это разные блоки, один другого не заменяет. Отказ пишу так же подробно, как согласие. Честное «нет» с разбором удерживает человека; молчание не удерживает никого. ## Шаг 5 — завести в CRM в тот же заход Каждый внешний человек: - строка в `$OBSIDIAN_VAULT/_outreach/tracker.json` → `audience_A_engineers` (поля: handle `github:<login>`, channel `github`, warmth с УЛИКОЙ мотива, what_they_did, our_answer_at, ladder, next_step); - карточка `$OBSIDIAN_VAULT/07-People/person-<slug>.md` с frontmatter `context: github-contributor`, `origin: github`, тегами `[person, github-contributor, engineer-funnel]` и обратными ссылками на артефакт (правило no-orphan). ## Шаг 5-бис — если в треде был СОВЕТ, а не только патч → в реестр кредита Человек написал, ЧТО нам стоит сделать (даже одной строкой, даже без кода) — это вклад идеей, и он обязан дожить до имени в CREDITS. Кладу строку сразу, не «потом»: ``` python ~/.claude/scripts/alpha_credit.py add --source gh \ --author "<Имя или login>" --handle @<login> --url <ссылка на коммент> \ --advice "<что посоветовал одной фразой>" --kind method|repo|tool|critique \ --ref "gh:<owner/repo>#<номер>:<id коммента>" ``` `--ref` обязателен: этот скилл ходит по одному треду каждый день, без ключа один совет размножится копиями. Дальше цепочка живёт в `/alpha-credit` (судить → испытать → спасибо → имя). ## Шаг 6 — контент Входящий PR от постороннего = контентный момент по определению. Рефлекс [[content-miner-reflex]]: ``` python "$VAULT_IMPORTS/content-factory/content_miner.py" capture --title "<хук>" --note "<суть>" --tier medium ``` Сильная форма истории — не «нам прислали PR», а «что он поймал такого, чего не видели мы». ## Шаг 7 — вердикт ⚠️ **Красное у сторожа — это claim, а не приговор** ([[instrument-is-a-claim-too]]). Перед ответом человеку сверь ДВЕ вещи, которых сторож не знает: - **чей мяч по последнему касанию** — с 14.09.2026 он читает и РЕВЬЮ (`/pulls/N/reviews`), а не только комментарии треда; до этого канонический ответ по §4.7 был для него молчанием, и он печатал ВОЗРАСТ самого PR как долг (PR#7: 90.1 ч при PR, созданном 10.09 10:46Z); - **срок, который мы САМИ дали автору** — этого сторож не знает вообще. Пообещали ждать правку до N-го числа — до N-го числа долга нет, и бампать нельзя, даже если строка красная. ✅ только когда: ноль просроченных долгов · мотив каждого нового человека проверен уликой · CRM пополнен · заявленные цифры перепроверены до мержа. ⚠️ если ответили, но не проверили мотив или не завели в CRM. ## Рутина Ночной прогон (окно 23:00-06:00 Лиссабон, §4.6) + дневной тик: сторож живёт ВНЕ сессии, молчит когда чисто, кричит только на просрочку с именем человека и ссылкой (§5.5). ## Счётчик Каждый прогон пишет строку в `~/.claude/logs/part_usage.jsonl` (`part: contrib_watch.py`, `event: scan`, `outcome: clean|overdue`). Судьба детали решается на /retro по этому счётчику (§5.8). ## ⭐ Обратная половина: мы тоже просим (anton 21.09.2026) Этот скилл ловит ВХОДЯЩЕЕ касание инженера. Входящего не будет, если у репо нет видимой просьбы: люди приходят по `label:"help wanted"`, а не по README. Закрыл входящее и увидел, что у репо ноль своих просьб → завести их по `/consumer-hunt` Шаг 5-бис (дыры берутся из наших же секций `What's intentionally missing` / `Honest limits` / `Roadmap`, выдумывать ⛔). Реестр просьб: `$OBSIDIAN_VAULT/_outreach/we_ask_registry.jsonl`. ## Связи Док-паспорт: `~/.claude/scripts/docs/contrib-watch.md` · канон: `reglament-vhodyashchiy-fidbek-inzhenerov-otvechaem-v-sutki` · память: [[github-inbound-watch]], [[github-communication-autonomous]], [[engineer-acquisition-enrichment-not-scraping]] · соседи: `/consumer-hunt`, `/issue-match`, `/github-growth`, `/local-engineer-outreach` <!--kit-footer--> --- **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). 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_) **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.