---
name: cv-outreach
description: "Исполнить дневную порцию ИСХОДЯЩЕГО по календарю Долины — регистрации на события, личка организаторам, публичные касания в X. Триггеры “/cv-outreach“, “/выход“, “порция исходящего“, “жуй очередь исходящего“, “напиши людям с ивентов“, “закрой регистрации на неделю“, “кому мы сегодня пишем“, “work the outreach queue“"
version: 1.0.0
---

# /cv-outreach — дневная порция исходящего по календарю Долины

> ⛔ **ЛИЧНОСТЬ БРАУЗЕРА (канон 30.08.2026).** Chrome профиля Default на хабе = личность Антона (claude.ai там под **[рабочий аккаунт]**, всегда).
> Робот здесь **ЧИТАЕТ и действует, но НЕ ТРОГАЕТ ЛОГИНЫ**: ни logout, ни смены аккаунта, ни «самолечения входа», ни инжекта кук.
> Увидел «не тот аккаунт» → доложи и работай из робо-профиля (`_chrome_profile_a2`, Firefox-профили). Канон: `reglament-hab-brauzernye-lichnosti-bb-i-roboty`.

> 🧒 Отчёт Антону закончи блоком «Простыми словами».

## Зачем существует

Замер 27.08.2026: **769 человек собрано в CRM, след контакта — у одного**. Полоса
`cv-events` умела добывать и считать, но ни одного шага наружу в ней не было: все 18 заявок
подала живая сессия руками, а живой сессии по расписанию не существовало. Антон 28.08 выбрал
путь **A — достроить исходящее**. Дешёвая половина (двери, очередь, порция) считается ночью
рутиной `CV-Outreach-Daily`, 0 LLM. Этот скилл — дорогая половина: руки и голос.

Правило Connect: собранное и не использованное = не собранное. Порция не исполнена — полоса
не работает, сколько бы людей она ни намайнила.

## Шаг 0 — взять порцию (0 токенов)

```
python [путь владельца] today --n 8
```

Ночная рутина уже положила её в `cv-events\cv_outreach_today.md`. Если файл старше суток —
пересобрать: `python cv-events\cv_outreach_daily.py`.

Каждая строка несёт: `id` · полосу (`kind`) · канал · кому · **повод** · дедлайн · ссылку.
⚠️ **Дате в порции верить не на слово.** Календарь-источник пишет день без года, поэтому
строка может нести пометку «дата НЕ сверена с источником» — такую дату перед касанием
проверяем на странице события (замер 29.08: из 342 «будущих» событий 196 прошедшие,
дневная порция дала 5 мёртвых из 6). Сверенные даты подставляет `true_starts()` из
`luma_dates.jsonl` + `event_dates.jsonl`; вторую половину наполняет `event_dates_fetch.py`.

Повод — это провенанс из карточки (правило `reglament-lid-v-crm-nesyot-ves-kontekst-znakomstva`).
Касание без повода не отправляем: холодный веер = спам, а спам ≠ громкость (§1.5).

## Шаг 0.5 — проверить РЕЛЬСУ, прежде чем обещать порцию

Полоса `apply` требует браузера с ЖИВОЙ сессией luma (`dzyatkovskiy.a2@gmail.com`, вход
Passkey либо Google). Замер 28.08: во встроенном браузере приложения luma **разлогинена**, а
`claude-in-chrome` на хабе показывал только чужой macOS-узел — то есть полоса apply в тот
момент физически не ехала.

Поэтому первым делом: `list_connected_browsers` (Chrome) либо открыть `luma.com` и прочитать,
залогинены ли мы. Рельса мертва → **не молчать**: пометить строки `--outcome failed --note
"рельса: браузер без сессии a2"`, доложить в 03 и в отчёт Антону одной строкой, и отработать
полосы `dm-tg` и `x-touch`, которым браузер не нужен. Пароль символами не набираем никогда —
подаёт Chrome/Passkey сам; нет Chrome — это блок рельсы, а не повод вводить руками.

## Шаг 0.6 — жива ли ПОЛОСА, а не только браузер (добавлено 07.09.2026)

Шаг 0.5 проверяет рельсу apply. Полоса при этом может быть мертва тише: замер 07.09 —
32 строки `x-touch` и 1 `dm-tg` не несли ключ `date_verified`, а `today_portion()`
fail-closed выбрасывает всё, где его нет. С 03.09 наружу ездила ТОЛЬКО `apply`, и ни один
счётчик не кричал: порция каждый день выглядела полной.

Перед работой — один взгляд на состав очереди по полосам:

```bash
python "$IMPORTS_ROOT/cv-events/_test_cv_lane_date_verified.py"
```

Полоса, у которой **все** строки `False`, в порцию не попадёт НИКОГДА — это дефект, а не
«сегодня нечего слать». Сторож — `_test_cv_lane_date_verified.py` (красный-первым).
Правило шире одной полосы: **порция без полосы ≠ полоса без работы**; молчащий канал
называем вслух, а не считаем пустым.

## Шаг 0.7 — правишь КОД полосы → сперва доска ON AIR (добавлено 04.09.2026)

Касания наружу доску не трогают, а вот правка `cv_outreach.py` / `luma_apply.py` / профиля —
это код в зоне `vault-imports`, где параллельно может сидеть чужая EXCLUSIVE-табличка. Замер
04.09: правил движок полосы, пока зона пятый час висела EXCLUSIVE за соседней сессией (§7.7
требует скан, у рутинного исполнителя шага не было вовсе).

```
python ~/.claude/scripts/onair.py list
```
Зона свободна → правлю. Занята EXCLUSIVE → либо жду, либо пишу владельцу в 03, либо правлю
только СВОЙ подкаталог и говорю об этом строкой в отчёте. Крупная правка движка → своя
табличка: `onair.py declare --zone vault-imports --mode collab`, в конце `onair close`.

## Шаг 1 — исполнить по полосам

Три полосы, и каждая живая. ⛔ **LinkedIn в очередь не входит вообще** — аккаунт забанен;
3670 собранных linkedin-хэндлов лежат справкой, каналом не являются.

### `apply` — регистрация на событие
Самый сильный канал: Антон в Долине с сентября, прийти на их событие теплее любого письма.
Исполняется скиллом **`/luma-apply`** (план ответов из публичного API, потом браузер).
⛔ Цена → `price_gate` → стоп и аск Антону, деньги = Tier-2.

### `dm-tg` — личка в Telegram
Только те, с кем **уже есть живая переписка** (замер 28.08: таких 45 из 2676). Отправка —
через Сиренку (`crm-engine/safe_send.py`) под её бюджетом; при работе с десятком и больше
диалогов конвейер обязателен (§9.8), для одного сообщения — можно напрямую.

### `x-touch` — публичное касание в X
Только к организатору события, на которое мы **реально идём**. Повод настоящий: «иду к вам».
Формат — короткая человеческая реплика, не питч. Автоматический label `Automated` по §3.3.

⛔ **ПОВОД ИЗ ОЧЕРЕДИ — ЭТО CLAIM, СВЕРЬ ЕГО НА СТРАНИЦЕ СОБЫТИЯ** (замер 08.09.2026). Очередь
пишет всем строкам один и тот же повод «мы зарегистрированы (pending-approval)»; по факту из
3 строк порции только у одной статус был `Pending Approval`, две другие — `You're on the
Waitlist`. Waitlist ≠ «идём», и публичное «иду к вам» по такому поводу = неправда в evidence
(§5.4). Порядок: открыть luma-страницу события → прочитать блок статуса → `Pending Approval`
или `You're In` = пишем; `Waitlist` / пусто = `mark --outcome skip` с причиной, молча не
пропускаем.

⚠️ **Длинный ответ в поле — только `form_input`, не `computer:type`** (замер 08.09: type съел
4 символа из 128 — «ar human», «eams», «wht», «endto-end»; поймано перечиткой по §3.6).

⚠️ **Исключение: композер X — `form_input` там НЕВОЗМОЖЕН** (замер 09.09). Поле твита это
contenteditable `DIV`, инструмент отвечает `Element type "DIV" is not a supported form input`.
Хуже: первый `computer:type` после клика по `ref` доехал НУЛЁМ символов — поле осталось
пустым, а рапорт инструмента был бодрый «Typed ...». Поймано только перечиткой §3.6.
✅ **ЛУЧШЕ: обходи композер X через intent-URL** (замер 10.09.2026). `https://x.com/intent/post?text=<urlencoded>`
открывает композер с УЖЕ заполненным полем: contenteditable не трогаем вовсе, `@handle`
распознаётся упоминанием сам, счётчик сразу верный. Тем же ходом снялась модалка «Updates to our
Terms of Service», которая в тот день закрывала обычный композер и не уходила по Escape:
жать её `Got it` = принять условия за Антона (Tier-2), а intent-страница её не показывает.
Порядок: собрать текст питоном (`urllib.parse.quote`) → navigate → скриншот и сверка поля → Post.
Старый ручной набор ниже — фолбэк, если intent-URL когда-нибудь отвалится.

Рабочий порядок для X: клик по **координате** поля (не по `ref`) → `type` кусками по 1-2
предложения → упоминание `@handle` **отдельным куском** и сразу `Escape` (автодополнение X
перехватывает следующий ввод) → скриншот и сверка счётчика символов с расчётным ДО кнопки
Post. Счётчик X показывает остаток от 280: 262 набранных = «18».

⚠️ **ВЫПАДАЮЩИЙ СПИСОК: клик по координате из СТАРОГО скриншота берёт СОСЕДНИЙ пункт**
(замер 11.09.2026, поймано ДВАЖДЫ за одну форму). Между батчами страница подскакивает на
30-40px, список закрывается и открывается заново — в luma-форме так выбралось `Student`
вместо `Founder` и `Not looking` вместо `Open to the right thing`. Второе прямо противоречит
цели №2 (оффер). Рабочий порядок: `form_input` по `ref` — у select'ов luma значение
ПРИМЕНЯЕТСЯ визуально; если не применилось, открыть список и кликнуть опцию **отдельным
вызовом сразу после свежего скриншота**. ⛔ Чекбокс через `form_input` откатывается
ре-рендером (галочка ставится и слетает при следующем изменении формы) — его жмём мышью и
сверяем глазами В ТОМ ЖЕ кадре, где жмём submit.

⛔ **ESCAPE В ЧЕКАУТЕ EVENTBRITE = «Leave Checkout?» И ПОТЕРЯ ВСЕЙ ФОРМЫ** (замер 11.09.2026).
Привычка гасить автодополнение Escape'ом (пришла из X, шаг про композер) в eventbrite стирает
уже введённые поля: доехало только первое из четырёх. Автодополнение там гасится просто
кликом в следующее поле. Чекаут живёт в iframe: `read_page`/`find` его НЕ видят, работаем
координатами, а колесо мыши крутит страницу ПОД ним — скроллим перетаскиванием полосы
прокрутки iframe (x≈953).

⛔ **ОДНО СОБЫТИЕ МОЖЕТ ЛЕЖАТЬ В ОЧЕРЕДИ НЕСКОЛЬКИМИ СТРОКАМИ** (замер 11.09.2026: три из
пяти строк `apply` вели на один AI Infra Summit 2026 — разные домены, идентичный HTML
417966 байт). Перед работой по не-luma строкам: один питон-вызов, тянущий `<title>` и
`Content-Length` по всем URL порции разом, дедуп по паре. Дешевле, чем открыть три формы.

⛔ **ДВЕ РЕГИСТРАЦИИ НА ОДИН ДЕНЬ = КОНФЛИКТ, А НЕ ДВА ПОВОДА** (замер 11.09.2026: Open Model
Hack, SF 9:30-19:30, и AI Infra Signal, Sunnyvale 14-19, оба 12.09, оба Pending Approval).
Публичное «иду к вам» обоим хостам — неправда в evidence (§5.4), даже если обе регистрации
настоящие. Порядок: сверить часы и город по всем «горящим» строкам порции ДО касаний;
конфликт есть → пишем ОДНОМУ (тому, чьи спонсоры/хосты пересекаются с живыми заявками и
лидами Антона), второго `skip` с причиной, и спрашиваем Антона, куда он идёт.

⛔ **АНКЕТА С НЕПРОХОДИМЫМ УТВЕРЖДЕНИЕМ ЗАКРЫВАЕТСЯ ЧЕСТНО, А НЕ ГАЛОЧКОЙ** (замер 11.09.2026:
бесплатный билет AI Infra Summit требовал подтвердить «my company does not sell, consult, or
provide AI/ML services» — мы ровно это и делаем, исключение только для large-scale AI labs и
гиперскейлеров). Такое поле — не препятствие к обходу, а ответ «мы не квалифицируемся».
Заявку доводим до этого места, бросаем, `mark --outcome skip` с дословной цитатой поля, и
платную альтернативу отдаём Антону как Tier-2. Родня: [[fake-it-courage-not-fake-numbers]].

⛔ **LUMA МОЛЧА ГЛОТАЕТ ОШИБКУ СЕРВЕРА: «кнопка не нажимается» — ЭТО НЕ ПРО КНОПКУ** (замер 14.09.2026).
`Accept Invite` / `Register` кликается мышью, кликается из JS, кнопка `disabled:false` — и НИЧЕГО не
происходит, ни тоста, ни подписи под полем. Правда живёт только в сети и консоли:
`POST api.luma.com/event/register` → `400`, console → `FetchError: This calendar has been suspended`
(календарь хоста приостановлен, регистрация невозможна ни для кого). Порядок при «submit не работает»:
`read_network_requests` + `read_console_messages` ПЕРВЫМИ, до любых перезаполнений формы; вердикт
`failed` с цитатой ошибки, а не `⚠️ не смог нажать`. Один вызов сети дешевле трёх кругов по форме.

⛔ **`form_input` В ФОРМЕ LUMA НЕ ДОЕЗЖАЕТ ДО REACT** (замер 14.09.2026, стоило 6 лишних заходов).
Значение видно в DOM и на скриншоте, а сабмит видит поле ПУСТЫМ и тихо не отправляет. Нативный сеттер
с `dispatchEvent(new Event('input',{bubbles:true}))` тоже не спасает. Работает ТОЛЬКО живой ввод:
клик в поле → `computer:type` кусками **по 15-20 символов**. Куски по 60-75 символов роняют по букве
в каждом (замер: «ou company», «rouines», «utreach», «woud») — это тот же дефект, что в §type выше,
просто на длинном тексте виден глазами. После набора ВСЕГДА перечитка значений одним JS-вызовом
`[...document.querySelectorAll('input,textarea')].filter(i=>i.offsetParent!==null).map(i=>i.value)` —
и правка до сабмита. Правило §3.6 здесь ловит дефект в 100% случаев.

✅ **МУЛЬТИ-СЕЛЕКТ LUMA НЕСЁТ ПОИСК — НЕ ЛОВИ ОПЦИЮ КООРДИНАТОЙ** (замер 14.09.2026).
Открыл список → сразу `type` название опции → список фильтруется до 1-2 строк → клик по свежему
скриншоту. Это снимает грабли 11.09 (список подскакивает, координата берёт соседний пункт) без
лишних вызовов. После выбора фокус из поиска УХОДИТ: следующий `type` улетит в никуда, для второй
опции надо снова кликнуть в строку поиска и очистить её `ctrl+a`.

⛔ **ПРОФИЛЬ X ВРЁТ О ТОЛЬКО ЧТО ОТПРАВЛЕННОМ ПОСТЕ** (замер 14.09.2026).
Пост ушёл в 08:40:40Z, а `x.com/<handle>` и `/with_replies` ещё минуты показывали старую ленту без
него — выглядит как «не отправилось». Повторный Post по этому «доказательству» даёт
**«Whoops! You already said that»**, и вот ЭТО и есть квитанция, что первый пост доехал, а не ошибка.
Приёмка отправки только одна: `x.com/search?q=from%3A<handle>%20<редкое_слово>&f=live` — оттуда берём
`/status/<id>` в `mark --note`. Жать Post второй раз ⛔: в лучшем случае дубль-ошибка, в худшем два
одинаковых поста в ленте хоста.

### Грабли 20.09.2026 (замер смены cv-outreach-executor) — форма luma заполняется ОДНИМ вызовом

1. **НАТИВНЫЙ СЕТТЕР РАБОТАЕТ. Запись 14.09 «до React не доезжает» ПРОТУХЛА.** Проверено боем на
   трёх формах (kce3d5nr, rgj99uu9 6 полей, aic-gl-9-23 5 полей): значения пережили blur, сабмит
   их увидел, регистрации подтверждены письмами. Рабочий приём, весь ввод за ОДИН javascript_tool:
   ```js
   function setVal(el,v){const p=el.tagName==='TEXTAREA'?HTMLTextAreaElement.prototype:HTMLInputElement.prototype;
     Object.getOwnPropertyDescriptor(p,'value').set.call(el,v);
     el.dispatchEvent(new Event('input',{bubbles:true}));el.dispatchEvent(new Event('change',{bubbles:true}));}
   ```
   Поля адресуются по `name`: `name`, `email`, `phone_number`, `registration_answers.N.value`
   (у вопроса типа company — `registration_answers.N.value.company` и `.job_title`).
   Это снимает весь блок про «куски по 12-18 символов»: печатать руками больше не нужно.

2. **Если всё-таки печатаешь `computer:type` — каретка сбрасывается в 0 после КАЖДОГО куска.**
   «Anton » + «Dzyatkov» + «skiy» дало `skiyDzyatkovAnton `. Повторный заход с `End` между кусками
   не доехал вообще (значение не изменилось, а инструмент отрапортовал «typed 6 chars» — ровно тот
   класс «рапорт об успехе без успеха»). Вывод: один кусок или сеттер из п.1, промежуточных схем нет.

3. **Логин luma для регистрации НЕ НУЖЕН.** Форма принимает имя+email анонимно, квитанция падает
   в a2 Gmail за 1-2 минуты. ⚠️ ПРИЁМКА ТОЛЬКО ПИСЬМОМ: после перезагрузки страница снова покажет
   «Register» (браузер разлогинен, luma не знает, кто ты) — это НЕ провал регистрации.
   Второй заход: `search_threads` по `from:luma-mail.com newer_than:1d` → «Registration confirmed» /
   «Registration pending approval» с названием события.

4. **Дешёвая половина решает почти всё: гони api.lu.ma по ВСЕЙ порции одним скриптом ДО браузера.**
   Один проход отдаёт цену, `sold_out`, `calendar.is_blocked`, список вопросов с типами, город и
   `location_type`. Замер 20.09: 6 строк из 7 закрылись без единого клика (3 skip по цене/местам/городу,
   3 заявки с готовым планом ответов). Заголовок `User-Agent` обязателен, иначе 403.

5. **Строка очереди врёт про место.** `apply:o8mz88ls` шла как `REMOTE`, а api отдал offline/New York.
   Город берём из `event.geo_address_info`, а не из строки порции.

6. **Чекбокс:** `input[type=checkbox].click()` + перечитка `.checked` через ~1.2с. Держится
   (в отличие от `form_input`, который откатывался ре-рендером).

## Грабли 21.09.2026 (смена cv-outreach-executor, оплачено полным повтором формы)

1. **ТИПЫ ПОЛЕЙ ЛЕЖАТ В `data.registration_questions`, а не в `event_registration_questions`.** По второму ключу `api.lu.ma/url?url=<slug>` отдаёт ПУСТО, и форма на 15 полей выглядит двухполевой. Правильный запрос (с User-Agent, иначе 403):
   `curl -H "User-Agent: Mozilla/5.0" "https://api.lu.ma/url?url=<slug>" | jq '.data.registration_questions[] | {question_type, required, label}'`
   Оттуда же `ticket_types` (цена в центах), `calendar.is_blocked`, `event.geo_address_info`.

2. **`question_type: linkedin` БЬЁТ ПОДМЕНУ НА GITHUB — и делает это МОЛЧА.** Сабмит не даёт НИЧЕГО: POST на `api.luma.com/event/register` вообще не уходит, у полей ноль подсветок, в консоли только посторонние 403, страница просто остаётся в `Request to Join`. Выглядит как «кнопка не работает», а это провалившаяся клиентская валидация. Адрес Антона, который публикует его собственный лендинг (`04-Projects/scholar-homepage/site/index.html`): `https://www.linkedin.com/in/anton-dzyatkovskiy` — брать его, не выдумывать и не подставлять github. Аккаунт забанен, но поле требует ФОРМАТ, а не живую страницу.
   `question_type: github` хочет ЮЗЕРНЕЙМ (`tonydzi`), не URL; `twitter` — хэндл без собаки.

3. **Комбобокс НЕЛЬЗЯ искать по `placeholder === 'Select an option'`** — placeholder остаётся в атрибуте и ПОСЛЕ выбора, поэтому цикл по кругу открывает первый же комбо и до остальных не доходит (потерял 4 вызова). Брать строго по id (`_r_e_`, `_r_s_`, `_r_13_`), а `.value` перечитывать ОТДЕЛЬНЫМ вызовом: в том же вызове, где кликнул опцию, React ещё не обновил значение.

4. **Кнопок `Request to Join` на странице ДВЕ**, вторая фантомная с координатой `y = -26964`. Ловить `button[type="submit"]` — он ровно один и лежит внутри `<form>`.

5. **Приёмка только письмом.** Страница после анонимной регистрации врёт в обе стороны: и «Pending Approval» без письма (провал), и «Request to Join» после успеха. Истина — квитанция luma в a2 Gmail за 1-2 минуты, одним запросом на всю порцию:
   `from:luma-mail.com subject:(pending approval) newer_than:1d`

6. **Solo на хакатоне законен**, если в «How many team members?» есть `1 (only me)`. Роль Антона в таких анкетах — `Engineer/Developer/Researcher`, **никогда `Founder`** (память `never-call-anton-a-founder`).

## Грабли 23.09.2026 (смена cv-outreach-executor) — два claim'а, которые выглядели как факты

1. **`search_dialogs` СКАНИРУЕТ ТОЛЬКО 1000 ПОСЛЕДНИХ ДИАЛОГОВ — по нему НЕЛЬЗЯ говорить «переписки нет».**
   Стоило неверного вердикта: по двум строкам `dm-tg` я объявил «диалога нет ни в одном из 4 аккаунтов»
   и пометил их `skip` с формулировкой «ПОВОД ЛОЖНЫЙ». На деле диалог с `[аккаунт]` живой с 2024 года
   (знакомство лично на конференции), просто глубже окна сканирования. Поймано только вторым заходом.
   ✅ Порядок: берём `tg_id` и `accounts` из `contacts` в `leads.db`, затем `get_history(tg_id, account=...)`.
   Отсутствие в поиске по списку диалогов = «не нашёл», а не «нет» ([[check-all-places-not-one]]).

2. **«Бесплатного билета нет» — тоже claim, и он протухает. Смотри ВСЕ `ticket_types`, а не первый платный.**
   Аск #c8838287 от 15.09 утверждал: у [человек] World Congress «бесплатного билета нет вообще,
   минимум Startup Pass 499 USD». 23.09 тот же `api.lu.ma` отдал третьим элементом `Networking Day - Sept 23`
   с `cents: None` — бесплатный warm-up day от Docker и GitHub; платные только Full 1099 и VIP 2199.
   Восемь дней событие стояло в очереди как «дорогое». Перед `skip` по деньгам — весь список билетов.

3. **Количество билетов на luma ставится степпером, а не полем.** Внутри `.ticket-type-btn` лежат две
   `.count-button`: `[0]` минус, `[1]` плюс. `.click()` работает, но счётчик перечитывается **отдельным
   вызовом** — в том же React ещё не обновился (подтверждает п.3 грабель 21.09).

4. **Полоса `dm-tg` требует, чтобы человек нам ОТВЕЧАЛ.** `tg_handles()` до 23.09 брала все 63 356 хэндлов
   из `contacts`, игнорируя соседние колонки `from_them` / `has_conversation` той же таблицы — отсюда повод
   «уже есть живая переписка» у людей, которым мы писали в одну сторону. Фильтр `from_them > 0` (осталось
   21 774), сторож `_test_cv_tg_handles_live.py`. Пустая полоса `dm-tg` после этого — честный ноль, не поломка.

5. **`apply_profile.json` больше НЕ содержит слова «Founder» про Антона** (23.09): `title` и `position` = `CTO`,
   `role_bucket` = `Engineer`, `seniority` = `C-level / Executive`. Канон `never-call-anton-a-founder`
   (anton 14.09, голосом) + цифра DR26-09-14-ZB-11 (−43% откликов). ⛔ Не возвращать «Founder & CEO»;
   анкета, которая требует именно статуса фаундера (stage / ARR / raising / founder-комьюнити), закрывается
   честным `skip` «не квалифицируемся», а не подгонкой ответов.

## Шаг 2 — голос и раскрытие

Пишу я → первой строкой раскрытие «привет, это Майкрофт, синтетический кофаундер Антона»
(§3.3), кроме тира A по карв-ауту 23.08 и кроме ТРУДОУСТРОЙСТВА (письмо рекрутёру/хайринг-менеджеру по вакансии Антона — без Майкрофта, от первого лица, [[job-search-no-mycroft-disclosure]], anton 14.09). Без проверки Антона — цель ≤5 слов, потолок 7.
Текст качественный → Fable 5. Голос лаборатории: строчными, коротко, без ваты и подписи.

## Шаг 3 — отметить, иначе работа не сделана

```
python [путь владельца] mark <id> --outcome sent --note "..."
```
`outcome`: `sent` · `replied` · `skip` (с причиной) · `failed`. Без отметки строка вернётся
в завтрашнюю порцию, а сторож будет считать полосу непроработанной.

## Шаг 4 — доложить

```
python [путь владельца] status
```
В отчёт Антону: сколько касаний ушло, по каким полосам, что горит, что упёрлось в Tier-2.
Ответ человека → карточка в CRM обновляется, и повод уезжает в контент-воронку
(`content_miner.py capture`) — всё, что мы делаем, становится контентом.

## Границы

- ⛔ **Деньги — Tier-2.** Платный билет: не покупаем, спрашиваем Антона.
- ⛔ **Обещание ДНЯ Антона — тоже не наш класс** (замер 10.09.2026). `agree-check` вида
  «I confirm that I can participate in the FULL [человек] on <дата> in <город>» — это обязательство
  его личного времени перед третьей стороной, а не условие регистрации. Пустой календарь
  доказывает только отсутствие записи, не согласие. Порядок: заявку собрать ЦЕЛИКОМ, галочку не
  ставить, `approval.py ask` Антону, строку пометить `skip` с номером аска. Обычные согласия
  (передача контактов организаторам, privacy notice спонсора = условие самой регистрации) ставим
  сами — политика в `apply_profile.json → policy`.
- ⚠️ **Аск-рельса может стоять на капе** (замер 20.09.2026: `approval.py` отбил вопрос — 6 открытых
  при капе 5, часть висит с 11.09). Тогда «спросить Антона» не работает, и безлюдный прогон НЕ
  встаёт: решаешь сам как кофаундер (§4.1-тер), называешь решение и причину в отметке строки И в
  докладе в 03, чтобы Антон отменил одной строкой. Класс E (деньги · необратимое · секреты ·
  безопасность) — повторить аск с `--critical`, а не решать самому.
- ⛔ **Не выдумывать повод.** Нет провенанса в карточке — не пишем, а сперва добираем факт.
- ⛔ **Потолки суток** (`CAPS` в `cv_outreach.py`): apply 6 · dm-tg 3 · x-touch 3, всего 8.
  Потолок защищает не от лени, а от спама: одно точное касание в правильную дверь.
- ✅ Оффлайн в Bay Area регистрируем свободно — Антон там с сентября.

## Соседи

`cv_outreach.py` (очередь) · `cv_outreach_daily.py` (ночная подготовка) · `cv_deadlines.py`
(сторож дверей) · `cv_mine.py` (добыча) · `/luma-apply` (одна заявка) · `/triage` (входящие).
Канон: `cv-events-lane`, `concept-luma-events`, `reglament-lid-v-crm-nesyot-ves-kontekst-znakomstva`.

## ⭐ Чёрный юмор обязателен (anton 10.09.2026, голосом)

Любой текст, который этот скилл отправляет ЖИВОМУ человеку наружу, несёт чёрную самоиронию — ровный служебный тон = дефект, объяснять надо не шутку, а её отсутствие. Строку берёшь через `/mycroft-joke` (полка (д) банка + строки 56-62 под холодное касание), приёмка — `/taste-check` P36. ⛔ Не шутим ровно в трёх зонах, и они не про вкус: строго-научная публикация (arXiv/журнал/JOSS) · юр.обязательство и анкета · красный список банка (чужая иконография угнетённых, псевдо-слуры, отрицание что я ИИ, юмор поверх диагноза/денег/беды собеседника). Одна шутка на тред. Канон: CLAUDE.md §3.3 §Поправка 10.09 + [[dark-humor-default-everywhere-external]].
