feat(x-engine): smart spotlight cadence — daily when there's news, quiet when there isn't (#374)

CEO verdict on the blind 3-day timer: 'It should default to 1 day and
be more like... smart.' Now: interval defaults to 1 day; the cycle
skips (with logged reasons) while a spotlight draft is still awaiting
the CEO, and stretches to 3x the interval when nothing has shipped
(CHANGELOG sections via the read clone) since the last spotlight
activity — where activity is a materialized draft's seen_at or a
completed exploration's updated_at, deliberately excluding the stale-
cycle janitor's cancels. The HoM gains an explicit skip exit
(propose_feature_spotlight skip=true + reason: completes the
exploration, no draft, no seen-slug, still counts as activity), and
its spawn prompt now carries the seen ledger WITH dates, what shipped
since the last spotlight, and recently rejected drafts with the CEO's
reasons — fresh-but-unspotlighted first. Fail-open on changelog read
errors so a signal outage never starves the engine.

Co-authored-by: Renn F <rennf93@users.noreply.github.com>
This commit is contained in:
Renzo F
2026-07-09 20:59:53 +02:00
committed by GitHub
co-authored by Renn F
parent 3cb32e3c5f
commit 0450ec9e89
15 changed files with 957 additions and 39 deletions
+24 -6
View File
@@ -586,27 +586,43 @@ def propose_roadmap(cycle_goal: str, items: list[dict[str, Any]]) -> dict[str, A
def propose_feature_spotlight(
feature_slug: str,
feature_title: str,
body: str,
feature_slug: str = "",
feature_title: str = "",
body: str = "",
wants_video: bool = False,
video_script: str = "",
skip: bool = False,
skip_reason: str = "",
) -> dict[str, Any]:
"""Head of Marketing: draft ONE feature-spotlight marketing post.
"""Head of Marketing: draft ONE feature-spotlight marketing post, or skip.
Call this exactly ONCE per exploration cycle, after investigating the
CHANGELOG, feature-flags ledger, docs/map, charter, and KB to pick a real,
under-publicized capability. The draft is held in the X post queue for the
CEO to edit/approve — nothing auto-posts.
If nothing shipped is genuinely worth spotlighting this cycle, pass
skip=True with a substantive skip_reason instead of forcing a weak post —
a forced spotlight is worse than skipping. A skip still completes the
exploration task (no draft materialized, no feature marked seen) and
counts as this cycle's activity for the engine's cadence, so it won't just
re-fire daily into the same quiet period.
Args:
feature_slug: Stable slug identifying the feature (the dedup key).
feature_title: Short human title of the feature.
body: The tweet text (plain, <=280 chars, no invented facts).
Ignored when skip=True.
feature_title: Short human title of the feature. Ignored when
skip=True.
body: The tweet text (plain, <=280 chars, no invented facts). Ignored
when skip=True.
wants_video: Also request a companion video (held separately for CEO
approval, when the video engine is armed for spotlights).
video_script: Optional script for that video; falls back to the
feature title/body when omitted.
skip: True to declare "nothing worth spotlighting this cycle" instead
of authoring a draft.
skip_reason: Required (non-empty, >=8 chars) explanation when
skip=True.
"""
return _post(
"/api/v1/do/propose_feature_spotlight",
@@ -616,6 +632,8 @@ def propose_feature_spotlight(
"body": body,
"wants_video": wants_video,
"video_script": video_script,
"skip": skip,
"skip_reason": skip_reason,
},
)