Skip to content

feat(promote): add ce-promote skill for post-ship announcement copy#888

Open
imwm wants to merge 1 commit into
mainfrom
nervous-gould-7bce37
Open

feat(promote): add ce-promote skill for post-ship announcement copy#888
imwm wants to merge 1 commit into
mainfrom
nervous-gould-7bce37

Conversation

@imwm
Copy link
Copy Markdown
Collaborator

@imwm imwm commented Jun 1, 2026

What & why

After a feature ships, the user-facing messaging — a tweet/thread, a changelog blurb, a LinkedIn post, an email — is usually written later, by someone without the shipping context. ce-promote pulls that drafting into the engineering workflow: it figures out what shipped (from a description, or derived from the merged PR / diff / changelog / commits), picks sensible channels, and produces copy-pasteable drafts. It drafts only — never posts, publishes, or touches git.

Design notes

  • Lightweight footprint. Two product files (SKILL.md + one reference) plus two README rows; no new dependencies.
  • Spiral is an optional enhancement, not a dependency. With the Spiral CLI installed and authed, drafts are voice-matched and humanized. Without it, ce-promote ships a lite layer of editorial & social-media expertise to write strong copy on its own — modest by design (brand-voice matching, humanization, saved styles, and campaign orchestration are where the Spiral path goes further).

Spiral integration details

  • Three-state detection (ready / installed-unauthed / absent). Ready → voice-matched via spiral write … --instant --json.
  • Agent-driven sign-in, no key in chat: when Spiral is installed but unauthed, the agent runs spiral login --json (non-blocking), shares the returned auth_url, the user approves in a browser, and the agent polls spiral auth status --json until authenticated: true. The API key is exchanged server→CLI and never touches the agent's transcript or logs. Returning users (already_authenticated) skip straight through. Requires @every-env/spiral-cli ≥ 1.8.0; older CLIs degrade gracefully (suggest update, or the user signs in themselves).
  • First-run nudge, never naggy: the setup offer is shown once; a single dismissal records a per-repo opt-out so this per-ship skill never re-prompts.
  • Encodes Spiral's multi-channel / cue-word behavior: campaign phrasing returns one set of drafts per channel and ignores --num-drafts; single-channel variations need --num-drafts and must avoid cue words. Verified live.

Testing

  • Validated live against the real Spiral CLI: single-channel variations and multi-channel campaign both behave as documented.
  • Simulated the unauthed / absent / opted-out states; confirmed the nudge fires once and the opt-out suppresses it on later runs.
  • bun test (frontmatter + shell-safety) green; bun run release:validate in sync (39 skills).

Open for review (draft)

  • Per-repo opt-out lives in the per-worktree gitignored config, so a new worktree could re-show the offer once. Acceptable, or should it be user-global?
  • The agent sign-in path depends on @every-env/spiral-cli ≥ 1.8.0 (agent-aware spiral login, shipping in EveryInc/spiral-next#1182). The skill degrades gracefully on older CLIs.
  • Comfort check on naming the Spiral CLI / @every-env/spiral-cli package in an OSS plugin.

@imwm imwm force-pushed the nervous-gould-7bce37 branch from 991c8bb to 55b896c Compare June 1, 2026 04:56
Copy link
Copy Markdown
Collaborator

@tmchow tmchow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the skill end-to-end — really clean work. The graceful-degradation (three-state detect, never-block-on-Spiral) and the drafts-only safety stance are the strong parts, and Path B is substantive rather than a degraded teaser. Two small change requests on the opt-out config write before merge (inline). Everything else is polish.


### Record the opt-out (best-effort)

Resolve the repo root, then add `ce_promote_spiral_optout: true` as a top-level key to `<root>/.compound-engineering/config.local.yaml`, using the native file-write/edit tool — create the file (and its `.compound-engineering/` directory) if absent, or append the key if the file already exists without it. If the root can't be resolved or the write fails, proceed to Path B anyway; the opt-out is a convenience, never a blocker.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change request — gitignore hygiene. This creates .compound-engineering/config.local.yaml if absent, but doesn't ensure the file is gitignored. ce-setup — the canonical creator of this file — explicitly checks and offers to add the .gitignore entry when it creates it (ce-setup/SKILL.md:98,104). A user who runs /ce-promote before /ce-setup ends up with an un-ignored config file holding machine-local opt-out state that can get committed by accident.

Suggest mirroring ce-setup here: when creating the file, verify/offer the .gitignore entry — or only append the key when the file already exists, leaving first-time creation (with gitignore handling) to ce-setup.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch, updated: when the opt-out write has to create the config, it ensures .compound-engineering/*.local.yaml is gitignored and then tells the user so. if the file exists it just appends the key. did mirroring rather than append-only to avoid silent failure if the config doesn't exist yet. and if it can't resolve or the write fails it just goes ahead to draft using the lite guidance in the plugin.

cat "$(git rev-parse --show-toplevel 2>/dev/null)/.compound-engineering/config.local.yaml" 2>/dev/null || echo '__NO_CONFIG__'
```

If the contents include `ce_promote_spiral_optout: true`, **skip Path 0** and go straight to Path B. Otherwise, offer setup.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change request — document the new config key. ce_promote_spiral_optout is a new top-level key in .compound-engineering/config.local.yaml, but it isn't in ce-setup/references/config-template.yaml — the self-documenting schema ce-setup seeds new configs from. Add it there (commented) so the config surface stays documented and discoverable.

Note: that's a cross-skill file outside this PR's current diff, so it'll need to be added to the changeset.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup – added a commented ce_promote_spiral_optout entry under a new # --- ce-promote --- section in ce-setup/references/config-template.yaml

@imwm imwm force-pushed the nervous-gould-7bce37 branch from 55b896c to f984658 Compare June 1, 2026 20:04
@imwm imwm marked this pull request as ready for review June 1, 2026 22:34
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f984658cb4

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

API key required. Usage: spiral auth login --token <spiral_sk_...>
Create a key at: https://app.writewithspiral.com/settings/api-keys
```
Surface that link to the user. They open it, create a key, and either paste the `spiral_sk_...` key back so the agent runs `spiral auth login --token spiral_sk_...`, or run that command themselves. Then re-run `spiral auth status`; if a `spiral_sk_...` key now appears, proceed with Path A, else fall to Path B. (In v1.6.1 `spiral login` is the create-a-key link flow, not a one-click browser approve.)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid asking users to paste API keys into chat

When Spiral is installed but unauthenticated, this flow tells the user they can paste a spiral_sk_... API key back so the agent runs the login command. In that scenario the credential is exposed to the model transcript, tool logs, and any session-history tooling, even though the same paragraph already supports the safer path of having the user run spiral auth login --token ... locally. Please keep the key out of chat and instruct the user to run the command themselves.

Useful? React with 👍 / 👎.

@imwm imwm force-pushed the nervous-gould-7bce37 branch from f984658 to 786dc9e Compare June 1, 2026 22:41
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 786dc9eeeb

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Resolve the repo root, then add `ce_promote_spiral_optout: true` as a top-level key to `<root>/.compound-engineering/config.local.yaml`, using the native file-write/edit tool:

- **File already exists:** append the key if it isn't already present.
- **File absent:** create it (and its `.compound-engineering/` directory) with the key, AND ensure the machine-local config is gitignored — mirroring `ce-setup`, the canonical creator of this file. Check whether the path is already ignored (`git check-ignore -q .compound-engineering/config.local.yaml`); if it isn't, append `.compound-engineering/*.local.yaml` to the repo-root `.gitignore`. Without this, a user who runs `/ce-promote` before `/ce-setup` ends up with an un-ignored config holding machine-local opt-out state that can get committed by accident.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid dirtying the user's repo on a draft-only decline

When a user declines Spiral setup in a repo that has not run /ce-setup, this instruction automatically appends .compound-engineering/*.local.yaml to the repo-root .gitignore. That leaves an unstaged/tracked-file change even though /ce-promote is explicitly positioned as drafts-only and the user only chose to draft without Spiral; using an already-ignored location such as .git/info/exclude, or asking before editing .gitignore, would avoid surprising post-ship working tree churn.

Useful? React with 👍 / 👎.

@imwm imwm force-pushed the nervous-gould-7bce37 branch from 786dc9e to cf31ef9 Compare June 3, 2026 01:18
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cf31ef9a8b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

cat "$(git rev-parse --show-toplevel 2>/dev/null)/.compound-engineering/config.local.yaml" 2>/dev/null || echo '__NO_CONFIG__'
```

If the contents include `ce_promote_spiral_optout: true`, **skip Path 0** and go straight to Path B. Otherwise, offer setup.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Parse the opt-out key instead of substring-matching comments

This substring check treats the commented template entry as a real opt-out: /ce-setup copies references/config-template.yaml into .compound-engineering/config.local.yaml with # ce_promote_spiral_optout: true, so any project that accepted the default setup template will skip Path 0 even though the user never declined Spiral. Please parse the YAML/top-level key or ignore commented lines before deciding to suppress the setup offer.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch :) opt-out check now required uncommented ce_promote_spiral_output: true so the example no longer reads as an opt-out

@imwm imwm force-pushed the nervous-gould-7bce37 branch from cf31ef9 to aa6e9b6 Compare June 3, 2026 01:46
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: aa6e9b60e4

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".


Resolve the repo root, then add `ce_promote_spiral_optout: true` as a top-level key to `<root>/.compound-engineering/config.local.yaml`, using the native file-write/edit tool:

- **File already exists:** append the key if it isn't already present.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Append an active opt-out despite template comments

When this file already exists because ce-setup copied references/config-template.yaml, it contains the commented example # ce_promote_spiral_optout: true; this instruction only says to append the key “if it isn't already present,” so the agent can treat the commented template line as present and skip writing an uncommented opt-out. Fresh evidence beyond the earlier opt-out parsing issue is the write path here: the read path now ignores comments, but the record path can leave only the commented line, causing users who explicitly choose “Draft directly without Spiral” to be prompted again on the next run.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed, write path ensures an uncommented ce_promote_spiral_output: true is there, mirroring the above fix

@imwm imwm force-pushed the nervous-gould-7bce37 branch from aa6e9b6 to 5d2c654 Compare June 3, 2026 01:50
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5d2c654057

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

- **Absent** → guide the user to install + connect in one step via the pairing-code command from Settings → Connect an Agent.
- **Decline** → record the opt-out (best-effort) and go to Path B.

Skip Path 0 entirely — straight to Path B — when the opt-out is already recorded, when running headless, or when no blocking-question tool is available.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fall back to text prompts instead of skipping setup

In runtimes without a blocking question tool (for example Codex edit modes, where request_user_input may be unavailable), this tells the skill to skip Path 0 entirely, so the first-run Spiral setup offer is never shown and users go straight to non-personalized drafting. That conflicts with the plugin interaction guidance in plugins/compound-engineering/AGENTS.md, which requires falling back to numbered options in chat and waiting for a reply rather than silently skipping the question; it also contradicts the new reference file's own fallback instructions.

Useful? React with 👍 / 👎.

Generate user-facing announcement copy (X post/thread, changelog blurb,
LinkedIn, email, blog, demo script) for a feature that just shipped,
right inside the engineering workflow. Spiral-agnostic by default;
voice-matched via the optional Spiral CLI when installed and authed.

- Derives what shipped from a description or from the merged PR / diff /
  changelog / commits, and leads with user value over implementation.
- Three-state Spiral detection (ready / unauthed / absent) with a
  one-time, declinable first-run setup nudge; a single dismissal records
  a per-repo opt-out so this per-ship skill never nags.
- Encodes Spiral's multi-channel / cue-word behavior (verified live
  against CLI v1.6.1) and degrades gracefully to direct drafting when
  Spiral is absent, without giving away Spiral's voice-matching.
- Drafts only: never posts, publishes, or touches git.
@imwm imwm force-pushed the nervous-gould-7bce37 branch from 5d2c654 to b61cb89 Compare June 3, 2026 01:54
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b61cb89813

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

spiral auth status 2>/dev/null
```

Classify into one of three states. Spiral is **ready** only if the binary exists AND auth status shows an authed key (`spiral_sk_...`):
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Detect authenticated Spiral from JSON status

For already-authenticated Spiral 1.8 users, the published agent flow reports readiness via spiral auth status --json returning authenticated: true / status: authenticated, while this check only treats output containing spiral_sk_... as ready. If the status command does not print a raw token, ready users are misclassified as unauthed and get the setup/opt-out prompt instead of Path A; use the JSON authenticated flag (or spiral login --json's already_authenticated) for readiness.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants