车东 Che, Dong

Sun 19 July, 2026

22:45 feat: chunked LLM enhancement for large man pages (>200KB) » Recent Commits to phpman:master
feat: chunked LLM enhancement for large man pages (>200KB)

Pages exceeding PHPMAN_ENHANCE_CHUNK_THRESHOLD (default 200KB) are
automatically split into sections at h1/h2 heading boundaries, each
chunk independently enhanced via callLLM(), then reassembled.

Split strategy (failsafe cascade):
1. h1 section boundaries (NAME, SYNOPSIS, DESCRIPTION, etc.)
2. h2 sub-section boundaries within oversized sections
3. Paragraph/block boundaries (</p>, <br>, </li>, </dd>, etc.)
4. Sentence boundaries ($. + ' ') — last resort, never mid-sentence

Key guarantees:
- Never splits inside <pre>, <table>, <dl> blocks
- Parent heading preserved in every chunk for LLM context
- Failed chunks fall back to original HTML (graceful degradation)
- Each chunk capped at PHPMAN_ENHANCE_MAX_CHARS (32KB)

Co-Authored-By: Claude <noreply@taotoken.net>
16:57 docs: add architectural paradox — data sources are already CLI tools » Recent Commits to phpman:master
docs: add architectural paradox — data sources are already CLI tools

The man/perldoc/info/ri/pydoc3 data sources already have CLI interfaces.
phpMan's web layer (HTML rendering, format negotiation, emoji enhance)
is redundant for LLM Agent use cases. The only irreplaceable value:
TLDR cheatsheets + cross-mode FTS5 search.

Co-Authored-By: Claude <noreply@taotoken.net>
16:43 docs: strategic review — phpMan value in the LLM era (GEO/MCP/SEO ana… » Recent Commits to phpman:master
docs: strategic review — phpMan value in the LLM era (GEO/MCP/SEO analysis)

Key findings from production access log:
- AI bots prefer MCP/markdown over HTML (78-86% structured format choice)
- MCP is GPTBot's #1 format (437 > markdown 413 > html 297)
- Traditional SEO failed — Googlebot only 23 phpMan requests
- LLM emoji enhancement cost: ~¥2,170 total (), marginal value
- phpMan's strategic value shifted: human web viewer → AI agent API

Co-Authored-By: Claude <noreply@taotoken.net>

Wed 15 July, 2026

09:27 fix: deterministic PID file naming for multi-mode parallel batch-enhance » Recent Commits to phpman:master
fix: deterministic PID file naming for multi-mode parallel batch-enhance

Problem: restarting a batch process didn't clean up the old one
because PID file paths weren't derived from the same option combination.
Manual 'rm pidfile && nohup ...' bypassed the startup guard, creating
duplicate processes for the same mode.

Changes:
- buildPidFilePath(mode, format) — canonical path for any option combo
- 15 unique PID files: 5 modes × 3 formats (both/html/md)
- --force flag: auto-kills existing process with same PID file
- --yes also enables auto-cleanup (batch/cron friendly)
- --restart + --mode=man auto-finds /tmp/bm.pid (no need --pid-file)
- Old error message now suggests --force as an option

PID file naming:
  --mode=man                → /tmp/bm.pid
  --mode=man --format=html  → /tmp/bm_html.pid
  --mode=ri  --format=md    → /tmp/br_md.pid
  --pid-file=/custom.pid    → /custom.pid (explicit wins)

Co-Authored-By: Claude <noreply@taotoken.net>
05:03 docs: add batch-enhance.php CLI reference with --status to §2.12.1 » Recent Commits to phpman:master
docs: add batch-enhance.php CLI reference with --status to §2.12.1

Documents all options including --status, --stop, --restart,
--rebuild, --parameter, --format, --cached-first, --cache-only,
--rate-limit, --pid-file. Includes quick enhance shorthand,
full batch mode, and process management examples.

Co-Authored-By: Claude <noreply@taotoken.net>

Tue 14 July, 2026

00:24 docs: extract LLM enhancement + GA analytics to external projects » Recent Commits to phpman:master
docs: extract LLM enhancement + GA analytics to external projects

Following the 2026-07-14 architectural simplification, phpMan is now a
pure documentation server: man/perldoc/info/pydoc/ri → raw HTML/Markdown/
JSON/MCP, 0 LLM calls. Two capabilities move out to standalone repos.

docs/01-PRODUCT.md §2.12:
  Old "LLM Emoji Enhancement (v4.0)" (148 lines) replaced with a short
  "Moved to External Project" note listing what moved and why.

docs/05-PLAN.md:
  v4.10 entry replaced with "Superseded by External site-stats Project".
  v4.0 Phase 3 marked as shipped-then-moved-out.
  New "## Migration Plan: phpMan → llm_enhance + site_stats" section
  with 7 phases (A–G), source/transformation/sink abstractions, code
  migration map, 5-week schedule, rollback plan, 6 open questions.

docs/06-ANALYTICS.md:
  Rewritten as a STANDALONE multi-site service design (not a phpMan MCP
  tool). Pluggable DataSource (GA4 → Plausible later), 7 report
  categories, MCP + HTTP/JSON dual interface, phpMan is one consumer.

docs/00-INDEX.md:
  Reorganized to separate "External Projects (References)" from phpMan
  docs. Added "What phpMan Does NOT Do" table.

Companion issues opened: #222 (llm_enhance), #223 (site_stats),
#224 (phpMan v5.0 cleanup). Closed #216 (PATH_INFO guard bug, already
fixed by validatePathInfo() in earlier commit.

Co-Authored-By: AtomCode (minimax-m3) <noreply@atomgit.com>
EOF
)

Mon 13 July, 2026

21:13 fix: deploy src/ before phpMan.php to avoid transient 500 errors » Recent Commits to phpman:master
fix: deploy src/ before phpMan.php to avoid transient 500 errors

On 2026-07-13, deploying v4.9.26 to production caused 2 transient
HTTP 500 errors (Applebot requests at 20:19:46 and 20:19:48 PDT):

  PHP Fatal error:  Uncaught Error: Call to undefined function
  validatePathInfo() in /home/chedong/chedong.com/phpMan.php:106

Root cause: the Makefile deploy order uploaded phpMan.php (which calls
validatePathInfo) BEFORE src/util.php (which defines it). During the
~30 second window between the two rsync/scp operations, any request
to a Perl module URL hit the new phpMan.php with the old src/, returning
500 instead of 200/403.

Fix: swap the order in both _deploy-code (staging) and _release-code
(production) so src/ is uploaded first, then phpMan.php. Same
rsync/scp commands, just reordered.

The first v4.9.x release with a src/ function addition since the
multi-file split revealed this latent ordering bug. Before this, src/
files were unchanged on most deploys so the window never had a
mismatched function definition.

After fix: post-deploy window 7-13 20:19-20:42 (25 min) shows
- 676 successful phpMan.php responses (200/301/302)
- 2 expected 403s (sftp://, sftp:onedrive:gdocs: — correctly rejected)
- 0 new 500s after 20:19:50

Co-Authored-By: AtomCode (minimax-m3) <noreply@atomgit.com>
19:47 Merge SourceForge upstream (AdSense) + Perl module fix » Recent Commits to phpman:master
Merge SourceForge upstream (AdSense) + Perl module fix
19:42 fix: prevent PHP default_socket_timeout from preempting CURLOPT_TIMEOUT » Recent Commits to phpman:master
fix: prevent PHP default_socket_timeout from preempting CURLOPT_TIMEOUT

Add ini_set('default_socket_timeout', max(timeout+30, 900)) before
each LLM API call so the 600s primary / 300s fallback cURL timeouts
actually take effect. Previously default_socket_timeout=60s was
silently cutting off long-running requests.

Co-Authored-By: Claude <noreply@taotoken.net>
19:42 fix: allow valid Perl modules with multiple :: in 403 guard » Recent Commits to phpman:master
fix: allow valid Perl modules with multiple :: in 403 guard

The PATH_INFO 403 guard was rejecting any path segment with > 2 colons,
which wrongly blocked valid Perl module URLs like
/man/Dpkg::Control::HashCore (4 colons, two :: pairs) and
/perldoc/A::B::C::D::E (8 colons).

Replace the count-based check with a single-colon detector: only colons
that are NOT part of a '::' pair are treated as URI-scheme indicators.
This preserves the original protection against scanner probes
(sftp:onedrive:gdocs:) while allowing any depth of Perl package name.

- Extract the guard into testable validatePathInfo() in src/util.php
- Returns the failing condition name (tooLong/tooDeep/hasProto/
  hasProtocolColon) instead of just true/false
- Add test/unit/test_path_guard.php with 26 assertions covering:
  - Valid Perl modules at 1/2/3/4/5 :: pairs
  - C++ namespaces (std::string)
  - Rejection of sftp://, http://, sftp:onedrive:, Foo::Bar:Baz
  - Boundary cases for tooLong (100 chars) and tooDeep (5/6 segments)
- All 349 unit+integration tests pass
19:42 Restore PATH_INFO guard (ec489ee, lost in code split) + colons enhanc… » Recent Commits to phpman:master
19:42 Increase LLM timeout: primary 120→600s, fallback default 60→300s » Recent Commits to phpman:master
19:42 Add runtime process status to --status output » Recent Commits to phpman:master
19:42 Add log-analyze.sh — web access log analysis tool » Recent Commits to phpman:master
19:42 Add URL attack guard: reject malformed paths with protocol-prefix traps » Recent Commits to phpman:master
19:42 Add LLM gateway failure analysis report » Recent Commits to phpman:master
19:42 Add /status JSON endpoint for batch enhance process monitoring » Recent Commits to phpman:master
19:42 Add --restart option to batch-enhance.php » Recent Commits to phpman:master
19:41 fix: allow valid Perl modules with multiple :: in 403 guard » Recent Commits to phpman:master
10:13 Add /status JSON endpoint for batch enhance process monitoring » Recent Commits to phpman:master