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
@@ -23,7 +23,7 @@ the convention out of the ledger.
One row per marker, grouped by file: One row per marker, grouped by file:
`<file>:<line> <what was simplified>. ceiling: <the limit named>. upgrade: <the trigger to revisit>.` `<file>:<line>, <what was simplified>. ceiling: <the limit named>. upgrade: <the trigger to revisit>.`
The convention is `ponytail: <ceiling>, <upgrade path>`, so pull the ceiling The convention is `ponytail: <ceiling>, <upgrade path>`, so pull the ceiling
and the trigger straight from the comment. Want an owner per row too? add and the trigger straight from the comment. Want an owner per row too? add
+1 -1
View File
@@ -2,4 +2,4 @@
description: "Harvest ponytail: comments into a tracked debt ledger" description: "Harvest ponytail: comments into a tracked debt ledger"
--- ---
Harvest every `ponytail:` comment in this repository into a debt ledger so deferrals do not rot into 'later means never'. Grep the whole tree for comment markers (grep -rnE '(#|//) ?ponytail:' ., skipping node_modules/.git/build output). One row per marker, grouped by file: <file>:<line> <what was simplified>. ceiling: <the limit named in the comment>. upgrade: <the trigger to revisit>. Tag any marker that names no upgrade path or trigger as no-trigger, those rot silently. End with the count of markers and how many lack a trigger. If none: 'No ponytail: debt. Clean ledger.' Report only, change nothing. Harvest every `ponytail:` comment in this repository into a debt ledger so deferrals do not rot into 'later means never'. Grep the whole tree for comment markers (grep -rnE '(#|//) ?ponytail:' ., skipping node_modules/.git/build output). One row per marker, grouped by file: <file>:<line>, <what was simplified>. ceiling: <the limit named in the comment>. upgrade: <the trigger to revisit>. Tag any marker that names no upgrade path or trigger as no-trigger, those rot silently. End with the count of markers and how many lack a trigger. If none: 'No ponytail: debt. Clean ledger.' Report only, change nothing.
+2 -2
View File
@@ -96,7 +96,7 @@ Flojo, no negligente: la validación en límites de confianza, el manejo de pér
El mayor esfuerzo que ponytail te va a pedir: El mayor esfuerzo que ponytail te va a pedir:
Los plugins de Claude Code y Codex ejecutan dos pequeños lifecycle hooks de Node.js, así que `node` debe estar en tu PATH (nota para usuarios de Nix/nvm: debe estar en el PATH del shell no-interactivo). Si no lo está, los skills igualmente funcionan la activación automática simplemente queda en silencio en vez de lanzar un error en cada prompt. Los plugins de Claude Code y Codex ejecutan dos pequeños lifecycle hooks de Node.js, así que `node` debe estar en tu PATH (nota para usuarios de Nix/nvm: debe estar en el PATH del shell no-interactivo). Si no lo está, los skills igualmente funcionan, la activación automática simplemente queda en silencio en vez de lanzar un error en cada prompt.
### Claude Code ### Claude Code
@@ -224,7 +224,7 @@ node scripts/check-rule-copies.js
npm test npm test
``` ```
El paquete de skills de OpenClaw (`.openclaw/skills/`) se genera desde `skills/`; ejecuta `node scripts/build-openclaw-skills.js` después de cambiar un skill la suite de tests falla si está desactualizado. El paquete de skills de OpenClaw (`.openclaw/skills/`) se genera desde `skills/`; ejecuta `node scripts/build-openclaw-skills.js` después de cambiar un skill, la suite de tests falla si está desactualizado.
El benchmark de correctness lanza Python para las verificaciones de email y CSV; se prueba `python3` antes que `python`. Las verificaciones de CSV requieren `pandas` instalado localmente. El benchmark de correctness lanza Python para las verificaciones de email y CSV; se prueba `python3` antes que `python`. Las verificaciones de CSV requieren `pandas` instalado localmente.
+1 -1
View File
@@ -181,7 +181,7 @@ It reuses this repo's `gemini-extension.json`. One difference: Antigravity conve
### CodeWhale ### CodeWhale
Reads `AGENTS.md` from the project root zero setup. Copy [`AGENTS.md`](AGENTS.md) to your project, or run `codewhale` from a checkout of this repo. That's it. Reads `AGENTS.md` from the project root, zero setup. Copy [`AGENTS.md`](AGENTS.md) to your project, or run `codewhale` from a checkout of this repo. That's it.
### OpenClaw ### OpenClaw
+1 -1
View File
@@ -6,7 +6,7 @@ Three arms (no skill, [caveman](https://github.com/JuliusBrussee/caveman), ponyt
### Claude (Haiku / Sonnet / Opus) ### Claude (Haiku / Sonnet / Opus)
Requires an Anthropic API key and **Node.js ≥ 22.22.0** (promptfoo's engine constraint Requires an Anthropic API key and **Node.js ≥ 22.22.0** (promptfoo's engine constraint,
check with `node --version` and upgrade if needed): check with `node --version` and upgrade if needed):
```bash ```bash
+2 -2
View File
@@ -92,11 +92,11 @@ python judge.py --run runs/<stamp> # score every workspace's source
Fewer lines only counts as a win if the code still does the job. The LOC tier scores the open Fewer lines only counts as a win if the code still does the job. The LOC tier scores the open
feature tasks on `git diff` alone, with no deterministic check that the asked feature was feature tasks on `git diff` alone, with no deterministic check that the asked feature was
actually built so an arm could "win" the LOC metric by shipping a stub. This pass closes that actually built, so an arm could "win" the LOC metric by shipping a stub. This pass closes that
hole: the same auditable LLM judge (fixed model, temperature 0, published rubric) rates how hole: the same auditable LLM judge (fixed model, temperature 0, published rubric) rates how
**fully** each submission implements its task. Rubric: `0` stub/placeholder, `1` partial (core **fully** each submission implements its task. Rubric: `0` stub/placeholder, `1` partial (core
behavior missing), `2` mostly complete (a stated requirement missing), `3` fully implements the behavior missing), `2` mostly complete (a stated requirement missing), `3` fully implements the
task. Read it **alongside** the LOC table a low-LOC arm whose completeness also drops is doing task. Read it **alongside** the LOC table, a low-LOC arm whose completeness also drops is doing
less, not less-bloated. less, not less-bloated.
Validated like the over-engineering judge: `--selftest` requires the judge to rank a complete Validated like the over-engineering judge: `--selftest` requires the judge to rank a complete
+8 -8
View File
@@ -60,7 +60,7 @@ Libraries people install that the runtime already ships.
| `query-string` / `qs` | `new URLSearchParams(location.search)` | | `query-string` / `qs` | `new URLSearchParams(location.search)` |
| `lodash.clonedeep` | `structuredClone(obj)` | | `lodash.clonedeep` | `structuredClone(obj)` |
| `lodash.groupby` | `Object.groupBy(arr, fn)` | | `lodash.groupby` | `Object.groupBy(arr, fn)` |
| `lodash.debounce` | see debounce one-liner below | | `lodash.debounce` | see debounce one-liner below |
| `numeral` / `accounting` | `new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" })` | | `numeral` / `accounting` | `new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" })` |
| `date-fns` format | `new Intl.DateTimeFormat("en-US", { dateStyle: "long" }).format(date)` | | `date-fns` format | `new Intl.DateTimeFormat("en-US", { dateStyle: "long" }).format(date)` |
| `date-fns` relative time | `new Intl.RelativeTimeFormat("en", { numeric: "auto" }).format(-3, "day")` | | `date-fns` relative time | `new Intl.RelativeTimeFormat("en", { numeric: "auto" }).format(-3, "day")` |
@@ -97,7 +97,7 @@ Packages that wrap Node built-ins.
| `make-dir` | `fs.mkdirSync(path, { recursive: true })` | | `make-dir` | `fs.mkdirSync(path, { recursive: true })` |
| `slash` (win paths) | `path.posix` or `path.normalize()` | | `slash` (win paths) | `path.posix` or `path.normalize()` |
| `uuid` (v4) | `crypto.randomUUID()` | | `uuid` (v4) | `crypto.randomUUID()` |
| `ms` (parse duration strings) | keep `ms`, it's genuinely useful and tiny | | `ms` (parse duration strings) | keep `ms`, it's genuinely useful and tiny |
| `is-stream` | `val instanceof stream.Readable` | | `is-stream` | `val instanceof stream.Readable` |
| `object-assign` | `Object.assign()` / spread | | `object-assign` | `Object.assign()` / spread |
| `array-uniq` | `[...new Set(arr)]` | | `array-uniq` | `[...new Set(arr)]` |
@@ -119,12 +119,12 @@ Packages that wrap what Python already ships.
| `python-dateutil` (basic parsing) | `datetime.fromisoformat()` (Python 3.7+) | | `python-dateutil` (basic parsing) | `datetime.fromisoformat()` (Python 3.7+) |
| `pytz` | `zoneinfo.ZoneInfo("America/New_York")` (Python 3.9+) | | `pytz` | `zoneinfo.ZoneInfo("America/New_York")` (Python 3.9+) |
| `attrs` (simple data classes) | `@dataclass` | | `attrs` (simple data classes) | `@dataclass` |
| `six` | drop it, Python 2 is gone | | `six` | drop it, Python 2 is gone |
| `pathlib2` | `pathlib.Path` (built-in since Python 3.4) | | `pathlib2` | `pathlib.Path` (built-in since Python 3.4) |
| `enum34` | `enum.Enum` (built-in since Python 3.4) | | `enum34` | `enum.Enum` (built-in since Python 3.4) |
| `typing_extensions` (common types) | `from __future__ import annotations` + built-in generics | | `typing_extensions` (common types) | `from __future__ import annotations` + built-in generics |
| `simplejson` (basic use) | `json` (stdlib) | | `simplejson` (basic use) | `json` (stdlib) |
| `requests` (simple GET) | `urllib.request.urlopen(url)` `requests` for anything real | | `requests` (simple GET) | `urllib.request.urlopen(url)`, `requests` for anything real |
| `click` (single command) | `argparse` (stdlib) | | `click` (single command) | `argparse` (stdlib) |
| `mergedeep` | `dict \| other_dict` (Python 3.9+) | | `mergedeep` | `dict \| other_dict` (Python 3.9+) |
| `more-itertools` (basic) | `itertools` (stdlib): `chain`, `islice`, `groupby`, `product` | | `more-itertools` (basic) | `itertools` (stdlib): `chain`, `islice`, `groupby`, `product` |
@@ -150,9 +150,9 @@ Things the application layer implements that the database already does.
| JSON storage + query | `jsonb` (Postgres) / `JSON_EXTRACT` (SQLite/MySQL) | | JSON storage + query | `jsonb` (Postgres) / `JSON_EXTRACT` (SQLite/MySQL) |
| UUID generation | `gen_random_uuid()` (Postgres) / `UUID()` (MySQL) | | UUID generation | `gen_random_uuid()` (Postgres) / `UUID()` (MySQL) |
| Timestamps on insert/update | `DEFAULT now()` + trigger or `ON UPDATE CURRENT_TIMESTAMP` | | Timestamps on insert/update | `DEFAULT now()` + trigger or `ON UPDATE CURRENT_TIMESTAMP` |
| Enforce uniqueness | `UNIQUE` constraint not application-level checks | | Enforce uniqueness | `UNIQUE` constraint, not application-level checks |
| Enforce referential integrity | `FOREIGN KEY` not application-level checks | | Enforce referential integrity | `FOREIGN KEY`, not application-level checks |
| Enforce value ranges | `CHECK (price > 0)` not application-level validation | | Enforce value ranges | `CHECK (price > 0)`, not application-level validation |
--- ---
@@ -170,4 +170,4 @@ You debug the wrapper.
Skip the wrapper. The platform ships with your app for free. Skip the wrapper. The platform ships with your app for free.
When the native solution is genuinely insufficient (old browser support, edge cases it doesn't handle, ergonomics that matter at scale), the library earns its place. Install it then not before. When the native solution is genuinely insufficient (old browser support, edge cases it doesn't handle, ergonomics that matter at scale), the library earns its place. Install it then, not before.
+1 -1
View File
@@ -1,6 +1,6 @@
# Examples # 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 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`. 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." **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 # Python code to read sales.csv and sum the 'amount' column
@@ -57,7 +57,7 @@ except KeyError:
- Provides built-in error handling - Provides built-in error handling
- Efficient for large files - Efficient for large files
## With Ponytail 3 lines of code ## With Ponytail, 3 lines of code
```python ```python
import csv import csv
@@ -66,6 +66,6 @@ total = sum(float(row['amount']) for row in csv.DictReader(open('sales.csv')))
print(total) 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." **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 # Debounce Search Input
@@ -190,7 +190,7 @@ searchInput.addEventListener('blur', () => {
**Typical keystroke reduction:** 10 characters = 10 API calls → 1-2 API calls with debounce ✅ **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 ```javascript
const searchInput = document.querySelector('input[type="search"]'); 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); 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." **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 # 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. **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 ```python
import re import re
@@ -151,6 +151,6 @@ def is_valid_email(email: str) -> bool:
return bool(re.match(r'^[^@]+@[^@]+\.[^@]+$', email)) 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: [...] } // → { 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 ## With Ponytail
+6 -6
View File
@@ -2,9 +2,9 @@
**Task:** "Add rate limiting to my FastAPI endpoint so users can't spam it." **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 # Rate Limiting in FastAPI
@@ -248,9 +248,9 @@ async def test_rate_limit():
# First 5 should be 200, 6th should be 429 # 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 ```python
from fastapi import FastAPI, HTTPException from fastapi import FastAPI, HTTPException
@@ -267,6 +267,6 @@ async def my_endpoint(request):
return {"status": "ok"} 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." **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 # React Countdown Timer Component
@@ -369,7 +369,7 @@ export function StyledCountdownTimer({ initialSeconds = 60 }) {
Choose the version that best fits your needs! Choose the version that best fits your needs!
## With Ponytail 9 lines of code ## With Ponytail, 9 lines of code
```jsx ```jsx
export function CountdownTimer({ seconds }) { 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.
+2 -2
View File
@@ -12,9 +12,9 @@ prompt menu, or that pull context through tools. See issue #70.
## What it exposes ## What it exposes
- Prompt `ponytail` returns the ruleset as a user message. Optional `mode` - Prompt `ponytail`, returns the ruleset as a user message. Optional `mode`
argument: `lite`, `full`, or `ultra`. Omit it to use the configured default. argument: `lite`, `full`, or `ultra`. Omit it to use the configured default.
- Tool `ponytail_instructions` same text, plus `structuredContent` - Tool `ponytail_instructions`, same text, plus `structuredContent`
(`{ mode, instructions }`), for hosts that pull context via tools or code (`{ mode, instructions }`), for hosts that pull context via tools or code
execution. Read-only. execution. Read-only.
+1 -1
View File
@@ -26,7 +26,7 @@ the convention out of the ledger.
One row per marker, grouped by file: One row per marker, grouped by file:
`<file>:<line> <what was simplified>. ceiling: <the limit named>. upgrade: <the trigger to revisit>.` `<file>:<line>, <what was simplified>. ceiling: <the limit named>. upgrade: <the trigger to revisit>.`
The convention is `ponytail: <ceiling>, <upgrade path>`, so pull the ceiling The convention is `ponytail: <ceiling>, <upgrade path>`, so pull the ceiling
and the trigger straight from the comment. Want an owner per row too? add and the trigger straight from the comment. Want an owner per row too? add