From b40a758d4e7614e582bf6ce850a24b12364cb318 Mon Sep 17 00:00:00 2001 From: Mobeen Abdullah Date: Sun, 13 Sep 2026 19:43:51 +0300 Subject: [PATCH] fix(root): the scheduled metadata check loads nothing an install would provide scripts/check-repo-metadata.mjs runs in repo-metadata.yml, a scheduled job that installs nothing. It imported the retired-category patterns from check-docs-claims.mjs, which imports @mdx-js/mdx and, through check-docs-compile.mjs, js-yaml. Every scheduled run since 2026-09-11 has died with ERR_MODULE_NOT_FOUND before checking anything. The patterns and their classifier move verbatim into scripts/retired-category.mjs, which imports nothing. check-repo-metadata.mjs imports it directly; check-docs-claims.mjs imports and re-exports it, so there is still one definition and every existing importer keeps its path. --- scripts/check-docs-claims.mjs | 42 ++++++-------------------- scripts/check-repo-metadata.mjs | 2 +- scripts/retired-category.mjs | 53 +++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 34 deletions(-) create mode 100644 scripts/retired-category.mjs diff --git a/scripts/check-docs-claims.mjs b/scripts/check-docs-claims.mjs index d195e972d1..d402914fbf 100644 --- a/scripts/check-docs-claims.mjs +++ b/scripts/check-docs-claims.mjs @@ -31,6 +31,11 @@ import { basename, dirname, extname, join, relative, sep } from "node:path"; import { compile } from "@mdx-js/mdx"; import { splitFrontmatter } from "./check-docs-compile.mjs"; +import { + RETIRED_CATEGORY, + RETIRED_CATEGORY_TAG, + namesRetiredCategory, +} from "./retired-category.mjs"; /** * Files come from git's index, not from a directory walk. @@ -232,41 +237,12 @@ export function context7Findings(config, coreDescription) { } /** - * The category the project moved away from. - * - * A hyphen or whitespace between the words, because the repository has spelled - * it both ways and a reader sees no difference, and an optional plural, because - * "one of several app frameworks" is the same claim about the same category. - */ -export const RETIRED_CATEGORY = /\bapp(?:-|\s+)frameworks?\b/i; - -/** - * The same category, as a whole tag rather than a phrase in prose. + * The retired-category patterns and their classifier, defined in `retired-category.mjs`. * - * npm keywords and GitHub topics are both single tokens on a surface people search, and both - * were left carrying `framework` after the prose was cleared. The word is the one the whole - * repositioning turned on: it could mean an application framework, a UI framework or a backend - * framework, which made it the least informative word available. - * - * `RETIRED_CATEGORY` cannot serve here — it requires the `app` prefix, so a bare `framework` - * tag would pass. Anchored rather than substring-matched: `page-builder` and `nextly-plugin` - * are tags this must never touch. + * Re-exported so an importer of this module keeps a path to them, while a job that cannot install + * packages imports the dependency-free module directly instead of this one. */ -export const RETIRED_CATEGORY_TAG = /^(?:app-)?frameworks?$/i; - -/** - * The single answer to "does this tag name the retired category", for every tag surface. - * - * A tag can carry the category two ways, and one pattern cannot see both: as the whole tag - * (`framework`), or with the phrase embedded in a longer one (`nextjs-app-framework`). Two - * checks used to answer this for npm keywords — the prose check matched the phrase, the - * keyword check matched the whole tag — so a keyword like `app-framework` was reported twice - * under two names, and their patterns were free to drift apart. This is now the only answer, - * shared by npm keywords and GitHub topics. - */ -export function namesRetiredCategory(tag) { - return typeof tag === "string" && (RETIRED_CATEGORY_TAG.test(tag) || RETIRED_CATEGORY.test(tag)); -} +export { RETIRED_CATEGORY, RETIRED_CATEGORY_TAG, namesRetiredCategory }; /** * The keywords npm derives from a manifest, which is not always the keywords it was given. diff --git a/scripts/check-repo-metadata.mjs b/scripts/check-repo-metadata.mjs index b34a1bd03b..78d1d12216 100644 --- a/scripts/check-repo-metadata.mjs +++ b/scripts/check-repo-metadata.mjs @@ -23,7 +23,7 @@ import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { RETIRED_CATEGORY, namesRetiredCategory } from "./check-docs-claims.mjs"; +import { RETIRED_CATEGORY, namesRetiredCategory } from "./retired-category.mjs"; const OWNER = "nextlyhq"; const REPO = "nextly"; diff --git a/scripts/retired-category.mjs b/scripts/retired-category.mjs new file mode 100644 index 0000000000..b733ce8ca0 --- /dev/null +++ b/scripts/retired-category.mjs @@ -0,0 +1,53 @@ +/** + * The category the project moved away from, as two patterns and one classifier, with no imports. + * + * Its own module, and importing nothing, because a job that installs no packages loads it. The + * scheduled repository-metadata check runs straight after checkout — the GitHub About line and the + * topic list are repository settings rather than files, so only a scheduled run can observe them — + * and any module in that check's import closure that reaches for an npm package fails the job + * before it examines anything. + * + * Kept apart from the docs-claims check, which compiles MDX: the metadata check needs these three + * definitions and nothing else, and must not load a compiler to get them. There is still exactly + * one definition — the docs-claims check imports and re-exports it rather than restating it. + * + * `no-install-jobs.test.mjs` holds the property for every script a workflow starts without + * installing: its whole import graph must be Node builtins. + */ + +/** + * The category the project moved away from. + * + * A hyphen or whitespace between the words, because the repository has spelled + * it both ways and a reader sees no difference, and an optional plural, because + * "one of several app frameworks" is the same claim about the same category. + */ +export const RETIRED_CATEGORY = /\bapp(?:-|\s+)frameworks?\b/i; + +/** + * The same category, as a whole tag rather than a phrase in prose. + * + * npm keywords and GitHub topics are both single tokens on a surface people search, and both + * were left carrying `framework` after the prose was cleared. The word is the one the whole + * repositioning turned on: it could mean an application framework, a UI framework or a backend + * framework, which made it the least informative word available. + * + * `RETIRED_CATEGORY` cannot serve here — it requires the `app` prefix, so a bare `framework` + * tag would pass. Anchored rather than substring-matched: `page-builder` and `nextly-plugin` + * are tags this must never touch. + */ +export const RETIRED_CATEGORY_TAG = /^(?:app-)?frameworks?$/i; + +/** + * The single answer to "does this tag name the retired category", for every tag surface. + * + * A tag can carry the category two ways, and one pattern cannot see both: as the whole tag + * (`framework`), or with the phrase embedded in a longer one (`nextjs-app-framework`). Two + * checks used to answer this for npm keywords — the prose check matched the phrase, the + * keyword check matched the whole tag — so a keyword like `app-framework` was reported twice + * under two names, and their patterns were free to drift apart. This is now the only answer, + * shared by npm keywords and GitHub topics. + */ +export function namesRetiredCategory(tag) { + return typeof tag === "string" && (RETIRED_CATEGORY_TAG.test(tag) || RETIRED_CATEGORY.test(tag)); +}