fluffos/docs
Claude 3bdbe9676e www: real ws backpressure fix, teardown leak fix, src/www docs, websocket smoke test in CI
The lws output wedge addressed in the previous commit was incompletely
understood: under genuine backpressure (peer slow or paused, kernel
send buffer full) a connection still froze permanently. Root cause,
established by tracing the writeable-request plumbing end to end:
lws_send_pipe_choked() is true not only when lws holds a truncated
send (lws re-arms the writeable callback itself then) but also when a
zero-timeout poll(POLLOUT) reports the socket simply full -- and in
that case every lws_write() has fully succeeded, lws has nothing
pending, and nobody re-arms anything. Fix, per lws README.coding.md:
whenever the drain loop exits with data still queued in pss->buffer,
request the next writeable callback. Queued data always has a callback
requested, so no exit path can strand output.

Also:
- LWS_CALLBACK_CLOSED frees the session evbuffer unconditionally: on
  driver-initiated closes (e.g. the mudlib destructing the interactive)
  close_user_websocket() nulls pss->user first, and the old early
  return leaked the buffer every time.
- src/www/README.md + src/www/AGENTS.md: architecture doc and agent
  checklist for the web terminal pages (xterm.js/telnet.js layering,
  vendor policy, packaging, testing, the wedge mechanism).
- tools/ws-smoke.js, wired into CI on the Clang Debug matrix entries
  (with and without sanitizers): a dependency-free node websocket
  client that boots the real driver and exercises the http mount,
  telnet + ascii subprotocols through the shared src/www/telnet.js,
  SGA char-mode switching, live TUI streaming, TLS, and -- the actual
  regression gate -- forced-backpressure bursts (paused socket, ~4.8MB)
  on the plain and TLS ports plus a destruct-while-choked teardown
  check. All three backpressure checks fail on the unfixed driver;
  neither GTest nor the LPC suite exercises any websocket client
  traffic.
- Fix stale src/www/wasm/vendor/ path references left from the vendor
  directory move (src/wasm/README.md, docs/build-wasm.md, release.yml).

Validated on the ASan Debug build: forced-backpressure repros recover
the full burst on both subprotocols, destruct-while-choked clean under
ASan, ws-smoke 17/17, GTest 312/312, LPC testsuite clean.
2026-07-14 09:53:26 -05:00
..
apply docs: document call_out handle validity and mid-compile valid_read behavior (#1252) 2026-07-12 02:02:56 -04:00
archive Move to /docs folder 2018-12-30 17:03:14 -08:00
cli docs: fully-expandable generated sidebar + Chinese docs via Docusaurus i18n (#1246) 2026-07-11 17:20:25 -04:00
concepts/general docs: fully-expandable generated sidebar + Chinese docs via Docusaurus i18n (#1246) 2026-07-11 17:20:25 -04:00
driver docs: fully-expandable generated sidebar + Chinese docs via Docusaurus i18n (#1246) 2026-07-11 17:20:25 -04:00
efun docs: document call_out handle validity and mid-compile valid_read behavior (#1252) 2026-07-12 02:02:56 -04:00
i18n/zh-CN docs: validate "See Also" references, drop dead ones, document valid_ffi (#1251) 2026-07-12 01:09:17 -04:00
lpc vm: string foreach/ref fixes, buffers as byte arrays (foreach, strict bytes, to_buffer), thorough ref tests; #1196 docs follow-up (#1250) 2026-07-12 01:39:30 -04:00
src/css setup vitepress 2023-12-02 20:00:33 -08:00
static Add local search and documentation guide for docs site (#1221) 2026-07-09 22:09:55 -04:00
stdlib web terminals on xterm.js; TUI library fixes; emsdk pin; lws output-wedge fix 2026-07-14 09:53:26 -05:00
.gitignore Add local search and documentation guide for docs site (#1221) 2026-07-09 22:09:55 -04:00
add_missing_efuns.py Add local search and documentation guide for docs site (#1221) 2026-07-09 22:09:55 -04:00
bug.md Add local search and documentation guide for docs site (#1221) 2026-07-09 22:09:55 -04:00
build-wasm.md www: real ws backpressure fix, teardown leak fix, src/www docs, websocket smoke test in CI 2026-07-14 09:53:26 -05:00
build.mdx docs: fully-expandable generated sidebar + Chinese docs via Docusaurus i18n (#1246) 2026-07-11 17:20:25 -04:00
build_v2017.md Add local search and documentation guide for docs site (#1221) 2026-07-09 22:09:55 -04:00
CLAUDE.md docs: fully-expandable generated sidebar + Chinese docs via Docusaurus i18n (#1246) 2026-07-11 17:20:25 -04:00
docusaurus.config.ts docs: fully-expandable generated sidebar + Chinese docs via Docusaurus i18n (#1246) 2026-07-11 17:20:25 -04:00
gen_config_docs.py docs: fully-expandable generated sidebar + Chinese docs via Docusaurus i18n (#1246) 2026-07-11 17:20:25 -04:00
gen_sidebar.py docs: fully-expandable generated sidebar + Chinese docs via Docusaurus i18n (#1246) 2026-07-11 17:20:25 -04:00
index.mdx docs: fully-expandable generated sidebar + Chinese docs via Docusaurus i18n (#1246) 2026-07-11 17:20:25 -04:00
package-lock.json Add local search and documentation guide for docs site (#1221) 2026-07-09 22:09:55 -04:00
package.json Add local search and documentation guide for docs site (#1221) 2026-07-09 22:09:55 -04:00
README.md docs: fully-expandable generated sidebar + Chinese docs via Docusaurus i18n (#1246) 2026-07-11 17:20:25 -04:00
sidebar_meta.json docs: fully-expandable generated sidebar + Chinese docs via Docusaurus i18n (#1246) 2026-07-11 17:20:25 -04:00
sidebars.generated.json vm: string foreach/ref fixes, buffers as byte arrays (foreach, strict bytes, to_buffer), thorough ref tests; #1196 docs follow-up (#1250) 2026-07-12 01:39:30 -04:00
sidebars.ts vm: string foreach/ref fixes, buffers as byte arrays (foreach, strict bytes, to_buffer), thorough ref tests; #1196 docs follow-up (#1250) 2026-07-12 01:39:30 -04:00

FluffOS Documentation

This directory contains the source for the FluffOS documentation site, published at https://www.fluffos.info.

The site is built with Docusaurus 3 (@docusaurus/preset-classic). Markdown files live directly in this directory (the docs plugin is configured with path: '.' and routeBasePath: '/'), so docs/efun/strings/explode.md becomes /efun/strings/explode on the site.

This README is for contributors and is excluded from the published site (see exclude in docusaurus.config.ts).

Local Development

Requires Node.js 18+ (Node 22 recommended).

cd docs
npm install
npm run dev       # dev server on http://localhost:3000

Other scripts:

npm run build     # production build → docs/build/
npm run preview   # serve the production build locally
npm run clear     # clear the Docusaurus cache

Full-text search is provided by @easyops-cn/docusaurus-search-local, an offline/local search theme — the index is generated at build time and shipped with the site, so no external search service (e.g. Algolia) is needed.

Notes:

  • The search index is only generated by npm run build. In the dev server (npm run dev) the search bar shows a hint instead of results; use npm run build && npm run preview to test search locally.
  • Both English and Chinese pages are indexed (language: ['en', 'zh']).
  • Search options live in the themes section of docusaurus.config.ts.

Chinese docs (i18n)

The Chinese corpus lives under i18n/zh-CN/docusaurus-plugin-content-docs/current/, mirroring the English tree layout (a translation of docs/efun/arrays/allocate.md goes at i18n/zh-CN/docusaurus-plugin-content-docs/current/efun/arrays/allocate.md). The site serves it at /zh-CN/ with a locale dropdown in the navbar; untranslated pages automatically fall back to the English content.

  • Sidebar/navbar/footer label translations: i18n/zh-CN/docusaurus-plugin-content-docs/current.json and i18n/zh-CN/docusaurus-theme-classic/*.json. Rescaffold new keys with npx docusaurus write-translations --locale zh-CN after sidebar changes, then translate them.
  • The dev server runs one locale at a time: npm run dev -- --locale zh-CN.
  • npm run build builds both locales.

Layout

Path Contents
docusaurus.config.ts Site config: navbar, footer, docs plugin, search theme
sidebars.ts Sidebar skeleton; splices in the generated reference trees
sidebars.generated.json Generated sidebar trees for the reference docs (do not hand-edit)
sidebar_meta.json Curated sidebar labels, descriptions and ordering for the generated trees
src/css/custom.css Infima CSS variable overrides
static/ Files copied verbatim to the site root (CNAME, Google site verification)
apply/ Driver-to-LPC callback (apply) reference
efun/ Built-in function (efun) reference, by category
stdlib/ LPC standard-library reference
driver/ Driver internals & configuration
lpc/ LPC language reference
concepts/ High-level LPC / MUD concepts
cli/ Command-line tool docs
i18n/zh-CN/ Chinese translations (Docusaurus i18n; mirrors the English tree layout)
archive/ Historical MudOS-era documents (not published)

Maintenance scripts

Script Purpose
gen_sidebar.py Regenerates sidebars.generated.json from the reference doc trees + sidebar_meta.json (--check verifies freshness, used by CI)
gen_config_docs.py Regenerates driver/config.md from src/base/internal/rc.cc
add_missing_efuns.py Creates stub pages under efun/general/ for undocumented efuns (needs a keywords.json from the generate_keywords tool)

Conventions & Gotchas

  • driver/config.md is auto-generated from src/base/internal/rc.cc — never edit it by hand. Regenerate with python3 docs/gen_config_docs.py; CI fails if it is stale.
  • .md files are treated as standard CommonMark (markdown.format: 'detect'), but bare {...} in prose is still parsed as a JSX expression and breaks the build — escape it as \{...\} outside fenced code blocks.
  • Sidebar entries in sidebars.ts use doc IDs (relative path without extension), not URLs.
  • The reference trees (efun/apply/stdlib/cli/concepts/driver) have no index.md files: their sidebar trees live in sidebars.generated.json and their landing pages are Docusaurus generated-index card pages. After adding, removing, or moving a page in those trees, run ./gen_sidebar.py and commit the result — CI fails if it is stale. Category labels/descriptions/ordering are curated in sidebar_meta.json. lpc/index.md is hand-written and its sidebar is hand-authored in sidebars.ts.
  • The sidebar is shared by both locales; Chinese category labels come from i18n/zh-CN/docusaurus-plugin-content-docs/current.json, not from sidebar_meta.json.
  • onBrokenLinks is set to 'throw': a broken internal link fails the build (and the Pages deploy) instead of shipping a 404.

See CLAUDE.md for detailed documentation templates (applies, efuns, CLI tools) and the full contribution workflow.