Insert `from __future__ import annotations` in the 17 files that use
PEP 604/585 annotations in module-level positions evaluated at import
time, so scripts/banned_phrase_scan.py and friends no longer raise
TypeError on Python 3.8/3.9. Add a 3.8 leg to the CI matrix so the
floor claim in README.md is actually gated, and correct the two
imprecise "439 deterministic cases" references to "440 deterministic
script cases (439 pass, 1 documented xfail)".
New scripts must carry the future-import until the floor is raised;
if the maintainer later chooses 3.10+, delete the CI 3.8 leg and
README claim together.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K6CYksdLbXbTAxcAQjvHz5
- whether-you're pattern requires a role noun phrase (a/an/just starting) and
matches sentence-initially: 'Whether you're right or wrong' and activity
gerunds are clean, canonical audience flattery still flags (FP-39/40, REC-19)
- Bare 'bolstered' ban dropped in favor of the tense-aware collocation gate;
literal reinforcement clean, rhetorical support flags (FP-41, REC-20);
catalog row updated
- double-down collocation inflected (doubled/doubling) with its/their/a
determiners (FN-22)
- and/or extracted as a preservation constraint: collapse to plain 'and'
fails, rewording to 'or (or both)' passes (PRES-28/29)
- structure_scan opener-repetition ignores enumeration openers
(Section/Chapter/Step/Figure...); academic roadmap abstracts clean
(STRUCT-17)
- run_local.py fails a case on CLI error output (Not logged in etc.) instead
of grading the error page; stale DONOHARM-01 tune artifact regenerated with
a real answer (similarity 1.0)
- SKILL.md preservation-gate wording aligned with --strict semantics
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A red-team of the writing the skill PRODUCES (not just detection) confirmed the
core thesis: unslop can swap corporate slop for an equally-detectable "anti-slop"
register, and its validation is blind to the semantic facts most at risk. An
incentivized adversary attacked faithful skill outputs; the top findings were
re-verified by hand before fixing.
Scanner (B1, B7): the gold fragment-contrast form ("Not the technology. The
people.") and staccato triplets scored 0 — the scanner was blind to the skill's
own house style. Added an anti_slop_register category (fragment contrast +
staccato run, soft) and a readability staccato flag with no sentence-count gate.
Validation (B2): extract_constraints now captures cited references (Section 12(b),
Figure 2, Eq. 3) as hard must-preserve; validate_preservation warns when
negations, scope words, or conditionals are dropped ("does not support" ->
"supports"). SKILL.md no longer claims validation covers meaning.
SKILL.md guards (B3/B4/B6/B8): added "Register & genre guards" — don't de-hedge
regulated/technical text, don't invent first-person voice, avoid your own
staccato/fragment tell, keep warm text warm. Em-dash rule rewritten from "default
to zero" (which 2/4 presets violate) to "sparing appositive dash, never a splice".
Evals: +8 deterministic (AS-01/02/03, FP-12, PRES-08/09, SEM-01) and +8 behavioral
(SKILL-FRAGMENT/HEDGE/LEGAL/STACCATO/WARMTH/NOINVENT/OVEREDIT/EMDASH). Full
write-up in evals/ADVERSARIAL-WRITING-ANALYSIS.md.
Suite: 77 cases (51 script: 50 PASS / 1 XFAIL / 0 FAIL, 26 behavioral).
Flips 19 of the 20 deterministic xfail cases to PASS (FP-06, literal
"delve into a place", stays xfail as an accepted regex sense-ambiguity limit).
Final: 20 PASS, 1 XFAIL, 0 FAIL.
Fact preservation (validate_preservation.py, extract_constraints.py):
- currency compares absolute magnitude, so $47.3M no longer equals $47.3 billion
- percentages require an exact token match (12% no longer matches 120%)
- dates require the month, not just the year (March 3 2020 != December 2020)
- bare integers and whole phone numbers are now tracked as constraints
- faithful rewordings ($47.3M -> $47.3 million) still pass, no false missing
- missing input files exit cleanly instead of raising a traceback
Scanner (banned_phrase_scan.py):
- removed over-broad entries: "the real" (hit "the real estate"), bare
"period."/"full stop." (hit any sentence ending in "period")
- gated context-sensitive words (leverage, navigate, tapestry, boasts) behind
jargon collocations so literal/financial senses aren't flagged
- added missing tells: in conclusion, firstly/secondly, underscore the
importance, treasure trove, ever-evolving, rich mosaic, plus stop-slop's
false-agency family (numbers speak for themselves, data tells a story)
- quote masking: dropped the 500-char cap, allowed multi-line quotes, and
stopped masking single-quoted prose that was hiding real slop
Robustness (readability_metrics.py, diff_check.py):
- numeric-only text counts as words instead of reading as empty
- punctuation-only edits register as change instead of 0%
Kept references/taboo-phrases.md in sync with the new scanner patterns.