From 400fe902e027cc449201800d38eb0819399f7ed9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Thu, 24 Sep 2026 13:08:45 +0000 Subject: [PATCH] :recycle: Run doc-test generation as an explicit CI step Drop the `pretest:ci` lifecycle hook and call `create:doc-tests` from the `build` job before `test:ci`. The hook hid the step from the job log and made `test:ci` behave differently under npm than when run directly. --- .gitea/workflows/ci.yml | 4 ++++ AGENTS.md | 2 +- CONTRIBUTING.md | 4 ++-- development/docs.md | 4 ++++ package.json | 1 - src/doc-test/README.md | 4 ++-- 6 files changed, 13 insertions(+), 6 deletions(-) diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index b5b93fb..fe72d2f 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -77,6 +77,10 @@ jobs: - run: npm ci - run: npm run build - run: npm run check + # Compile the prose examples into gitignored tests. Kept as an + # explicit step (not a `pretest:ci` hook) so it is visible in the + # job log and `test:ci` stays a plain command. + - run: npm run create:doc-tests # Fails the build below 100% coverage on `src/` (`c8 --all --100`); # the same run produces the report published below. See # development/ci.md § Coverage threshold. diff --git a/AGENTS.md b/AGENTS.md index 8d78f8a..3ca0553 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,7 +11,7 @@ first-action facts. Do not restate evolving prose here — it will drift. - **While iterating:** `npm run test` (`check:tsc` + the unit suite) for fast feedback on the files you changed. - **Optional code intelligence:** this repo installs `@spences10/pi-lsp` (pinned in `.pi/settings.json`) as a project-local pi extension. It talks to the repo's own TypeScript 7 via `tsc --lsp --stdio` and exposes **read-only** tools — `lsp_hover`, `lsp_definition`, `lsp_references`, `lsp_find_symbol`, `lsp_document_symbols`, `lsp_diagnostics(_many)`. **When you are looking for a symbol, reach for the LSP before `rg`/`grep`** — `lsp_references` / `lsp_find_symbol` / `lsp_definition` / `lsp_document_symbols` are semantic and cross-file, so they see shadowing, imports and overloads that a text search cannot; use `lsp_hover` to read inferred types on generic-heavy code. Use `rg` for what the LSP cannot see — doc prose, string literals, config, task lists, file discovery — and reconcile the two sets before editing (symbols from the LSP, strings and prose from `rg`). It has no rename / code-action / apply-edit surface — the write side is pi's `edit` tool + `check:tsc`. Treat empty LSP output as _inconclusive_, not success: **`npm run test` / `npm run verify` remain the sole authoritative gate** (see the next bullet). The server keeps running across that gate with a ~5 min idle timeout and registers no file watchers, so if you change `tsconfig.json` / `package.json` mid-session its diagnostics can be stale — when LSP output disagrees with `check:tsc`, trust `check:tsc` and restart pi (or wait out the idle timeout) before concluding the LSP is wrong. - **Definition of done — run this before you call the work finished:** `npm run verify`. If all green, commit. If red, look at the output, fix the root cause, and re-run. -- **Touched a `ts`-tagged fence in `README.md` / `CONTRIBUTING.md`?** Run `npm run create:doc-tests` first: it regenerates the gitignored tests under `src/doc-test/__generated__/`, formats and type-checks them, so `verify` executes the documented example. CI does this automatically via `pretest:ci`; the fast local tiers do not. See [development/docs.md](./development/docs.md). +- **Touched a `ts`-tagged fence in `README.md` / `CONTRIBUTING.md`?** Run `npm run create:doc-tests` first: it regenerates the gitignored tests under `src/doc-test/__generated__/`, formats and type-checks them, so `verify` executes the documented example. CI runs it in an explicit step before `test:ci`; the fast local tiers do not. See [development/docs.md](./development/docs.md). - **On commit:** write a good message (see [CONTRIBUTING.md § Commit messages](./CONTRIBUTING.md#commit-messages)). Lefthook's pre-commit hook already runs the fast, offline, staged-file checks — don't run them by hand. If the hook fails on style, `npm run fix`, restage, recommit. - **Document decisions where the next maintainer will look:** rationale, rejected alternatives and known issues go in `development/.md` (see [development/README.md](./development/README.md)); the actionable rule stays in [CONTRIBUTING.md](./CONTRIBUTING.md) and links to it. Write each fact once — never copy the rule into `development/` or the reason into `CONTRIBUTING.md` — and change both in the same commit when a rule changes. - **`npm run maintain` is NOT part of the feature loop.** Its scans are advisory, never a gate; run them only on an explicit maintenance / update-deps branch. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0e07828..3afe51d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -96,8 +96,8 @@ executed test, so a documented example cannot drift from the API. Describe each fence with the paragraph directly above it (that text becomes the test title), and keep its library import self-contained; `npm run create:doc-tests` regenerates, formats and type-checks the tests under -`src/doc-test/__generated__/`. CI runs it automatically via `pretest:ci`, so run -it yourself before `npm run verify` when you touched a fence. Why: +`src/doc-test/__generated__/`. CI runs it in an explicit step before `test:ci`, +so run it yourself before `npm run verify` when you touched a fence. Why: [development/docs.md](./development/docs.md). ## Code style and formatting diff --git a/development/docs.md b/development/docs.md index 4a22084..590abc4 100644 --- a/development/docs.md +++ b/development/docs.md @@ -55,3 +55,7 @@ Compile every `ts / `typescript fence in the prose docs into a real (`git ls-files 'src/*.test.ts'` — the generated files are untracked), and `test:doc` runs the examples in a separate process without c8. `test:ci` chains the two, so correctness and coverage stay independent. +- The CI `build` job runs `npm run create:doc-tests` as an explicit step before + `npm run test:ci`, not a `pretest:ci` lifecycle hook: the hook hides the step + from the job log and makes `test:ci` behave differently under npm than when + run directly. diff --git a/package.json b/package.json index e9facd1..ea082e8 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,6 @@ "maintain:knip": "knip --include dependencies,exports,files", "maintain:outdated": "check-outdated --ignore-pre-releases --ignore-packages @types/node", "test": "npm run check:tsc && node --test --strip-types \"src/**/*.test.ts\"", - "pretest:ci": "npm run create:doc-tests", "test:ci": "npm run test:coverage && npm run test:doc", "test:coverage": "c8 --all --include \"src/**/*.ts\" --reporter=text --reporter=lcov --reporter=html --100 node --test --strip-types $(git ls-files 'src/*.test.ts')", "test:doc": "node --test --strip-types \"src/doc-test/__generated__/*.test.ts\"", diff --git a/src/doc-test/README.md b/src/doc-test/README.md index 3b46ec2..85d5364 100644 --- a/src/doc-test/README.md +++ b/src/doc-test/README.md @@ -7,6 +7,6 @@ formats them with `oxfmt`, then type-checks them with [`tsconfig.json`](./tsconfig.json) — the scoped config that relaxes `noUnusedLocals` so example-only locals (and the injected `assert`) compile. -CI regenerates them first via `pretest:ci`; the fast local `test` / `verify` -tiers do not. See [development/docs.md](../../development/docs.md) for why the +CI regenerates them in an explicit step before `test:ci`; the fast local `test` / +`verify` tiers do not. See [development/docs.md](../../development/docs.md) for why the generator is shaped this way.