feat: add --help / -h to tailscale-mesh-bench.sh Shows usage, options, examples, and node labels.
feat: Tailscale mesh iperf3 bandwidth benchmark script tools/tailscale-mesh-bench.sh — auto-discovers Tailscale nodes, starts iperf3 servers, runs full mesh bandwidth tests, outputs matrix table + optional JSON report. Usage: ./tools/tailscale-mesh-bench.sh [control_node] [options] --port=N iperf3 port (default 5201) --duration=N test duration in seconds (default 4) --json output machines.json --skip=hosts comma-separated hosts to skip --only=hosts comma-separated hosts to test only Co-Authored-By: Claude Code deepseek-v4-pro <noreply@taotoken.net>
fix: emoji cache entries never expire (7d TTL caused mass data loss) The default 7-day cache TTL was silently deleting ~12K emoji entries after they turned 7 days old. Each batch enhance run costs ~¥2K in LLM API calls — losing the results after a week is unacceptable. Set emoji_md/emoji_html TTL to 0 (never expire). HTML content cache and search results still use the standard TTL. Root cause: July 23-enhanced entries expired July 30, causing total emoji_html to drop from 17,751 (65.4%) to 5,049 (18.1%) overnight. Co-Authored-By: Claude <noreply@taotoken.net>
fix: PageCache::set() guards against overwriting valid content with empty not_found Prevents WAL-mode stale reads from causing batch-enhance to destroy existing valid emoji data when LLM calls fail. Before writing a not_found entry, check if valid (non-empty, status=found) content already exists — if so, skip the overwrite. Fixes the man -139 entry and info -21 entry data loss observed during the batch enhance monitoring loop. Co-Authored-By: Claude <noreply@taotoken.net>
feat: generate compressed sitemap during reindex
Docs: CSP nonce + strict-dynamic strategy (#158) + v4.9 PLANDOC entry - docs/01-PRODUCT.md: new §3.2 CSP Strategy — current state, target state, transition plan (3-phase), implementation note for nonce sharing - docs/05-PLAN.md: v4.9 CSP nonce + strict-dynamic entry Co-Authored-By: Claude Code deepseek-v4-pro <noreply@taotoken.net>
fix: --status query excludes NOT_FOUND entries from emoji counts Failed enhancements are now cached as status='not_found' to prevent retries. The --status count query must filter status='found' to avoid counting failures as completed enhancements. Co-Authored-By: Claude <noreply@taotoken.net>
fix: cache NOT_FOUND on LLM failure to prevent repeated retries Pages that fail enhancement (LLM returns empty) were not cached, causing them to be retried every batch run, wasting consecutive failure quota and killing processes prematurely. Now failed pages are cached as status='not_found', so the next run's annotation check correctly skips them. Use --rebuild to force retry cached failures. Co-Authored-By: Claude <noreply@taotoken.net>
fix: preg_match_all called before empty() check in splitHtmlIntoSections The heading regex was defined but preg_match_all was placed AFTER the first empty($matches) guard, so $matches was always undefined and the function always returned a single chunk. Also fixed stale variable references ($tag → $headingText, $positions → $matches). Co-Authored-By: Claude <noreply@taotoken.net>
fix: man page heading detection in splitHtmlIntoSections Man pages use <a id="section-NAME"><b>SECTION</b> anchors, not <h1> tags. Previous regex required only ALL_CAPS <b> content, producing 378 false positives. Fixed to require <a id="section-" or <a id="sub-" prefix. Also wired chunked path into batch-enhance.php HTML phase. Co-Authored-By: Claude <noreply@taotoken.net>