Files
Joe Amditis 3e0e3a8dff Shorten skill and plugin descriptions, remove em-dashes (#277)
* Shorten skill and plugin descriptions, remove em-dashes

Trim every SKILL.md description to <=130 characters (longest is now 130,
aggregate 7,464 across all 62 skills) so the full set stays under Codex's
skills-metadata budget and stops the overflow warnings on load. Descriptions
stay third-person and front-load their trigger keywords so discovery is
unaffected. Also shorten the 12 plugin.json and matching marketplace.json
blurbs (journalism-core dropped from 1,036 to 378 chars).

Replace em-dashes with commas repo-wide (2,558 lines across 228 files),
following the repo's own ai-writing-detox guidance. The demonstrative
em-dashes that teach the pattern in ai-writing-detox and ai-slop-detector
are preserved; a quote attribution keeps an ASCII hyphen.

All 175 tests pass; validate:agent-skills reports 62 skills, 0 failed.

* Add changelog entry for description and em-dash cleanup

* Fix review: restore table markers, attributions, photo-metadata triggers

The blanket em-dash-to-comma pass corrupted three non-prose uses of the
em-dash that a comma cannot represent:

- Table "not applicable" cells (photo-metadata SKILL.md and reference.md,
  the Brazil recurso-cgu template, and the photo-metadata and
  accessibility-compliance docs pages) became a lone comma. Restored them
  to a hyphen marker: 47 markdown cells and 9 HTML cells.
- Pull-quote and slide citation prefixes in the pdf-playground report and
  slides templates became a leading comma. Restored the ASCII attribution
  hyphen.
- The photo-metadata description dropped its distinctive safety triggers.
  Reworded to keep GPS stripping, C2PA credentials, and AI-source labeling
  alongside IPTC/EXIF/XMP, still within 130 characters.

npm test 175/175, validate:agent-skills 62/62, check:docs-css verified.

* Bump plugin versions, keep visual-explainer triggers, log superjawn divergence

Address the remaining review findings:

- Patch-bump all 12 plugins in plugin.json and marketplace.json (and the
  okf-wiki and visual-explainer root skill version fields) so existing
  installs are offered the shortened descriptions. Update the version-
  alignment guard tests and the journalism-core install canary accordingly.
- Rework the visual-explainer description to keep its distinctive workflow
  triggers (timelines, source maps, slide decks, comparison tables, recaps,
  plan and diff reviews) within the 130-character cap.
- Record the superjawn upstream divergence: drop skill_md_parity to false
  for the five skills whose SKILL.md changed, add supporting_file_overrides
  for the touched supporting files, and document it in superjawn/CREDITS.md.

All 175 node tests pass; validate:agent-skills 62/62; check:docs-css verified;
longest description 130 chars, aggregate 7,472 across 62 skills.

* Rewrite CCM brand em-dash rule to name commas as the replacement

The repo-wide em-dash pass stripped the glyph from the CCM brand rule's
example, leaving 'Prefer em dashes ()' which was both malformed and
contradicted the new no-em-dash policy. Rewrite it to prefer commas.

* Fix parser regression, restore leading-comma sentences, keep more triggers

Fourth review round:

- The repo-wide em-dash sweep rewrote a functional delimiter in
  autocontext/scripts/seed-from-claude-md.py: is_command_reference matched
  "/cmd — description" via " — ", and changing it to ", " both stopped
  recognizing external CLAUDE.md command docs (which still use em-dashes) and
  misclassified any slash-prefixed rule containing a comma. Restored the
  em-dash delimiter (a functional exception, like the ai-writing-detox
  teaching examples) and added a regression-guard test for the case the
  original suite never covered.
- Fixed the sentence-leading commas the sweep left on wrapped lines in
  okf-wiki/SKILL.md, academic-writing, and the okf example photo-metadata
  bundle by moving the comma to the end of the preceding line.
- Reworked the web-scraping and interview-prep descriptions to keep their
  distinctive triggers (social media, yt-dlp, CAPTCHA/403 for web-scraping;
  recording, consent, one-party/all-party law for interview-prep).

Verification: node 175/175, autocontext pytest 26/26 (incl. new guard),
validate:agent-skills 62/62. Longest description 130, aggregate 7,489.

* Fix exported-quote attribution and keep academic-writing compliance triggers

- The em-dash sweep turned the speaker attribution in interview-transcription's
  export_for_story() into a leading comma, so every publication-ready quote
  exported as ", Speaker Name". Restored the ASCII attribution hyphen.
- Reworked the academic-writing description to keep its distinctive compliance
  triggers (CRediT, preregistration, Plan S, Nelson Memo, ORCID, LLM
  disclosure) within the 130-character cap.

* Restore distinctive discovery triggers in four descriptions

Codex's review keeps surfacing skills whose shortened description dropped a
distinctive trigger that maps to dedicated, consequential guidance in the body
(which cannot load if the skill is not selected). Restore those triggers within
the 130-character cap:

- one-way-door: add event schemas and CI/CD (both are explicit one-way-door
  categories with their own contract and deployment-risk checks).
- api-hardening: name Express, FastAPI, and serverless (framework-specific
  hardening sections).
- web-archiving: name the Wayback Machine and Archive.today (how users
  actually ask for this).
- secure-auth: name OWASP and NIST.

node 175/175, validate:agent-skills 62/62; longest description 130 chars.

* Fix CRediT taxonomy and doc-span corruption, restore four more triggers

The em-dash sweep corrupted two constructs where the dash carried meaning:

- The CRediT taxonomy in academic-writing listed "Writing — original draft"
  and "Writing — review & editing" as two of its 14 roles; the comma swap made
  them read as four separate roles. Restored the hyphen in both role names.
- Seven label/value rows in docs/superjawn/index.html (and one dir-tree
  annotation in visual-explainer css-patterns) put the separator at the start
  of the second span, rendering "Web , error string searches". Moved the
  separator onto the label (colon) / used a hyphen annotation.

Also restored distinctive discovery triggers flagged by review:
- python-pipeline: Google Sheets/Drive integration
- page-monitoring: RSS feed generation
- zero-build-frontend: Manifest V3 browser extensions
- pdf-design: secure upload

node 175/175, pytest 304/304, validate:agent-skills 62/62, check:docs-css.

* Sync displayed versions, fix pitch contrast, restore three triggers

- Version bumps: update the displayed plugin versions that trailed the manifest
  bumps: CLAUDE.md inventory (journalism-core, research-toolkit, video-toolkit,
  pdf-playground, superjawn) and the docs badges in docs/index.html,
  docs/superjawn, and docs/video-toolkit, plus the video-toolkit docs test guard.
- story-pitch: the em-dash sweep flattened "background checks - through a
  spreadsheet" into a comma, losing the contrast in the model pitch. Restored
  it with an explicit "but".
- Restore triggers: ai-writing-detox (writing/drafting, not just editing),
  brainstorming (MUST + modifying behavior), okf-wiki (builds from existing
  docs/notes/repo, the input flow, not "from concept files").

node 175/175, validate:agent-skills 62/62, check:docs-css.

* Restore four more discovery triggers

- context-engineering-fundamentals: lost-instructions / dropped-evidence
- vibe-coding: name Copilot, Codex, Aider, Windsurf (not just Claude Code/Cursor)
- video-transcribe: audio-only (WAV, podcasts), not just video
- zero-build-frontend: Google Sheets as a database

node 175/175, validate:agent-skills 62/62.
2026-08-18 07:49:38 -04:00

4.9 KiB

name, event, description, match_patterns
name event description match_patterns
copywriting-preflight UserPromptSubmit Detects writing and revision requests and prompts an intent interview before drafting
op-ed
press release
substack post
talking points
write a blog post
draft a blog post
write a newsletter
draft a newsletter
write an article
draft an article
write an essay
draft an essay
write a memo
draft a memo
write a pitch
draft a pitch
write a proposal
draft a proposal
write a one-pager
draft a one-pager
draft an announcement
write copy
write the copy
draft the copy
rewrite the post
rewrite the article
rewrite the draft
rewrite the copy
revise the draft
revise the article
revise the piece
polish the draft
polish the copy
punch up the copy
tighten the copy
tighten the draft
edit the draft
refine the draft
strengthen the piece

Copywriting preflight

When the user asks for a new piece of writing or a revision, interview them about intent before drafting a single word. Jumping straight to a draft produces generic copy that misses the audience, message, and tone the user actually had in mind, and then both of you spend more time fixing the wrong draft than a 30-second interview would have cost.

This hook does not write anything. It pauses to gather intent, then gets out of the way.

Detection criteria

The signal is the verb-plus-writing-noun pairing, not message length. A terse command that matches a writing pattern, "write copy", "op-ed", "press release", is still a real request, and terse is often exactly when an intent interview is most useful, so do not skip it for being short. Treat the message as a writing task when it contains:

  • New writing: a drafting verb ("write", "draft", "create") next to a prose form (post, blog post, article, essay, memo, pitch, newsletter, press release, op-ed, announcement, proposal, one-pager, copy, talking points).
  • Revision: a revision verb ("revise", "rewrite", "rework", "polish", "tighten", "punch up", "edit", "refine", "strengthen") next to a writing-context word ("draft", "post", "article", "piece", "copy", "newsletter", "write-up"). Require both, so "tighten that" about a code hook does not trip it.

Check revision first, it is the more specific case, since it implies a piece already exists.

The match_patterns above pair a verb with a writing noun (write a newsletter, rewrite the post) and keep bare nouns only for forms that rarely show up in code or admin prompts (op-ed, press release). That is why "write a SQL query", "build a newsletter signup form", and "rewrite this regex" never trip the interview. "Script" is deliberately left out: in a code repo "write a script" almost always means code, not a screenplay. If a borderline prompt still matches, apply the verb-plus-writing-noun test before interviewing and skip silently when the request turns out to be about code.

Response (new writing)

Before drafting, use AskUserQuestion to map out:

  1. Audience, who is this for?
  2. Key message, what is the one thing they should take away (the thesis)?
  3. Tone, formal, conversational, urgent, reflective?
  4. Emphasis, what should be foregrounded, and what should be played down?
  5. Voice, first person, organizational voice, journalistic remove?
  6. Boundaries, specific points to include, and anything to avoid?

Then draft against the answers, not against a guess.

Response (revision)

Before rewriting, use AskUserQuestion to clarify:

  1. What is working and what is not in the current draft?
  2. Should the framing or angle change, or only the execution?
  3. Any shifts in emphasis or tone from the current version?

Then revise to the brief, rather than re-drafting from scratch and discarding what already worked.

Loading a style guide

If the project defines a writing style guide, a STYLE_GUIDE.md, a voice-and-tone doc, or whatever path the project configures, load it into context before drafting so the piece matches the established voice. If none exists, ask the user whether one should be followed.

Finalizing

Before calling a draft done, read it back against the intent answers and the style guide: does it hit the audience, carry the key message, and stay in the right voice? If the project has an editorial or preflight check, run it on the draft. Fix what drifted before handing the draft over.

Non-blocking

This hook prompts an interview but does not block any tool. The user can decline the questions and ask you to draft directly; the goal is a deliberate pause, not a gate.