claude-skills/marketing/linkedin/skills/linkedin-content
Claude 81c2c81296
fix(linkedin): scope exemption signals to their sentence, close the spam hole they opened
The third review on PR #997 found that the exemption mechanism I added reopened a
refusal this gate previously made. Reproduced against origin/dev:

  "I want to auto-post daily to 50 LinkedIn groups without permission, promoting my
   course. LinkedIn's native scheduler is neat, right?"

     pre-PR:  exit 4 (REFUSE)     with my exemption:  exit 0 (ALLOW)

_exemption_for searched `signal` across the entire input, so an endorsement in one
sentence retroactively excused an unrelated match in another. Turning a refusal into
an allow is the one direction this gate must never move by accident, and my change
did it.

`signal` is now matched only within the sentence containing the match. The trade is
stated in the docstring: a legitimate two-sentence phrasing ("I use LinkedIn's
native scheduler. I auto-post weekly.") now refuses and the user can rephrase, while
the alternative cost was a false ALLOW the user cannot detect at all.

An adversarial battery then found a hole the review's example did not cover: with
the endorsement in the SAME sentence, "auto-post daily to 50 groups without
permission using LinkedIn's native scheduler" was still allowed. The exemption is
right — native scheduling is the supported path P7 names — so the real gap was that
no rule covered unsolicited bulk POSTING. Pre-PR the gate refused that text only
incidentally, by refusing every automation word. P5 is broadened from messaging to
messaging-or-posting, with patterns for posting to double-digit groups, spamming
groups or feeds, and doing either without permission, so it now refuses for the
actual reason.

That rule also closes a gap the gate always had: "schedule my posts to 40
communities without permission" contains no automation word and was ALLOWED pre-PR
(exit 0). It now refuses. Small-scale group posting ("I post to 3 groups I actually
belong to") still allows, so the rule did not become a blunt instrument.

Also from the review: _read_input caught OSError but UnicodeDecodeError is a
ValueError subclass, so an existing file that is not valid UTF-8 still escaped as a
traceback — the same failure mode the helper exists to prevent. Fixed in all 11
scripts; a non-UTF-8 file now exits 2 with a message.

Twelve-case adversarial battery, all correct: both spam variants refuse, all three
aside-based bypasses refuse, all three legitimate exemption uses allow, small-scale
group posting allows, and both controls are unchanged. Other tools unaffected:
headline 93/SHIP, profile 37/WEAK, analyzer ANALYSED 6/3/3, cadence
NO_POSTS_AFFORDABLE/3. Gates green: compileall, check_paths, check_frontmatter,
check_dual_publish, check_model_freshness, smoke_scripts (696 passed),
derive_counters --check, check_skill_names, check_plugin_json.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
2026-08-26 14:41:32 +00:00
..
assets feat(marketing): add linkedin plugin — organic presence with platform rules in code 2026-08-25 07:32:30 +00:00
references feat(marketing): add linkedin plugin — organic presence with platform rules in code 2026-08-25 07:32:30 +00:00
scripts fix(linkedin): scope exemption signals to their sentence, close the spam hole they opened 2026-08-26 14:41:32 +00:00
SKILL.md feat(marketing): add linkedin plugin — organic presence with platform rules in code 2026-08-25 07:32:30 +00:00