Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
54ad439
trademark stuff added
EricAndrechek Aug 17, 2026
dfe3ada
Merge branch 'main' of github.com:Wave-RF/WaveHouse into docs-cloud-r…
EricAndrechek Aug 17, 2026
c93ae12
no premature new line splits, tabitem fencing and codeblocks fixed
EricAndrechek Aug 18, 2026
4c2eb80
Merge branch 'main' of github.com:Wave-RF/WaveHouse into docs-cloud-r…
EricAndrechek Aug 18, 2026
fc01c57
build(lint): autofix hard-wrapped prose and MDX fences at write time
EricAndrechek Aug 18, 2026
4929f7f
fix(lint): stop WH001 corrupting tables, setext headings, and MDX ESM
EricAndrechek Aug 18, 2026
b276661
Merge remote-tracking branch 'origin/main' into docs-cloud-refer
EricAndrechek Aug 18, 2026
9cb4bb0
fix(lint): stop WH001 writing markdownlint's masked buffer back to disk
EricAndrechek Aug 18, 2026
ca1545a
docs(changelog): correct three claims in the cloud-CTA entry
EricAndrechek Aug 18, 2026
8fc1c3f
fix(docs): address CodeRabbit review on #489
EricAndrechek Aug 19, 2026
e32c6d9
fix(docs): correct WH002's rationale — MDX renders a glued fence fine
EricAndrechek Aug 19, 2026
e513251
fix(lint): scope the on-save hook to the repo, keep WH001's hard breaks
EricAndrechek Aug 19, 2026
85a1bcd
docs(changelog): separate the reflow from the one content deletion
EricAndrechek Aug 19, 2026
3c8a625
docs(changelog): drop the sentence pair duplicated by the last split
EricAndrechek Aug 19, 2026
a6b30e9
fix(lint): reject non-opening tags in WH002 multiline detection
EricAndrechek Aug 19, 2026
d97cd5e
fix(lint): mask attribute values before WH002 validates an opening tag
EricAndrechek Aug 19, 2026
ac62a5f
fix(lint): collapse nested braces to a fixpoint in the WH002 tag test
EricAndrechek Aug 19, 2026
9600e13
fix(lint): never run the generic markdownlint fixers over MDX
EricAndrechek Aug 19, 2026
b601b2b
docs: reconcile every description with MDX no longer being auto-fixed
EricAndrechek Aug 19, 2026
6f52f48
fix(lint): glob MDX on lint:md so a bare --fix cannot reach it
EricAndrechek Aug 19, 2026
26f237c
docs: point every description at the config glob, and align the prose…
EricAndrechek Aug 19, 2026
5ed4fae
docs(components): correct the stale sizing note in ExternalIcon
EricAndrechek Aug 19, 2026
c450678
docs(makefile): reconcile the DOCS_PROSE comments with the widened scope
EricAndrechek Aug 19, 2026
c685aea
docs: fixture the last three classify() branches, document authoring …
EricAndrechek Aug 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .claude/.markdownlint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "../.markdownlint.json",
"WH001": false
}
78 changes: 78 additions & 0 deletions .claude/hooks/markdown-on-save.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/usr/bin/env bash
# PostToolUse hook: auto-fix Markdown/MDX after edits — the same fixers `make
# fix` runs, narrowed to the one file just written.
#
# Why a hook (vs leaving it to `make fix` or CI): these are deterministic,
# mechanical corrections — unwrapping hard-wrapped prose (WH001), inserting the
# blank line an MDX fence needs beside a JSX tag (WH002), common typos and
# US spelling. Catching them at write time means an agent's own output is
# already correct, instead of costing a lint failure and a second pass to fix
# by hand. Sibling of gofumpt-on-save.sh, which does the same for Go.
#
# Deliberately NOT wired into .githooks/pre-commit: a commit hook that rewrites
# and re-stages files silently changes what you reviewed and fights `git add -p`.
# The commit hook stays a check; this fixes early enough that it rarely fires.
#
# Order is load-bearing — see scripts/fix-mdx-fences.mjs for why the MDX
# structural pass must precede markdownlint.
#
# Safety: best-effort throughout. A missing tool, an unparseable file, or a
# lint error that has no fix leaves the file alone and never blocks the edit.

set -uo pipefail

input=$(cat)
file_path=$(echo "$input" | jq -r '.tool_input.file_path // empty' 2>/dev/null)

case "$file_path" in
*.md | *.mdx) ;;
*) exit 0 ;;
esac
[ -f "$file_path" ] || exit 0

cd "${CLAUDE_PROJECT_DIR:-.}" 2>/dev/null || exit 0

# markdownlint-cli2 resolves globs (and per-directory config) from the repo
# root, so hand it a repo-relative path.
rel="${file_path#"$PWD"/}"

# `rel` stays ABSOLUTE exactly when the strip above failed — i.e. the file is
# not under the project root. Bail there: this repo's Markdown conventions have
# no business rewriting agent memory files under ~/.claude/, scratch notes in
# /tmp, or Markdown in an unrelated checkout, all of which a session routinely
# writes. (Sibling worktrees are already covered by the `ignores` in
# .markdownlint-cli2.jsonc, which cli2 honors even for a named file.)
case "$rel" in
/*) exit 0 ;;
esac

# Phase 1: MDX structure. Must land before any generic fixer sees the file.
if [ "${rel##*.}" = "mdx" ]; then
node scripts/fix-mdx-fences.mjs "$rel" >/dev/null 2>&1 || true
fi

# Phase 2: markdownlint (style + WH001 unwrapping). `--no-globs` keeps it to
# this one file instead of the whole repo; a nonzero exit just means something
# unfixable remains (e.g. a fence with no language), which CI will report.
#
# Twice, mirroring `fix:md` in package.json: WH001's insert carries the pre-fix
# text of the lines it joins, so another rule's fix for a joined line is dropped
# on the first pass. One pass would leave behind an issue `make fix` would have
# cleared — the exact round-trip this hook exists to avoid, in the common case
# where WH001 fires.
if [ -x node_modules/.bin/markdownlint-cli2 ]; then
node_modules/.bin/markdownlint-cli2 --no-globs --fix ":$rel" >/dev/null 2>&1 || true
node_modules/.bin/markdownlint-cli2 --no-globs --fix ":$rel" >/dev/null 2>&1 || true
fi

# Phase 3: spelling, over docs prose only — the same scope `make lint-prose`
# uses, resolved by the canonical script rather than a second copy of the list.
if scripts/docs-prose.sh is-match "$rel" 2>/dev/null; then
for misspell in .bin/*/misspell-*; do
[ -x "$misspell" ] || continue
"$misspell" -locale US -source text -w "$rel" >/dev/null 2>&1 || true
break
done
fi

exit 0
4 changes: 4 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/gofumpt-on-save.sh"
},
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/markdown-on-save.sh"
}
]
}
Expand Down
4 changes: 4 additions & 0 deletions .github/.markdownlint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "../.markdownlint.json",
"WH001": false
}
26 changes: 23 additions & 3 deletions .markdownlint-cli2.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,24 @@
// `astro build` (CI, via `make ci` → build-docs), the single source of truth
// for broken links. See docs/astro.config.mjs.
//
// NOTE: .mdx is intentionally NOT linted — markdownlint parses CommonMark, not
// MDX's JSX/import syntax (docs/src/content/docs/index.mdx).
// .mdx IS linted, with a caveat worth knowing: markdownlint parses CommonMark,
// not MDX, so it reads JSX as HTML blocks. That turns out to be a feature —
// when a fence is glued to a <TabItem> (see WH002) the fence stops being a
// code block and the rules light up — which is exactly the hazard we want
// caught, since it is what makes a generic --fix rewrite the code.
// It also means generic `--fix` must never run first on such a file — the
// rules would "fix" code that only looks like prose — so scripts/fix-mdx-fences.mjs
// repairs the structure before this config's fix pass. See `fix:md` in package.json.
//
// customRules live here and nowhere else — the VS Code extension reads this
// file too, so no editor-side setting is needed (markdownlint.customRules is
// deprecated in favor of this file). Note the editor only activates on
// Markdown, so .mdx gets no squiggles either way; CI and `make fix` cover it:
// WH001 prose paragraphs must not be hard-wrapped (autofix: joins them)
// WH002 MDX fence adjacent to a JSX tag needs a blank line (fixed in phase 1)
// Both are enabled in .markdownlint.json. WH001 is turned off for CI docs and
// agent prompts by .github/.markdownlint.json and .claude/.markdownlint.json,
// and applies everywhere else — a narrower exclusion than scripts/docs-prose.sh.
//
// markdownlint-cli2 globs with dot:true, so `**/*.md` descends into hidden
// dirs — including .worktrees/, where this repo nests git worktrees. Honor
Expand All @@ -23,7 +39,11 @@
// (`--fix`) never rewrites another branch's files. The explicit ignores below
// stay as a fallback for the case where .gitignore is absent.
"gitignore": true,
"globs": ["**/*.md"],
"globs": ["**/*.md", "**/*.mdx"],
"customRules": [
"./scripts/markdownlint-rules/no-hard-wrapped-prose.mjs",
"./scripts/markdownlint-rules/mdx-fence-needs-blank-line.mjs"
],
"ignores": [
"**/node_modules/**",
"**/dist/**",
Expand Down
4 changes: 3 additions & 1 deletion .markdownlint.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@
"MD024": { "siblings_only": true },
"MD033": false,
"MD041": false,
"MD060": false
"MD060": false,
"WH001": true,
"WH002": true
}
26 changes: 23 additions & 3 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,21 @@
"editor.tabSize": 2,
// Apply markdownlint's auto-fixes on save — mirrors `make fix` / `pnpm run
// fix:md`. The DavidAnson.vscode-markdownlint extension and the CLI both read
// the same .markdownlint.json (rules) + .markdownlint-cli2.jsonc (globs), so
// the editor and CI stay in lockstep.
// the same .markdownlint.json (rules) + .markdownlint-cli2.jsonc (globs AND
// customRules — so no setting is needed here; markdownlint.customRules is
// deprecated in favor of exactly that file), so the editor and CI stay in
// lockstep for Markdown.
//
// Not for MDX: the extension activates on the `markdown` language ID only,
// and .mdx is not associated with it, so WH001 squiggles in .md alone and
// WH002 — which only applies to .mdx — never squiggles at all. `make fix`
// and .claude/hooks/markdown-on-save.sh are the MDX path. Associating .mdx
// with markdown would be the wrong fix: it would turn on the fix-on-save
// below for MDX and reintroduce the ordering hazard described next.
//
// WH002's autofix is owned by scripts/fix-mdx-fences.mjs, not by fix-on-save:
// it must run before the generic rules, which the editor cannot order. Save
// shows the squiggle; `make fix` (or the markdown-on-save hook) repairs it.
"editor.codeActionsOnSave": {
"source.fixAll.markdownlint": "explicit"
}
Expand All @@ -88,7 +101,14 @@
"markdown.validate.fileLinks.enabled": "ignore",
"markdown.validate.fileLinks.markdownFragmentLinks": "ignore",
"markdown.validate.fragmentLinks.enabled": "warning",
"markdown.validate.referenceLinks.enabled": "warning",
// Off, not "warning": Starlight asides are `:::note[Title]`, and the validator
// reads that trailing `[Title]` as a shortcut reference link with no
// definition — ~40 false positives across the docs, one per aside, plus a few
// more where it parses MDX JSX props the same way. This repo defines no
// reference-style links at all, so the check has nothing true to say here.
// (markdownlint's equivalent, MD052, stays quiet for its own reason: its
// shortcut_syntax option is off by default. Editor and CLI agree.)
"markdown.validate.referenceLinks.enabled": "ignore",
"markdown.validate.unusedLinkDefinitions.enabled": "warning",
"markdown.validate.duplicateLinkDefinitions.enabled": "warning",

Expand Down
24 changes: 22 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ make ci # Full pre-push pipeline — run it the documented way (
make build # Compile → bin/wavehouse
make dev # ClickHouse + hot-reload server on :8080 (Docker)
make deps-up # Start ClickHouse alone — for `make dev`; NOT needed by `make ci`
make dev-docs # Prod-faithful docs dev loop: rebuild-on-save + wrangler dev on :4321
make dev-docs # Prod-faithful docs dev loop: rebuild-on-save + wrangler dev on :4321 (next free port if busy)
make build-docs # Production build → docs/dist/
make preview-docs # Wrangler preview of the production build (auto-builds if dist/ missing)
make branding-docs # Regenerate logo/favicon/OG assets from docs/src/assets/branding/mark.svg
Expand All @@ -113,7 +113,7 @@ Tooling notes (the non-obvious bits `make help` won't tell you):
- `golangci-lint` is pinned in the Makefile (v2.11.4), auto-installed to `.bin/` on first `make lint` — kept out of `go.mod` (its deps conflict with the main module).
- `pnpm` (≥ 11.21) + `Node 22 LTS` (`.nvmrc`, matches CI) must be on PATH; `make tools` runs one root `pnpm install --frozen-lockfile` across the three workspaces (SDK `clients/ts/`, E2E `tests/e2e/sdk/`, docs `docs/`).
- **GNU Make 4+** required (uses `--output-sync=target`); macOS BSD Make 3.81 won't parse it. Full setup: `docs/src/content/docs/development.md` § Prerequisites.
- **Lint split**: Biome owns JS/TS/JSON, markdownlint owns Markdown *style*, misspell owns spelling (all under `make lint`/`make fix`); accuracy/clarity/doc-sync is the `docs-reviewer` gate (§Docs review).
- **Lint split**: Biome owns JS/TS/JSON, markdownlint owns Markdown *and MDX* style — including two repo-local rules, WH001 (no hard-wrapped prose) and WH002 (MDX fence beside a JSX tag) in `scripts/markdownlint-rules/` — misspell owns spelling (all under `make lint`/`make fix`); accuracy/clarity/doc-sync is the `docs-reviewer` gate (§Docs review). See §Markdown authoring rules.
- **Worktrunk** (`wt`, `.config/wt.toml`): `wt switch --create` seeds `.bin/` + `node_modules/` from main, then runs `make tools`.

## Testing Conventions
Expand Down Expand Up @@ -321,6 +321,26 @@ Source-of-truth pairs that must agree:

Before finishing a task, grep for the identifiers you touched (field names, env var names, endpoint paths) across docs to catch staleness.

### Markdown authoring rules

- **Never hard-wrap prose. One paragraph is one line.** No wrapping at 72/80 columns, no "semantic linefeeds" splitting a paragraph at sentence boundaries. Wrapped prose makes every later edit rewrap the whole block, so a one-word change lands as a five-line diff. Enforced by WH001 (`scripts/markdownlint-rules/no-hard-wrapped-prose.mjs`), which autofixes. Tables (with or without leading pipes), code, headings, setext underlines, blockquotes, JSX, multi-line MDX `import`/`export`, and `:::` aside delimiters are left alone; a list item is joined as a unit, marker line included; an aside's *body* is joined but its delimiters are not.
- **In MDX, leave a blank line between a JSX tag and a code fence.** MDX itself renders the glued form correctly — verified by compiling both shapes with the same `@mdx-js/mdx` Astro uses. The blank line is what keeps *markdownlint* agreeing with it: markdownlint parses CommonMark, where `<TabItem …>` opens an HTML block that runs to the next blank line, so a glued fence is not a code block to any generic rule and `markdownlint --fix` will reformat the code inside it:

````mdx
<TabItem label="YAML">

```yaml
data_dir: ./data
```

</TabItem>
````

Enforced by WH002. The autofix is `scripts/fix-mdx-fences.mjs`, which must run *before* markdownlint — while the blank line is missing CommonMark sees no code block, so generic rules will "fix" the code inside it. `make fix` and the agent hook already order it correctly; don't call `markdownlint-cli2 --fix` on MDX by hand.
- **Editors see WH001 in `.md` only.** The markdownlint extension reads `.markdownlint-cli2.jsonc`, `customRules` included, so no `.vscode` setting is needed (`markdownlint.customRules` is deprecated in favor of that file). But it activates on the `markdown` language ID, and `.mdx` is not associated with it — so WH002 never squiggles in the editor, and WH001 squiggles only in `.md`. Don't "fix" that with a `files.associations` entry: it would enable `source.fixAll.markdownlint` on `.mdx` and reintroduce the ordering hazard above. `make fix` and the agent hook are the MDX path.
- **These fix themselves as you write.** `.claude/hooks/markdown-on-save.sh` (PostToolUse, sibling of `gofumpt-on-save.sh`) runs the MDX pass, markdownlint `--fix`, and misspell on each `.md`/`.mdx` you write, so an agent's output is corrected in the same pass rather than costing a lint failure and a manual cleanup. It only sees `Edit`/`Write`/`MultiEdit` — a file written through a Bash heredoc bypasses it, so run `make fix` after doing that.
- **WH001 is off under `.github/` and `.claude/`** (CI docs and agent prompts) via their own `.markdownlint.json`. It applies everywhere else, `AGENTS.md` and `CHANGELOG.md` included — so this is a narrower exclusion than `scripts/docs-prose.sh`, which also skips those two.

### Authoring Mermaid diagrams

Diagrams render inside the Starlight content column (~46–58rem wide) as build-time SVG via `astro-themed-mermaid`, themed by `docs/src/config/mermaid-theme.mjs`. **Author them vertically so they fit the page at a legible size** — the single most common diagram mistake here is a wide left-to-right flowchart that gets scaled down to fit the column until its labels are unreadable.
Expand Down
Loading