docs: sweep em dashes out of the active published surface (#180)

Em dashes crept back into examples, docs/platform-native.md, several READMEs,
the ponytail-debt skill, and a command file since 88431de. Replaced with plain
punctuation (commas, matching the house convention), .openclaw mirror
regenerated. Follows 88431de's scope: leaves untouched the vendored caveman
SKILL.md and the dated benchmarks/results/ writeups (historical records).

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
DietrichGebert
2026-06-19 02:37:02 +02:00
committed by GitHub
co-authored by Claude Opus 4.8
parent bd6176a9b3
commit ff5d0936be
19 changed files with 50 additions and 50 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
# Examples
Real model output, verbatim from benchmark runs the same task answered by the same model
Real model output, verbatim from benchmark runs, the same task answered by the same model
with no skill (`## Without Ponytail`) and with ponytail (`## With Ponytail`), so you can
compare side by side. Model: Claude Haiku 4.5, temperature 1, source `benchmarks/output.json`.
+5 -5
View File
@@ -2,9 +2,9 @@
**Task:** "Write Python code that reads sales.csv and sums the 'amount' column."
Verbatim model output from a benchmark run Claude Haiku 4.5, no-skill arm vs ponytail arm, temperature 1, source `benchmarks/output.json`. Reproduce: `npx promptfoo@latest eval -c benchmarks/promptfooconfig.yaml`.
Verbatim model output from a benchmark run, Claude Haiku 4.5, no-skill arm vs ponytail arm, temperature 1, source `benchmarks/output.json`. Reproduce: `npx promptfoo@latest eval -c benchmarks/promptfooconfig.yaml`.
## Without Ponytail 20 lines of code
## Without Ponytail, 20 lines of code
# Python code to read sales.csv and sum the 'amount' column
@@ -57,7 +57,7 @@ except KeyError:
- Provides built-in error handling
- Efficient for large files
## With Ponytail 3 lines of code
## With Ponytail, 3 lines of code
```python
import csv
@@ -66,6 +66,6 @@ total = sum(float(row['amount']) for row in csv.DictReader(open('sales.csv')))
print(total)
```
Skipped: pandas, error handling, file closing add when the CSV is large, malformed, or you need more analysis.
Skipped: pandas, error handling, file closing, add when the CSV is large, malformed, or you need more analysis.
**20 → 3 lines of code** same model, same prompt.
**20 → 3 lines of code**, same model, same prompt.
+5 -5
View File
@@ -2,9 +2,9 @@
**Task:** "Add debounce to a search input in vanilla JavaScript. It currently fires an API call on every keystroke."
Verbatim model output from a benchmark run Claude Haiku 4.5, no-skill arm vs ponytail arm, temperature 1, source `benchmarks/output.json`. Reproduce: `npx promptfoo@latest eval -c benchmarks/promptfooconfig.yaml`.
Verbatim model output from a benchmark run, Claude Haiku 4.5, no-skill arm vs ponytail arm, temperature 1, source `benchmarks/output.json`. Reproduce: `npx promptfoo@latest eval -c benchmarks/promptfooconfig.yaml`.
## Without Ponytail 116 lines of code
## Without Ponytail, 116 lines of code
# Debounce Search Input
@@ -190,7 +190,7 @@ searchInput.addEventListener('blur', () => {
**Typical keystroke reduction:** 10 characters = 10 API calls → 1-2 API calls with debounce ✅
## With Ponytail 10 lines of code
## With Ponytail, 10 lines of code
```javascript
const searchInput = document.querySelector('input[type="search"]');
@@ -206,6 +206,6 @@ searchInput.addEventListener('input', (e) => {
});
```
Skipped: debounce utility function, class wrapper, config object `setTimeout` + `clearTimeout` is the debounce. Add a utility when you need it on 3+ inputs.
Skipped: debounce utility function, class wrapper, config object, `setTimeout` + `clearTimeout` is the debounce. Add a utility when you need it on 3+ inputs.
**116 → 10 lines of code** same model, same prompt.
**116 → 10 lines of code**, same model, same prompt.
+1 -1
View File
@@ -28,4 +28,4 @@ const copy = JSON.parse(JSON.stringify(original));
const copy = structuredClone(original);
```
**1 dependency (or a fragile hack) → 1 built-in.** `structuredClone` handles `Date`, `Map`, `Set`, `ArrayBuffer`, `RegExp`, circular references, and more everything `JSON.parse/stringify` silently drops. Available in every browser since 2022 and Node.js since v17. Pull lodash in when you need the rest of it, not for one function.
**1 dependency (or a fragile hack) → 1 built-in.** `structuredClone` handles `Date`, `Map`, `Set`, `ArrayBuffer`, `RegExp`, circular references, and more, everything `JSON.parse/stringify` silently drops. Available in every browser since 2022 and Node.js since v17. Pull lodash in when you need the rest of it, not for one function.
+5 -5
View File
@@ -2,9 +2,9 @@
**Task:** "Write me a Python function that validates email addresses."
Verbatim model output from a benchmark run Claude Haiku 4.5, no-skill arm vs ponytail arm, temperature 1, source `benchmarks/output.json`. Reproduce: `npx promptfoo@latest eval -c benchmarks/promptfooconfig.yaml`.
Verbatim model output from a benchmark run, Claude Haiku 4.5, no-skill arm vs ponytail arm, temperature 1, source `benchmarks/output.json`. Reproduce: `npx promptfoo@latest eval -c benchmarks/promptfooconfig.yaml`.
## Without Ponytail 75 lines of code
## Without Ponytail, 75 lines of code
# Email Validation Function
@@ -142,7 +142,7 @@ if __name__ == "__main__":
**Recommendation**: Use the `email-validator` library for production applications, as it properly handles RFC 5321/5322 standards. Use the simple regex version for quick scripts or when you want to avoid dependencies.
## With Ponytail 3 lines of code
## With Ponytail, 3 lines of code
```python
import re
@@ -151,6 +151,6 @@ def is_valid_email(email: str) -> bool:
return bool(re.match(r'^[^@]+@[^@]+\.[^@]+$', email))
```
Skipped: RFC 5322 parser, DNS MX lookup, confirmation email. Add when you actually need to reject `user+tag@sub.domain.co.uk` or catch typos until then, this catches 99% of "oops I fat-fingered it" cases.
Skipped: RFC 5322 parser, DNS MX lookup, confirmation email. Add when you actually need to reject `user+tag@sub.domain.co.uk` or catch typos, until then, this catches 99% of "oops I fat-fingered it" cases.
**75 → 3 lines of code** same model, same prompt.
**75 → 3 lines of code**, same model, same prompt.
+1 -1
View File
@@ -32,4 +32,4 @@ const byStatus = Object.groupBy(orders, order => order.status);
// → { pending: [...], shipped: [...], delivered: [...] }
```
**1 dependency (or a reduce) → 1 built-in.** `Object.groupBy` shipped in Chrome 117, Firefox 119, Safari 17.4, Node.js 21. If you need a `Map` instead of a plain object: `Map.groupBy(orders, o => o.status)`. Check your target runtime; if you need IE11 or old Node, the `reduce` one-liner is still the right call not lodash.
**1 dependency (or a reduce) → 1 built-in.** `Object.groupBy` shipped in Chrome 117, Firefox 119, Safari 17.4, Node.js 21. If you need a `Map` instead of a plain object: `Map.groupBy(orders, o => o.status)`. Check your target runtime; if you need IE11 or old Node, the `reduce` one-liner is still the right call, not lodash.
+1 -1
View File
@@ -55,4 +55,4 @@ export function Feed({ items, fetchMore, hasMore }) {
}
```
**1 dependency → 0 dependencies.** `IntersectionObserver` fires only when the sentinel enters the viewport no scroll event, no throttling, no jank. Ships in every browser. The library wraps exactly this API.
**1 dependency → 0 dependencies.** `IntersectionObserver` fires only when the sentinel enters the viewport, no scroll event, no throttling, no jank. Ships in every browser. The library wraps exactly this API.
+1 -1
View File
@@ -37,7 +37,7 @@ export function DeleteModal({ onConfirm, onCancel }) {
}
```
A dependency, a portal, an overlay, a root, a trigger, a content wrapper to show a box with two buttons.
A dependency, a portal, an overlay, a root, a trigger, a content wrapper, to show a box with two buttons.
## With Ponytail
+6 -6
View File
@@ -2,9 +2,9 @@
**Task:** "Add rate limiting to my FastAPI endpoint so users can't spam it."
Verbatim model output from a benchmark run Claude Haiku 4.5, no-skill arm vs ponytail arm, temperature 1, source `benchmarks/output.json`. Reproduce: `npx promptfoo@latest eval -c benchmarks/promptfooconfig.yaml`.
Verbatim model output from a benchmark run, Claude Haiku 4.5, no-skill arm vs ponytail arm, temperature 1, source `benchmarks/output.json`. Reproduce: `npx promptfoo@latest eval -c benchmarks/promptfooconfig.yaml`.
## Without Ponytail 128 lines of code
## Without Ponytail, 128 lines of code
# Rate Limiting in FastAPI
@@ -248,9 +248,9 @@ async def test_rate_limit():
# First 5 should be 200, 6th should be 429
```
**Recommendation:** Use `slowapi` for most casesit's the most popular and easiest to implement! 🚀
**Recommendation:** Use `slowapi` for most cases, it's the most popular and easiest to implement! 🚀
## With Ponytail 10 lines of code
## With Ponytail, 10 lines of code
```python
from fastapi import FastAPI, HTTPException
@@ -267,6 +267,6 @@ async def my_endpoint(request):
return {"status": "ok"}
```
Skipped: custom rate limit logic, Redis, sliding windows `slowapi` handles it. Add when: you need distributed rate limiting across multiple servers (swap `Limiter` for Redis backend) or per-user limits (add `key_func=lambda r: r.headers.get("authorization")`).
Skipped: custom rate limit logic, Redis, sliding windows, `slowapi` handles it. Add when: you need distributed rate limiting across multiple servers (swap `Limiter` for Redis backend) or per-user limits (add `key_func=lambda r: r.headers.get("authorization")`).
**128 → 10 lines of code** same model, same prompt.
**128 → 10 lines of code**, same model, same prompt.
+5 -5
View File
@@ -2,9 +2,9 @@
**Task:** "Build me a countdown timer component in React that counts down from a given number of seconds."
Verbatim model output from a benchmark run Claude Haiku 4.5, no-skill arm vs ponytail arm, temperature 1, source `benchmarks/output.json`. Reproduce: `npx promptfoo@latest eval -c benchmarks/promptfooconfig.yaml`.
Verbatim model output from a benchmark run, Claude Haiku 4.5, no-skill arm vs ponytail arm, temperature 1, source `benchmarks/output.json`. Reproduce: `npx promptfoo@latest eval -c benchmarks/promptfooconfig.yaml`.
## Without Ponytail 267 lines of code
## Without Ponytail, 267 lines of code
# React Countdown Timer Component
@@ -369,7 +369,7 @@ export function StyledCountdownTimer({ initialSeconds = 60 }) {
Choose the version that best fits your needs!
## With Ponytail 9 lines of code
## With Ponytail, 9 lines of code
```jsx
export function CountdownTimer({ seconds }) {
@@ -385,6 +385,6 @@ export function CountdownTimer({ seconds }) {
}
```
Skipped: pause/resume, formatted display (mm:ss), sound on zero, styling add when needed.
Skipped: pause/resume, formatted display (mm:ss), sound on zero, styling, add when needed.
**267 → 9 lines of code** same model, same prompt.
**267 → 9 lines of code**, same model, same prompt.