2026-04-29
X Research session 2026-04-29 — фиксация двух daily-loop'ов (own original posts + mafia engagement) с DoD, smoke coverage и tomorrow-scheduler'ом. Marvin supervisor + Claude Code executor, ноль live X writes.
- Цели сужены и зафиксированы: X Research оптимизируется на два ежедневных исхода — own original posts (собственные посты на X) и mafia engagement (ответы и взаимодействия с Launch Posting Mafia). LinkedIn и broader expansion — explicitly out of scope, потому что без проверяемой надёжности на двух базовых loop'ах остальное только размножает риск. Script-first архитектура стала операционной моделью: каждое опасное действие — детерминированный .mjs/.js с typed blocker'ами, ledger preflight skip rows и smoke coverage, не свободный prompt.
- Original-post lifecycle закрыт по DoD: validator + queue-manager + publish-scheduled-original + regenerate. return-to-review корректно unschedule'ит и пересчитывает даты остальных unpinned items без дубликатов; edit scheduled остаётся в том же canonical record. Live publish заблокирован typed blocker'ом real_executor_not_wired — promotion это отдельный operator-approved diff.
- Mafia engagement loop end-to-end: select → review packet → approve → dry-run → live, с armed sentinel + fresh approval ≤24h + plan-covering prior dry-run + daily caps. validatePlan в execute-x-actions.js требует approved_by даже в dry-run; smoke'ы покрывают и success path, и missing-approved_by refusal. Никакого fake approval не записано, никакого live engage не выполнено.
- Daily-run reliability: две campaigns по 10 counted runs каждая (Launch 8: 554–649 ms, mean 573; Launch 9: 545–618 ms, mean 559). All 20 runs ok, тот же step-set, та же skip pattern, без флейков. Per-run isolation теперь mechanically enforced: production canonical-ledger + daily report + mafia plan SHA bit-identical pre/post.
- Tomorrow scheduler armed: новый launchd job com.seva.xresearch-scoped-cycle (12:00 PT) после 11:30 PT pipeline запускает run-daily-cycle.mjs + recovery-report + daily-checklist в isolated режиме без --with-fetch. Старый broad cron (run-task.py + freeform daily-x-research-prompt) оставлен disabled. Сегодняшний pipeline сознательно skipped через data/operator-pipeline-skips.json.
- Verification: 28/28 smoke suites green, verify-handoff cold-start gate green, ledger consistency PASSED, status-check + daily-checklist различают operator_skipped vs missing/stale. 5 real bugs found and fixed (claude --prompt flag, spawnSync import, null-coalesce default, queue-manager dup-id across cancelled, smoke recursion fork-bomb). Live X writes сегодня: 0. Live reads ограничены read-only API probes (users/me, list timeline через fetch-mafia-posts.mjs) — никаких mutations.
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 — это сознательная граница, а не пробел.
verify-handoff cold-start gate проходит preflight + all_smokes + status_check + ledger_consistency + run_state_latest + no_api_call_invariant — все green.
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.
claude --prompt flag, spawnSync import, null-coalesce default, queue-manager dup-id across cancelled, smoke recursion fork-bomb.
Все ledger writes — dry_run / preflight skip / stub. Live reads ограничены read-only API probes (users/me, list timeline) — никаких mutations.
Что мы строим. 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
- 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 заблокировано
- 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 заблокировано
- 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 — что сработает само и какие артефакты докажут успех
- 11:30 PT — существующий daily pipeline отрабатывает и produce'ит daily-signals-2026-04-30.json (это уже работающая часть, не новая).
- 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 джобов.
- Артефакты, которые докажут успех: 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.
- Operator sequence утром: verify-handoff → status-check → daily-checklist. Если всё green — продолжить по TL;DR final handoff'а. Если красный — recovery-report покажет конкретный typed blocker, не общую ошибку.
- 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.
- 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'у упадёт.
- Если завтрашний 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.