◈ X-Research
← Latest Updates
Key developments
Inbox → Goals Pipeline → Operating Principles → Action Catalog → Autonomous Work →

X Research — два замкнутых daily-loop'а: own original posts и mafia engagement (2026-04-29)

День, в который X Research перестал быть «много скриптов» и стал двумя замкнутыми daily-loop'ами — original posts и mafia engagement — с DoD, smoke coverage, двумя 10-run reliability campaigns, операторскими гейтами и launchd-расписанием на завтра. Live writes: 0 — это сознательная граница, а не пробел.

Goal: own original posts + mafia engagement LinkedIn / broad expansion: out of scope 28/28 smoke suites green 20/20 reliability runs ok (Launch 8 + 9) 0 live X writes Real publish: gated (operator diff) Mafia live engage: gated (approve + dry-run + armed)
28/28
smoke suites green

verify-handoff cold-start gate проходит preflight + all_smokes + status_check + ledger_consistency + run_state_latest + no_api_call_invariant — все green.

20
counted reliability runs

Launch 8: 10/10 ok, 554–649 ms, mean 573. Launch 9: 10/10 ok, 545–618 ms, mean 559. Production canonical-ledger / daily report / mafia plan SHA bit-identical pre/post.

5
real bugs found and fixed

claude --prompt flag, spawnSync import, null-coalesce default, queue-manager dup-id across cancelled, smoke recursion fork-bomb.

0
live X writes

Все ledger writes — dry_run / preflight skip / stub. Live reads ограничены read-only API probes (users/me, list timeline) — никаких mutations.

Цели проекта и operating model

Что мы строим. X Research — это автоматизация двух ежедневных исходов для Seva: (1) own original posts — собственные качественные посты на X, (2) mafia engagement — вдумчивые ответы и взаимодействия с Launch Posting Mafia. Всё остальное — LinkedIn, броадер outreach, freeform research-prompts — вынесено за scope этой итерации, потому что без проверяемой надёжности на двух базовых loop'ах остальное только размножает риск. Operating model. Каждое опасное действие (publish, live engage, list mutation) проходит через детерминированный .mjs/.js с typed blocker'ами, ledger preflight skip rows и smoke coverage — не через свободный prompt. Marvin держит supervisor-контракт (полная intention chain в session prompt, durable state в data/run-state/, PROGRESS.md, OVERNIGHT-*-FINAL-HANDOFF.md), Claude Code — executor. Seva autonomy economics зафиксирована: оптимизируем Seva time и empirical reliability, не token cost.

Before → After

До этой сессии X Research выглядел как «много полезных скриптов», и было неясно, что именно отрабатывает каждый день и где границы. После сессии — это два узко-сфокусированных daily-loop'а с проверяемым DoD, операторскими гейтами и launchd-расписанием на завтра.
  • Goals — Before: широкий freeform research-prompt, LinkedIn-expansion в roadmap, неясная приоритизация. After: фокус сужен до own original posts + mafia engagement; LinkedIn явно out of scope; всё остальное — gated promotion contracts.
  • Architecture — Before: prompt-driven шаги, dangerous действия зависели от модели. After: script-first — каждый dangerous step это .mjs/.js с typed blocker'ами и smoke coverage; prompts остаются только для voice-bearing полей.
  • Originals lifecycle — Before: validator/queue/publish существовали отдельно, edge-cases не доказаны. After: closed loop — validator + queue-manager + publish-scheduled-original + regenerate, c DoD #4 (return-to-review корректно пересчитывает даты unpinned items) и DoD #5 (edit scheduled остаётся в том же canonical record), оба anchored smoke'ами.
  • Mafia engagement — Before: select/dry-run/live существовали, но не были связаны единым approval-aware flow. After: end-to-end loop select → review packet → approve → dry-run → live, с armed sentinel + fresh approval ≤24h + plan-covering prior dry-run + daily caps; каждый — hard exit on miss.
  • Reliability — Before: «один зелёный запуск», без empirical evidence о флейкости. After: две 10-run campaigns (Launch 8 + Launch 9 = 20/20 ok, без флейков), production артефакты SHA bit-identical pre/post, mechanically asserted в campaign harness и его smoke.
  • Tomorrow — Before: непонятно, что и когда сработает само. After: launchd com.seva.xresearch-scoped-cycle (12:00 PT) после 11:30 PT pipeline; старый broad cron (run-task.py + freeform daily-x-research-prompt) оставлен disabled; никакого параллельного broad-prompt джоба.

Что проверено vs что осталось intentionally заблокировано

Доказано без live writes
  • Proven — Reliability: 28/28 smoke suites green; verify-handoff cold-start gate green (preflight + all_smokes + status_check + ledger_consistency + run_state_latest + no_api_call_invariant). 20 counted reliability runs ok (Launch 8 + 9). 9 rehearsal iterations через reliability rehearsal looper со стабильным typed-blocker enum.
  • Proven — Script-first: каждый dangerous step имеет typed blocker и smoke coverage. publish-scheduled-original.mjs --executor=real падает с blocker_type=real_executor_not_wired; mafia-engage.mjs --live требует armed + approval ≤24h + dry-run + caps; все blockers — hard exit on miss.
  • Proven — Safety invariants: production canonical-ledger SHA-256 идентичен до и после rehearse-daily-cycle, обоих 10-run campaigns, всех smoke runs, rehearsal looper'а. no_api_call invariant audit (smoke audit-no-api-call cases 4b/4c) ловит explicit no_api_call:false. Operator-skip semantics date-bound; smoke covers 5 кейсов.
  • Proven — Scheduler: launchd com.seva.xresearch-scoped-cycle (12:00 PT) → daily-xresearch-scoped-cycle.sh → run-daily-cycle.mjs --json + recovery-report.mjs + daily-checklist.mjs. Smoke scripts/smoke-scheduled-daily-cycle.mjs (12/12 assertions). Старый broad cron disabled.
  • Gated — Real publish: live publish ждёт операторского diff'а, который заменит typed blocker реальным execute-inbox-approved.js → client.v2.tweet({text}) call'ом + recordOutcome ledger correlation. Smoke pin'ит exact payload text — drift к placeholder'у упадёт.
  • Gated — Mafia live engage: сегодняшний план mafia-2026-04-29 (6 actions) ждёт явного операторского approval. Никакого fake approval не записано. Operator sequence в TL;DR final handoff'а.
  • Gated — Optional live mafia fetch: завтрашний scheduled wrapper намеренно не передаёт --with-fetch; live X read только по операторскому решению. Это live read, не write — отдельная категория риска.
  • Why this is a feature, not a bug: zero live X writes сегодня — это контракт. Каждый gate либо hard-exit при нарушении, либо typed blocker, либо smoke-pinned invariant. Promotion = операторский diff, не autonomous decision.

Что конкретно сделано

Area Status Что появилось Почему важно
Originals: validator + queue-manager DoD validate-generated-original-posts.mjs (schema gate post-prompt с golden regression pack), queue-manager.mjs (schedule|unschedule|return-to-review|pin|unpin|reorder|recompute-positions|publish-dry-run, invariant validator после каждой мутации, dup-id check только среди active statuses). Originals lifecycle стал детерминированным: возврат в review восстанавливает даты остальных unpinned items без дубликатов, edit scheduled остаётся в том же canonical record.
Originals: publish-scheduled-original + regenerate DoD (live gated) publish-scheduled-original.mjs (--dry-run / --executor=stub / --executor=real с typed blocker и execute_tweet_plan exposure), regenerate-original-post.sh (single-item rerun из ACTION-CATALOG §B). Сегодняшний queued post (opq-20260428-001) уже на ledger как dry-run; live publish ждёт операторского diff'а, который заменит typed blocker реальным execute-inbox-approved.js → client.v2.tweet({text}) call'ом + recordOutcome ledger correlation.
Mafia: full daily loop DoD (live gated) mafia-select.mjs (scoring + plan emit), mafia-cycle.mjs (orchestrator), approve-mafia-plan.mjs, mafia-engage.mjs (dry-run / live с armed sentinel + fresh approval + prior dry-run + daily caps), mafia-auth-diagnostic. Сегодняшний план mafia-2026-04-29 (6 actions) ждёт явного операторского approval; review packet с marginal-pick callout приложен. Никакого fake approval не записано — только preflight skip rows на canonical ledger.
Reliability orchestration DoD run-daily-cycle.mjs (master, --report-out / --mafia-plan-out overrides), status-check.mjs (operator-skip + mafia freshness), recovery-report.mjs, snapshot-state.mjs, verify-handoff.mjs (cold-start gate + recursion guard), daily-checklist.mjs (one-screen morning view + plan-review/packet paths). Operator получает один зелёный/красный экран с reasons вместо собирания состояния по 8 файлам. verify-handoff обязателен любой следующей сессии; cold-start gate ловит drift до того, как сессия дойдёт до dangerous работ.
Daily-run reliability campaigns 20/20 ok daily-run-campaign.mjs + smoke-daily-run-campaign.mjs. Launch 8: 10/10 ok, 554–649 ms, mean 573. Launch 9: 10/10 ok, 545–618 ms, mean 559. + reliability-rehearsal-loop.mjs (9 rehearsal iterations). Reliability теперь empirical, не one-shot. Per-run --report-out / --mafia-plan-out изолируют production артефакты; SHA bit-identical pre/post — mechanically asserted в campaign harness и его smoke.
Tomorrow scheduler armed launchd com.seva.xresearch-scoped-cycle (Hour=12, Minute=0) → ~/.openclaw/scripts/daily-xresearch-scoped-cycle.sh. Smoke scripts/smoke-scheduled-daily-cycle.mjs (12/12 assertions). Завтра в 11:30 PT отрабатывает существующий pipeline и produce'ит daily-signals-2026-04-30.json; в 12:00 PT scoped flow consume'ит его и пишет data/run-reports/2026-04-30.json + mafia-plan.json. Старый broad cron disabled — никаких параллельных broad-prompt джобов.
Operator visibility done data/run-reports/2026-04-29-mafia-plan-review.md (review packet с marginal pick callout), 2026-04-29-operator-command-packet.md (готовые команды для verify / review / approve / dry-run / live / blocker / recovery), daily-checklist surfaces оба packet path'а. Operator не должен помнить последовательность команд из 5 doc'ов; daily-checklist сам показывает, что есть рядом и что заблокировано.
Recovery acknowledgments explicit data/recovery-acknowledgments.json — 11 исторических 403 / browser-API failure'ов acknowledged with reasons, matched by event_id only. Field-pattern matches были rejected как unsafe. Существующий шум не глушит будущие реальные failure'ы; новые event_id всё равно surface'ятся в recovery-report. Каждый ack — explicit decision, не silent mass-acknowledgment.
Mega-prompt v1.1 + golden regression done Mega-prompt v1.1 (post-run validator gate documented), golden regression pack для validator'а — pin'ит ожидаемые failure modes (thread overflow, schema drift, missing fields). Любая будущая правка validator'а или mega-prompt'а должна сохранить эти golden cases или сознательно их обновить — drift не пройдёт незамеченным.

Что осталось intentionally заблокировано

Reliability work не promote'ит ничего в live X. Все три остающихся gate'а — это операторские diff'ы или decisions, не autonomous tasks. Smoke'ы и typed blocker'ы охраняют границу.
  • Real publish executor: publish-scheduled-original.mjs --executor=real падает с typed blocker_type=real_executor_not_wired. Promotion = операторский diff, который заменит блок реальным execute-inbox-approved.js → client.v2.tweet({text}) call'ом, с recordOutcome ledger correlation. Smoke pin'ит exact payload text — drift к placeholder'у упадёт.
  • Mafia live engage: mafia-engage.mjs --live требует armed sentinel + approval ≤24h + plan-covering prior dry-run + daily caps. Сегодняшний план mafia-2026-04-29 не approved; никакого fake approval сделано не было. Operator sequence в TL;DR final handoff'а.
  • Optional live mafia fetch: Завтрашний scheduled wrapper намеренно не передаёт --with-fetch; live X read только по операторскому решению.
  • Editorial agent для voice-bearing полей: Out of scope этой hardening session, остаётся под L-6 promotion contract предыдущей итерации.

Завтрашняя operating model — что сработает само и какие артефакты докажут успех

  1. 11:30 PT — существующий daily pipeline отрабатывает и produce'ит daily-signals-2026-04-30.json (это уже работающая часть, не новая).
  2. 12:00 PT — launchd com.seva.xresearch-scoped-cycle поднимает scoped flow: run-daily-cycle.mjs --json + recovery-report.mjs + daily-checklist.mjs. Без --with-fetch, без live writes. Старый broad Gateway cron остаётся disabled — никаких параллельных broad-prompt джобов.
  3. Артефакты, которые докажут успех: data/run-reports/2026-04-30.json (scoped cycle ok), data/run-reports/2026-04-30-mafia-plan.json (selection без флейков), status-check.mjs flip'ает signals из not_yet_due в fresh для 2026-04-30, verify-handoff cold-start gate остаётся green.
  4. Operator sequence утром: verify-handoff → status-check → daily-checklist. Если всё green — продолжить по TL;DR final handoff'а. Если красный — recovery-report покажет конкретный typed blocker, не общую ошибку.
  5. Mafia live engage сегодня (опционально, операторское решение): прочитать review packet (2026-04-29-mafia-plan-review.md), решить approve all 3 / rerun selection с --max-posts=2 / edit plan JSON. Approve → dry-run → live с armed flag. Все четыре gate'а — hard exit.
  6. Real publish promotion (операторский diff, не autonomous task): заменить typed blocker реальным execute-inbox-approved.js → client.v2.tweet({text}) call'ом + recordOutcome ledger correlation. Smoke-пины payload-text уже на месте — drift к placeholder'у упадёт.
  7. Если завтрашний 12:00 PT scoped cycle пройдёт чисто — рассмотреть включение --with-fetch отдельным операторским decision'ом (это live X read, не write — отдельная категория).

Источники: docs/OVERNIGHT-2026-04-29-FINAL-HANDOFF.md, docs/INTEGRITY-REVIEW-2026-04-29-OVERNIGHT.md, docs/DAILY-OPERATOR-RUNBOOK.md, data/run-state/2026-04-29-overnight.json (10 launch summaries в одном файле). Phase 2 draft — после редакторской полировки, перед deploy.