← Compound EngineeringCONTENT HISTORYWHAT CHANGED · RULE-BASED ANALYSIS
Update to Compound Engineering
Snapshot Sep 30, 2026 · 23:16 UTC · version 3.24.0
Collection source: not recorded for this historical snapshot.
First saved snapshot
No earlier snapshot is available to establish a change.
Compare saved observations
Download comparison JSONFull technical diff · 0 changed fields
Full snapshot data
{
"description": "Draft launch or promotion copy for a shipped feature.",
"included_files": [
{
"relative_path": "references/spiral-cli.md",
"size_in_bytes": 13036
}
],
"name": "ce-promote",
"skill_md_contents": "---\nname: ce-promote\ndescription: \"Draft launch or promotion copy for a shipped feature.\"\ndisable-model-invocation: true\nargument-hint: \"[optional: what shipped and/or channels, e.g. 'a tweet thread and a LinkedIn post']\"\n---\n\n# Promotion Copy\n\nTurn a feature that just shipped into copy-pasteable, user-facing announcement copy, right inside the engineering workflow — so the messaging doesn't wait for a separate marketing pass.\n\n**Done when:** every drafted channel is presented as a labeled, copy-pasteable block and the user has been offered a revision. **This skill drafts only — it never posts, publishes, schedules, commits, or opens PRs.** Posting is a human action.\n\nIt is **spiral-agnostic**: with nothing installed it drafts directly from the editorial and social fundamentals in Path B. When the Spiral CLI is present and authed, drafts come back voice-matched to the user's brand — an enhancement, never a requirement.\n\n## Phase 1 — Figure out what shipped\n\nA free-form description in the arguments is the source of truth. Otherwise derive it from context, using what's available and blocking on no single source:\n\n- **Merged/active PR** — `gh pr view --json title,body,url` (the title and body usually state the user-facing value)\n- **The diff** — `git diff main...HEAD --stat`, skimming notable changes so the claim is grounded in what actually changed\n- **Changelog** — the top or `[Unreleased]` entry in `docs/changelog.md`, `CHANGELOG.md`, or similar\n- **Recent commits** — `git log --oneline -15` for the arc of the change\n\nThen write a 1-3 sentence summary of the **user-facing value**: what a user can now do that they couldn't before, and why they'd care. Outcome, not implementation — \"You can now export any report to CSV in one click\", not \"Added a CsvSerializer and an export endpoint.\" If you can't confidently tell what shipped, ask one short question rather than guessing.\n\n## Phase 2 — Pick channels\n\nDefault to an X post (or short thread) plus a one-line changelog / release blurb. If the user named channels — LinkedIn, email, a blog intro, a demo script — draft those instead of or in addition to the defaults. Scale to the change: a small fix warrants one or two short drafts, a flagship feature a cross-channel set. Don't force a fixed template.\n\n## Phase 3 — Draft the copy\n\nDetect Spiral's state with two quick, non-blocking commands:\n\n```bash\nwhich spiral\nspiral auth status --json 2>/dev/null\n```\n\n- No binary -> **Absent**\n- `\"authenticated\": true` -> **Ready**\n- `\"authenticated\": false` -> **Unauthed**\n- Output isn't JSON (older CLI that ignores `--json`) -> ready iff it contains `spiral_sk_`, else unauthed\n\n**Ready** -> Path A. **Absent or Unauthed** -> Path 0, then Path A if setup completes, else Path B. Never let a Spiral failure, timeout, or odd output block or slow the skill — when in doubt, treat it as not-ready and continue.\n\n### Path 0 — Offer Spiral setup (once, declinable)\n\nGo straight to Path B when running non-interactively — there is no human to answer. Otherwise offer setup **once**: read `references/spiral-cli.md` and follow its Path 0 section for the opt-out check, the blocking question, the agent-run `spiral login --json` flow (the API key never passes through the agent, and the user never pastes one into chat), the install path, and how the opt-out is recorded. Skip to Path B only when *that* check finds a recorded opt-out — it is the authority on what counts as recorded, and a naive config scan misreads `ce-setup`'s commented template example as one, silently suppressing the offer.\n\nTwo properties that section depends on: **any dismissal records the opt-out**, so a single first-run decline stops the offer for good in this repo, and a decline always proceeds to Path B rather than blocking. If a human is present but no blocking-question tool is in the current tool list, fall back to a numbered list of the two options in chat and wait — do not skip the offer, and never call a user-facing question tool to discover whether one exists.\n\n### Path A — Spiral ready (voice-matched)\n\n**Read `references/spiral-cli.md` before composing the prompt.** Whether Spiral returns a multi-channel set or several variations of one channel is phrasing-driven (channel keywords and cue words vs. `--num-drafts`), and getting it wrong silently returns the wrong number or shape of drafts — don't restate those rules from memory.\n\nAlways pass `--instant` and `--json`; parse `drafts[]` (each carries its own `channel`) plus `session_id`. **Present every returned draft, grouped by `channel`** — Spiral decides how many drafts per channel, so never assume one-per-channel or drop extras. If the `spiral write` call errors or returns no usable drafts, fall back silently to Path B for the affected channels.\n\n### Path B — Direct drafting\n\nNo Spiral needed. Draft every channel through the `ce-noslop` skill. (The Spiral path goes further: brand-voice matching, humanization, saved styles, and cross-channel campaign orchestration.)\n\n**Every channel:**\n\n- Lead with the user-facing outcome — what someone can now do, not how it was built.\n- One idea per piece.\n\n**Distributed channels:** the first line is the hook and has to earn the next line (feeds truncate) — no preamble. Match each channel's native shape and length; never reuse one draft verbatim across channels. One clear CTA where the channel supports it. Hashtags 0-2, and only where the channel expects them.\n\n**Per channel:**\n\n- **X** — value in the first line; ~1-3 tight lines. Thread only when there's more than one beat worth its own line.\n- **Changelog / release blurb** — one declarative line naming the new capability. Plain, not promotional.\n- **LinkedIn** — a short paragraph: human angle (why it matters), then the what. Warmer than X.\n- **Email** — benefit-stating subject + 2-4 sentence body + one CTA.\n- **Blog intro** — one opening paragraph framing the problem and the new capability; leave the deep-dive to the author.\n- **Demo script** — 3-6 spoken beats: hook, problem, action, payoff.\n\nOne strong draft per channel by default; produce more only when asked (\"3 tweet options\"), capped at ~3.\n\n## Phase 4 — Present the drafts\n\nShow every draft as a clean, copy-pasteable block labeled by channel:\n\n```\n### X post\n<the copy>\n```\n\nWhen Path A produced them, also surface the `session_id` and each draft's `url` so the user can open and tweak them in the Spiral web app. Offer to revise (tone, length, angle, more variations, another channel). **Do not post, publish, schedule, commit, or open a PR** — end by reminding the user the drafts are theirs to ship.\n"
}SHA-256 of public snapshot: 9ef1c15d466cdaddb8fd2c71f24ba306e14991a2a3d0b7a8b545f744a3b94a40