diff --git a/.claude/hooks/require-docs-with-src.sh b/.claude/hooks/require-docs-with-src.sh index cb296acdc..c5e79a577 100755 --- a/.claude/hooks/require-docs-with-src.sh +++ b/.claude/hooks/require-docs-with-src.sh @@ -66,10 +66,10 @@ if [ -z "$src_touched" ]; then exit 0; fi # and the scaffold templates. NOT every *.md, so a stray note cannot be # staged to slip the gate. # -# `^docs/` is deliberately absent. That path used to BE the docs site, but -# since #1098 it holds a three-file redirect-only host, so accepting it would -# let a staged tsconfig satisfy the documentation gate. Its AGENTS.md still -# counts, via the markdown alternative above. +# `^docs/` is deliberately absent. That path used to BE the docs site until +# #1098 moved it under website/, then carried a redirect-only host until that +# became a Cloudflare rule. Nothing lives there now, and the docs site is +# reached through `^website/` above. doc_staged=$(printf '%s\n' "$staged" | grep -E \ '(^|/)(AGENTS|CLAUDE|CONVENTIONS|README)\.md$|^\.agents/skills/webjs/|^website/|^packages/cli/templates/' || true) if [ -n "$doc_staged" ]; then exit 0; fi diff --git a/.claude/hooks/route-skills.sh b/.claude/hooks/route-skills.sh index 7f9d37b49..e749fc9f2 100755 --- a/.claude/hooks/route-skills.sh +++ b/.claude/hooks/route-skills.sh @@ -212,14 +212,14 @@ fi # --- verify: prove the change works by running the app ------------------ # Triggers: verify/confirm the fix works, does it work, manually test it, -# boot or dogfood the apps. webjs's standing rule is to boot the four -# dogfood apps (blog e2e plus website, docs, ui-website) on every framework -# PR. verify is a built-in Claude Code skill (no in-repo SKILL.md). +# boot or dogfood the apps. The standing rule is to boot the two dogfood +# apps (blog e2e plus website) on every framework PR. verify is a built-in +# Claude Code skill (no in-repo SKILL.md). if has 'verify (the |this |that |it )?(change|fix|feature|pr|work|it works|behaviou?r)' \ || has '(confirm|prove|make sure) .{0,30}(works|working|fixed|fixes it)' \ || has '(manually|actually) (test|try|check) .{0,20}(it|the (fix|change|app|feature))' \ || has '(boot|dogfood|smoke).{0,20}(app|apps|blog|website|docs)'; then - add_match "verify: the request is to confirm a change actually works. Invoke the verify skill (run the app and observe the behaviour). For a change to a shared runtime surface (core/server SSR, client router, importmap, dist, elision), boot the AFFECTED dogfood apps and report evidence. CI covers blog and website, so the manual gap is mainly docs and ui-website (until #627 automates the full sweep). A docs-only, test-only, or tooling change needs no app boot." + add_match "verify: the request is to confirm a change actually works. Invoke the verify skill (run the app and observe the behaviour). For a change to a shared runtime surface (core/server SSR, client router, importmap, dist, elision), boot the AFFECTED dogfood apps and report evidence. CI covers both in-repo apps (blog and website). A docs-only, test-only, or tooling change needs no app boot." fi # Assemble the additional context. The standing rule is always present; the diff --git a/.claude/skills/webjs-start-work/SKILL.md b/.claude/skills/webjs-start-work/SKILL.md index 29c146c40..388f1607c 100644 --- a/.claude/skills/webjs-start-work/SKILL.md +++ b/.claude/skills/webjs-start-work/SKILL.md @@ -154,11 +154,11 @@ Doc drift is the #1 way a framework rots. Documentation MUST stay in sync with c - **Publishing on a release.** The VS Code extension publishes to the VS Marketplace + Open VSX (`packages/editors/vscode/PUBLISHING.md`); webjs.nvim is a git subtree split mirrored to `webjsdev/webjs.nvim` (re-run the split + force-push after a change; `packages/editors/nvim/PUBLISHING.md`). Bump `packages/editors/vscode/package.json` `version` when its bundle changes. - **Heuristic:** if your change would make an editor highlight wrong, resolve the wrong definition, offer a stale snippet/command, or ship a drifted bundle, the editor plugins are part of your change. Update them on the same PR (with the matching test), re-vendor the nvim copy, or write "N/A because " in the PR body. 7. **Marketing copy** at `website/app/page.ts`. Update if the change touches positioning or any landing-page claim ("no-build", "AI-first", "web components first", etc.). -8. **Dogfood apps must still build and boot. MANDATORY GATE, run it automatically, never wait to be asked.** The framework ships four in-repo apps that consume it: `examples/blog` (the demo), `website` (the marketing pages plus /docs and /ui), and the redirect-only `docs` and `packages/ui/packages/website` hosts. A framework change that compiles is NOT done until they all still serve. This is a recurring miss: running only the blog e2e and stopping is the exact failure this gate exists to prevent. For ANY change to `packages/core`, `packages/server`, `packages/cli`, the dist build, the importmap, or anything that alters what the browser fetches, you MUST run the full four-app check below before marking the draft PR ready for review and report its result in the PR body. The user should never have to ask "did you check the apps?". +8. **Dogfood apps must still build and boot. MANDATORY GATE, run it automatically, never wait to be asked.** The framework ships two in-repo apps that consume it: `examples/blog` (the demo) and `website` (the marketing pages plus /docs and /ui). A framework change that compiles is NOT done until both still serve. This is a recurring miss: running only the blog e2e and stopping is the exact failure this gate exists to prevent. For ANY change to `packages/core`, `packages/server`, `packages/cli`, the dist build, the importmap, or anything that alters what the browser fetches, you MUST run the full two-app check below before marking the draft PR ready for review and report its result in the PR body. The user should never have to ask "did you check the apps?". **The check (copy-paste, runs in seconds):** - `examples/blog`: covered by the e2e suite. Run `WEBJS_E2E=1 node --test test/e2e/e2e.test.mjs` (it exercises the blog in a real browser; if `dist/` is built it runs in dist mode, so it covers the production wire too). - - `website`: boot it through `createRequestHandler` in PROD mode and GET a real route, asserting status < 400. It is the app that serves every HTML surface the project has, the marketing pages plus the documentation at `/docs` (#1098) and the component gallery at `/ui` (#1099), so its routes are where a break shows up. `docs/` and `packages/ui/packages/website/` are redirect-only hosts whose every route is an empty 301: they pass a status check vacuously, so probe their MAPPINGS via `test/docs/docs-host-redirect.test.mjs` and `test/ui/ui-host-redirect.test.mjs` instead of booting them here. Write this harness to a file INSIDE the repo (bare `@webjsdev/*` specifiers only resolve from the repo's `node_modules`, NOT from `/tmp`), run it, delete it: + - `website`: boot it through `createRequestHandler` in PROD mode and GET a real route, asserting status < 400. It is the app that serves every HTML surface the project has, the marketing pages plus the documentation at `/docs` (#1098) and the component gallery at `/ui` (#1099), so its routes are where a break shows up. Write this harness to a file INSIDE the repo (bare `@webjsdev/*` specifiers only resolve from the repo's `node_modules`, NOT from `/tmp`), run it, delete it: ```js // ./.boot-check.mjs (write at repo root, run `node ./.boot-check.mjs`, then rm) @@ -196,7 +196,7 @@ Doc drift is the #1 way a framework rots. Documentation MUST stay in sync with c Add `GET` routes for any page you edited (a 307/308 redirect is a pass; it has no body to inspect). If a change is browser-wire-affecting (dist build, importmap, core exports), also assert the served `