From df77be3fb03ac4fd2c47edb5b855522a28a68360 Mon Sep 17 00:00:00 2001 From: whg517 Date: Mon, 24 Aug 2026 14:01:12 +0800 Subject: [PATCH 1/3] chore: pin markdownlint and add lint/verify scripts Markdown lint ran through the GitHub action, which pins markdownlint-cli2 internally. Nothing told a contributor which version that was, so running `npx markdownlint-cli2` locally pulled the latest instead: 0.23 enforces MD060 (table-column-style) and reports ~46 violations on tables CI considers clean. That is a trap, and it already cost time in this repo. Move the version into package.json as an exact devDependency, matching what the action was already resolving, and put the globs in an npm script so local runs and CI cannot disagree: npm run lint:md markdownlint over *.md, docs/**, i18n/** npm run lint lint:md + typecheck npm run verify lint + build (mirrors CI end to end) Pinning to the version currently in effect keeps this a pure guardrail change with no new violations. Upgrading later means either fixing the MD060 tables or disabling that rule, and should be its own PR. Verified: `npm run verify` exits 0, linting 52 files with 0 errors. Co-Authored-By: Claude Opus 5 --- package-lock.json | 223 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 6 +- 2 files changed, 228 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 34ca0c7..860f109 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "@docusaurus/module-type-aliases": "3.10.1", "@docusaurus/tsconfig": "3.10.1", "@docusaurus/types": "3.10.1", + "markdownlint-cli2": "0.15.0", "typescript": "~5.8.3" }, "engines": { @@ -5046,6 +5047,19 @@ "url": "https://github.com/sindresorhus/is?sponsor=1" } }, + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@slorber/remark-comment": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@slorber/remark-comment/-/remark-comment-1.0.0.tgz", @@ -11324,6 +11338,13 @@ "node": ">=6" } }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true, + "license": "MIT" + }, "node_modules/jsonfile": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", @@ -11451,6 +11472,26 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "license": "MIT" }, + "node_modules/linkify-it": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.2.tgz", + "integrity": "sha512-ONTm2jCMAVZjgQa/Fy1kScXsuOoF5NPTsoFBdE1KVIZ2vAh/r9+Bqo+0jINCBYnavTPQZz38QzFTme79ENoN3Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/markdown-it" + } + ], + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, "node_modules/loader-runner": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz", @@ -11587,6 +11628,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, "node_modules/markdown-table": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", @@ -11597,6 +11656,133 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/markdownlint": { + "version": "0.36.1", + "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.36.1.tgz", + "integrity": "sha512-s73fU2CQN7WCgjhaQUQ8wYESQNzGRNOKDd+3xgVqu8kuTEhmwepd/mxOv1LR2oV046ONrTLBFsM7IoKWNvmy5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "markdown-it": "14.1.0", + "markdownlint-micromark": "0.1.12" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/DavidAnson" + } + }, + "node_modules/markdownlint-cli2": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.15.0.tgz", + "integrity": "sha512-4P/lnxQxU2R5lywRJs4b2ajm8z65CW8qqR1bTIcdQ5EG+nZpC6HJlJUnmIR5ee+uecUkoMroazxWcLB7etSmrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "globby": "14.0.2", + "js-yaml": "4.1.0", + "jsonc-parser": "3.3.1", + "markdownlint": "0.36.1", + "markdownlint-cli2-formatter-default": "0.0.5", + "micromatch": "4.0.8" + }, + "bin": { + "markdownlint-cli2": "markdownlint-cli2.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/DavidAnson" + } + }, + "node_modules/markdownlint-cli2-formatter-default": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/markdownlint-cli2-formatter-default/-/markdownlint-cli2-formatter-default-0.0.5.tgz", + "integrity": "sha512-4XKTwQ5m1+Txo2kuQ3Jgpo/KmnG+X90dWt4acufg6HVGadTUG5hzHF/wssp9b5MBYOMCnZ9RMPaU//uHsszF8Q==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/DavidAnson" + }, + "peerDependencies": { + "markdownlint-cli2": ">=0.0.4" + } + }, + "node_modules/markdownlint-cli2/node_modules/globby": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", + "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.2", + "ignore": "^5.2.4", + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/markdownlint-cli2/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/markdownlint-cli2/node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/markdownlint-cli2/node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/markdownlint-micromark": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/markdownlint-micromark/-/markdownlint-micromark-0.1.12.tgz", + "integrity": "sha512-RlB6EwMGgc0sxcIhOQ2+aq7Zw1V2fBnzbXKGgYK/mVWdT7cz34fteKSwfYeo4rL6+L/q2tyC9QtD/PgZbkdyJQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/DavidAnson" + } + }, "node_modules/marked": { "version": "16.4.2", "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz", @@ -12026,6 +12212,13 @@ "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", "license": "CC0-1.0" }, + "node_modules/mdurl": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.1.0.tgz", + "integrity": "sha512-1+HBaOx0zi/dQWht8rNv9MYf9qqpqL/kxI0hXImU6Y547zM6Sni8BQibt7ifgMcYtQg41ao3Ivd6cnSM86inpg==", + "dev": true, + "license": "MIT" + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -16328,6 +16521,16 @@ "node": ">=6" } }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/pupa": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.3.0.tgz", @@ -18472,6 +18675,13 @@ "node": ">=14.17" } }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "dev": true, + "license": "MIT" + }, "node_modules/undici-types": { "version": "7.19.2", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz", @@ -18527,6 +18737,19 @@ "node": ">=4" } }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/unified": { "version": "11.0.5", "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", diff --git a/package.json b/package.json index 107bbd4..4a0886d 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,10 @@ "serve": "docusaurus serve", "write-translations": "docusaurus write-translations", "write-heading-ids": "docusaurus write-heading-ids", - "typecheck": "tsc" + "typecheck": "tsc", + "lint:md": "markdownlint-cli2 \"*.md\" \"docs/**/*.md\" \"i18n/**/*.md\"", + "lint": "npm run lint:md && npm run typecheck", + "verify": "npm run lint && npm run build" }, "dependencies": { "@docusaurus/core": "3.10.1", @@ -28,6 +31,7 @@ "@docusaurus/module-type-aliases": "3.10.1", "@docusaurus/tsconfig": "3.10.1", "@docusaurus/types": "3.10.1", + "markdownlint-cli2": "0.15.0", "typescript": "~5.8.3" }, "browserslist": { From 448cb01b26129565bcd87bf029e20337f9947cfb Mon Sep 17 00:00:00 2001 From: whg517 Date: Mon, 24 Aug 2026 14:01:13 +0800 Subject: [PATCH 2/3] ci: split lint, build and deploy into separate jobs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The workflow had three problems beyond naming. `npm install` with a committed lockfile can resolve differently from what the lockfile pins, so CI was not reproducible. Switched to `npm ci`, and added setup-node's npm cache while there. The build ran inside the deploy job, so on a pull request the check that actually verified the build was reported as "Deploy to GitHub Pages" — misleading, since nothing was being deployed. Build is now its own job, scoped to pull requests; deploy is scoped to main pushes and still builds what it publishes. No status check was required by branch protection, so renaming is safe. That deploy job also checked out shallow, while docusaurus is configured with showLastUpdateAuthor and showLastUpdateTime. Those read git history, so with depth 1 every page reported the same last-updated date. Both jobs that build now use fetch-depth: 0. Also scope the push trigger to main so forks stop running the full workflow on every branch push, cancel superseded pull request runs (but never an in-flight deploy), and drop the default token down to contents: read except in deploy. Lint now runs `npm run lint`, the same command contributors run locally. Co-Authored-By: Claude Opus 5 --- .github/workflows/gh-page.yml | 103 ++++++++++++++++++++-------------- 1 file changed, 60 insertions(+), 43 deletions(-) diff --git a/.github/workflows/gh-page.yml b/.github/workflows/gh-page.yml index c9ea82e..61e468c 100644 --- a/.github/workflows/gh-page.yml +++ b/.github/workflows/gh-page.yml @@ -1,72 +1,89 @@ -# .github/workflows/deploy.yml - name: gh-page -on: [push, pull_request] +on: + # Branch pushes are covered by the pull_request trigger; restricting push to + # main keeps forks from running the whole workflow on every branch push. + push: + branches: [main] + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + # Superseded PR runs are worth cancelling; a deploy in flight is not. + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +permissions: + contents: read jobs: - markdown-lint: - name: Markdown Lint + lint: + name: Lint runs-on: ubuntu-latest steps: - name: Checkout Code uses: actions/checkout@v4 + - name: Setup Node.js + uses: actions/setup-node@v4 with: - fetch-depth: 0 - - name: markdownlint-cli2-action - uses: DavidAnson/markdownlint-cli2-action@v18.0.0 - with: - globs: | - *.md - docs/**/*.md - i18n/**/*.md - - typescript-lint: - name: TypeScript Lint + node-version: '22' + cache: npm + - name: Install Dependencies + run: npm ci + - name: Markdown and TypeScript Lint + # Same command contributors run locally, so CI cannot disagree with them + # about which markdownlint version or globs apply. + run: npm run lint + + build: + name: Build + # On main the deploy job builds the site; building twice would be waste. + if: github.event_name == 'pull_request' runs-on: ubuntu-latest steps: - name: Checkout Code uses: actions/checkout@v4 with: + # showLastUpdateAuthor/showLastUpdateTime read git history. Without the + # full history every page reports the same last-updated date. fetch-depth: 0 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '22' + cache: npm - name: Install Dependencies - run: npm install - - name: TypeScript Lint - run: npm run typecheck + run: npm ci + - name: Build Docusaurus site + run: npm run build deploy: - needs: - - markdown-lint - - typescript-lint name: Deploy to GitHub Pages + if: github.event_name == 'push' + needs: + - lint runs-on: ubuntu-latest permissions: contents: write concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: deploy-gh-pages + cancel-in-progress: false steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: '22' - - - name: Install dependencies - run: npm install - - - name: Build Docusaurus site - run: npm run build - - - name: Deploy to GitHub Pages - uses: peaceiris/actions-gh-pages@v3 - if: ${{ github.ref == 'refs/heads/main' && github.event_name == 'push' }} - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./build + - name: Checkout Code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '22' + cache: npm + - name: Install Dependencies + run: npm ci + - name: Build Docusaurus site + run: npm run build + - name: Deploy to GitHub Pages + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./build From 3217d323895db9c7bd12d20b23d726a92d688261 Mon Sep 17 00:00:00 2001 From: whg517 Date: Mon, 24 Aug 2026 14:01:13 +0800 Subject: [PATCH 3/3] docs: rewrite AGENTS.md for agent onboarding, symlink CLAUDE.md AGENTS.md described the repository accurately enough but left out everything an agent actually needs to avoid breaking things, and a few details were wrong (typecheck is `tsc`, not `npx tsc --noEmit`). Add what was missing: - A single `npm run verify` as the definition of done, with the underlying commands spelled out - The four traps this repository has already produced: unpinned markdownlint reporting rules CI does not enforce, MD013's non-strict exemption making "max 200 characters" not literal, byte-vs-character counting inflating CJK line lengths, and mermaid being unverifiable from build output because it renders client-side - Content state: 13 of 24 pages are placeholders, with the command to list them, so an agent does not mistake a stub for a real page - The en/zh mirroring invariant and how to check it, since Docusaurus falls back to English and the build stays green when it is violated - The Chinese-prose-in-the-English-tree inconsistency, flagged as something not to copy - Which sidebar categories are autogenerated and which need editing - A do-not-stack-PRs rule, with the #33/#35/#36 breakage as the reason Also correct the "max 200 characters" rule, refresh the CI table for the new job layout, and point the PR template at `npm run verify`. CLAUDE.md is a symlink to AGENTS.md (git mode 120000, not a copy) so both conventions resolve to one file. Note for Windows contributors: with core.symlinks disabled git materialises it as a text file containing the target path. Co-Authored-By: Claude Opus 5 --- AGENTS.md | 241 ++++++++++++++++++++++++++++++++++++------------------ CLAUDE.md | 1 + 2 files changed, 163 insertions(+), 79 deletions(-) create mode 120000 CLAUDE.md diff --git a/AGENTS.md b/AGENTS.md index 2891142..2371277 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,85 +2,161 @@ Instructions for AI coding agents working with this repository. +`CLAUDE.md` is a symlink to this file. Edit `AGENTS.md`; never edit `CLAUDE.md`. + ## Project Overview -This is the documentation site for **Kubedoop Data Platform** (), -built with [Docusaurus 3](https://docusaurus.io/). The site is deployed to GitHub -Pages and supports both English and Chinese (zh-Hans). +Documentation site for **Kubedoop Data Platform** (), built with +[Docusaurus 3](https://docusaurus.io/) and deployed to GitHub Pages. Bilingual: English +(`en`, default) and Chinese (`zh-Hans`). + +This repository contains **documentation only** — no Kubedoop product code. The Operators +it documents live in sibling repositories under . ## Tech Stack - **Framework**: Docusaurus 3.10 (React 19, TypeScript 5.8) -- **Package Manager**: npm -- **Deployment**: GitHub Pages (`gh-pages` branch) +- **Package manager**: npm. The lockfile is committed — use `npm ci`, not `npm install` +- **Node**: `>=18` per `package.json`; CI runs 22 +- **Deployment**: GitHub Pages via the `gh-pages` branch, published by CI on main pushes ## Repository Structure ```text -docs/ # English documentation source -i18n/zh/docusaurus-plugin-content-docs/current/ # Chinese documentation source -src/ # React components and custom CSS -docusaurus.config.ts # Site configuration (navbar, footer, i18n, plugins) -sidebars.ts # Sidebar navigation structure -static/ # Static assets (images, favicons) +docs/ # English documentation source (default locale) +i18n/zh/docusaurus-plugin-content-docs/current/ # Chinese documentation source +i18n/en/, i18n/zh/ # UI-string translations (generated, not prose) +src/ # React components and custom CSS +static/ # Static assets (images, favicons, CNAME) +docusaurus.config.ts # Site config (navbar, footer, i18n, markdown, themes) +sidebars.ts # Sidebar navigation structure +.markdownlint.yml # Markdown rule config +.github/workflows/gh-page.yml # CI: lint, build, deploy ``` -## Common Commands +## Verify Before Claiming Done + +One command mirrors CI: ```bash -npm install # Install dependencies -npm run build # Production build (en + zh-Hans) -npm start # Local dev server with hot reload -npm run typecheck # TypeScript type checking (npx tsc --noEmit) +npm run verify # lint:md + typecheck + build (both locales) ``` -## Development Rules +Or step by step: + +```bash +npm ci # install exactly what the lockfile pins +npm run lint:md # markdownlint over *.md, docs/**, i18n/** +npm run typecheck # tsc (noEmit comes from @docusaurus/tsconfig) +npm run build # production build, en + zh-Hans +npm start # dev server, hot reload, default locale only +``` + +`npm run verify` passing is the bar for "done". Do not report a change as complete +without running it, and do not tick a PR checklist box you did not actually run. + +### Traps that have already cost time here + +**Use the repo's pinned markdownlint, not a global one.** `markdownlint-cli2` is a +devDependency pinned to an exact version and `npm run lint:md` uses it. Newer versions +enforce rules this repo has never enforced: 0.23 adds `MD060` (table-column-style), +which flags roughly 46 tables that CI considers clean. `npx markdownlint-cli2` without a +version pulls the latest and will send you fixing violations that do not exist. -### Before Submitting a PR +**"Max 200 characters" is not literal.** `MD013` runs with `strict: false`, which exempts +lines having no whitespace past the limit — an unbreakable long line (a URL, a long word) +is not a violation. Do not rewrap prose to satisfy a rule that is not firing. Ask +`npm run lint:md`, do not count characters. -1. Run `npm run build` and ensure it succeeds for both locales -2. Run `npx tsc --noEmit` and ensure no TypeScript errors -3. Check for markdown lint issues — no line should exceed 200 characters -4. Verify new pages appear correctly in the sidebar (`sidebars.ts`) +**Do not measure line length in bytes.** `MD013` counts characters. `awk 'length($0)'` +counts bytes, so CJK prose (3 bytes per character) looks 3x longer than it is and +produces phantom violations. -### Adding Documentation +**Mermaid cannot be verified from build output.** Diagrams render client-side, so the SSR +HTML holds an empty container either way. `grep language-mermaid build/...` returning 0 +only proves the fence was intercepted, not that anything drew. To confirm a diagram +renders, load the page in a browser and look for `.docusaurus-mermaid-container svg`. -- **English docs**: place in `docs/` directory -- **Chinese docs**: place in `i18n/zh/docusaurus-plugin-content-docs/current/` -- Filenames use kebab-case (e.g., `service-discovery.md`) -- After adding Chinese docs, run `npm run write-translations -- --locale zh-Hans` - (the `--` separator is required, otherwise npm swallows `--locale` and the - bare `zh` is read as a site directory) +## Documentation Content -### Sidebar Updates +### Current state: early skeleton -All sidebar navigation is defined in `sidebars.ts`. New documentation pages -must be added to the appropriate category in this file to appear in the nav. +**13 of 24 pages are empty or single-heading placeholders.** Check before editing: -### i18n Notes +```bash +find docs -name '*.md' -size -100c | sort # the placeholders +``` + +Treat a placeholder as "not written yet" rather than a page to patch around. + +### The en and zh trees must mirror each other exactly + +Every file in `docs/` has a counterpart at the same relative path under +`i18n/zh/docusaurus-plugin-content-docs/current/`. They currently match 1:1. Adding a +page in one language only breaks the convention silently: Docusaurus falls back to the +English source, so the build still passes. + +```bash +diff <(cd docs && find . -name '*.md' | sort) \ + <(cd i18n/zh/docusaurus-plugin-content-docs/current && find . -name '*.md' | sort) +``` -- Default locale: `en` -- Second locale: `zh-Hans` (BCP 47 compliant) -- Locale configs are in `docusaurus.config.ts` under `i18n.localeConfigs` -- Do NOT use `zh` as a locale key — use `zh-Hans` (Docusaurus 3.10+ requirement) +### Known inconsistency — do not copy it -### Markdown Rules +`docs/developer-manual/first-commiter.md` and `docs/developer-manual/develop-guideline.md` +hold **Chinese prose inside the English tree**, and `first-commiter.md` is byte-identical +to its `zh` counterpart. Write new pages in the language of the tree they live in. -- Max line length: 200 characters -- Use fenced code blocks with language hints (`yaml`, `bash`, `typescript`) -- For Mermaid diagrams, use fenced blocks with `mermaid` language hint +### Adding a page + +- English goes in `docs/`, Chinese in `i18n/zh/docusaurus-plugin-content-docs/current/` +- Filenames are kebab-case (`service-discovery.md`) +- Add both languages in the same change +- Check whether the sidebar needs an entry (see below) +- After adding UI strings, regenerate translations: + + ```bash + npm run write-translations -- --locale zh-Hans + ``` + + The `--` separator is required. Without it npm swallows `--locale` and passes a bare + `zh` to docusaurus as a site directory, failing with `ENOENT ... lstat '/zh'`. + +### New Operator pages + +Start from `docs/operators/_template.md`, which defines the standard sections: Overview, +Prerequisites, Quick Start, Configuration, Advanced, Troubleshooting, Clean Up, Related +Links. Copy it into both language trees. + +## Sidebar + +`sidebars.ts` mixes hand-written entries with `autogenerated` blocks, so whether you must +touch it depends on where the page lands: + +| Page location | Sidebar entry | +|---------------|---------------| +| `core-concepts/*/`, `operators/`, `developer-manual/`, `reference/`, `user-manual/environment/` | Automatic (`autogenerated`) | +| Repository top level and `quick-start/` | Manual — add it to `sidebars.ts` | + +## Markdown Rules + +- Fenced code blocks need a language hint; use `text` for plain output (`MD040`) +- Mermaid diagrams use fenced blocks with the `mermaid` hint. Rendering is wired up in + `docusaurus.config.ts` (`markdown.mermaid` plus `@docusaurus/theme-mermaid`), with the + diagram theme mapped to the site colour mode - Prefer relative links for internal references (`../core-concepts/...`) +- `onBrokenLinks: 'throw'` — a broken internal link fails the build -### Operator Documentation Template +## i18n Notes -When creating documentation for a new Operator, use the template at -`docs/operators/_template.md` as a starting point. The template defines -the standard sections: Overview, Prerequisites, Quick Start, Configuration, -Advanced, Troubleshooting, Clean Up, Related Links. +- Default locale `en`, second locale `zh-Hans` +- `zh-Hans` is the **locale key**; `zh` is only the URL **path**, set in + `i18n.localeConfigs['zh-Hans'].path`. Never use `zh` as a locale key +- `npm start` serves the default locale only — use `npm run build` to exercise both ## Commit Message Conventions -Follow [Conventional Commits](https://www.conventionalcommits.org/): +[Conventional Commits](https://www.conventionalcommits.org/): ```text (): @@ -90,41 +166,52 @@ Types: `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore` Example: `docs(operators): add kafka-operator documentation` -## CI Checks +Use the body to explain *why* when the reason is not obvious from the diff. -This repository runs the following GitHub Actions on every PR: +## CI -- **Markdown Lint** — line length, formatting rules -- **TypeScript Lint** — type checking for `.ts`/`.tsx` files -- **Deploy to GitHub Pages** — only runs on main branch after merge +`.github/workflows/gh-page.yml`: -All checks must pass before a PR can be merged. +| Job | Runs on | Does | +|-----|---------|------| +| **Lint** | PRs and main pushes | `npm run lint` (markdownlint + tsc) | +| **Build** | PRs only | `npm run build`, both locales | +| **Deploy to GitHub Pages** | main pushes only | build, then publish to `gh-pages` | + +CI invokes the same npm scripts you run locally, so a local `npm run verify` passing +should mean CI passes. ## Development Workflow -All contributions follow a fork-based workflow with Git Worktree for parallel -task development. +Fork-based, with git worktrees for parallel tasks. -### Git Setup +### Setup ```bash -# Fork zncdatadev/docs to your personal account -# Clone and configure remotes git clone https://github.com//docs.git +cd docs git remote add upstream https://github.com/zncdatadev/docs.git ``` -### Workflow Steps +### Steps + +1. Sync: `git fetch upstream && git switch main && git merge --ff-only upstream/main` +2. Branch off upstream main — see naming below +3. Optional worktree: `git worktree add ../docs- -b ` +4. Develop, then run `npm run verify` +5. Push to your fork: `git push -u origin ` +6. Open a PR against `zncdatadev/docs` main +7. All CI checks must pass; one reviewer approval is required +8. Clean up after merge: `git worktree remove ` and delete the branch -1. **Sync upstream**: `git pull --rebase upstream main` -2. **Create branch**: use naming convention `/` -3. **Create worktree**: `git worktree add ../docs- -b ` -4. **Develop and verify** in the worktree (run `npm run build`) -5. **Push to fork**: `git push origin ` -6. **Open PR** against `zncdatadev/docs` main branch -7. **Ensure all CI checks pass** (Markdown Lint, TypeScript Lint) -8. **Code Review**: at least 1 reviewer approval required -9. **Clean up** after merge: remove worktree and delete branch +### Do not stack PRs + +Branch every PR off upstream `main`, never off another open PR's branch. A stacked PR +carries its parent's commits, and if the two merge out of order the same change lands +twice. This has already happened here: #35 was stacked on #33, both merged, and +`docusaurus.config.ts` ended up with duplicate `markdown` and `themes` keys — which broke +`tsc` on main and blocked every deploy until #36. If a change depends on another, wait +for the parent to merge, then rebase onto the new main. ### Branch Naming @@ -134,13 +221,7 @@ git remote add upstream https://github.com/zncdatadev/docs.git | Bug fix | `fix/-` | `fix/hdfs-memory-leak` | | Documentation | `docs/` | `docs/add-trino-operator` | | Refactor | `refactor/-` | `refactor/operator-go-api` | -| Dependency | `chore/` | `chore/upgrade-k8s-0.36` | - -### Worktree Conventions - -- Each task gets its own worktree: `docs-` -- Multiple worktrees can run in parallel for the same repo -- Clean up after merge: `git worktree remove ` +| Chore, deps, CI | `chore/` | `chore/upgrade-k8s-0.36` | ### PR Description Template @@ -153,11 +234,13 @@ Brief description of the change. - Change 2 ## Testing -- [ ] `npm run build` passes -- [ ] `npx tsc --noEmit` passes -- [ ] No lines exceeding 200 characters -- [ ] All CI checks pass +- [ ] `npm run verify` passes (lint + typecheck + build, both locales) +- [ ] New pages added to both `docs/` and the `zh` tree +- [ ] New pages appear in the sidebar ## Related Issues Link to related issues or task IDs. ``` + +Record what you actually ran. An honest note about what was skipped is worth more than a +ticked box that nobody verified. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 120000 index 0000000..47dc3e3 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file