From 7348bbcd20749cc8f0789cf0bcd4c06ba40b9c83 Mon Sep 17 00:00:00 2001 From: Yevheniia Sorokina Date: Tue, 22 Sep 2026 10:44:24 +0100 Subject: [PATCH] Delete the function my own fix orphaned, and pin display-name uniqueness The previous commit replaced frontmatterOnly's only shQuiet call with execFileSync and left shQuiet defined, called by nothing - and left the call-site comment reading "see the note on shQuiet". So the next reader is told stderr suppression comes from a function that no longer participates, goes looking for it, and finds dead code; and if they "restore" the call they reintroduce the shell-string interpolation of a git-derived path that the same commit removed on purpose. Deleted, and the comment now says what actually suppresses the noise: stdio ["ignore", "pipe", "ignore"], and why that noise exists at all - a file the PR ADDS has no base blob, so git prints a fatal line per new page and forty of them ahead of the gate's output reads as a crash rather than as forty new pages. `display` is a map key in four places - FRAMEWORK_URL_PATH and FRAMEWORK_SLUG in SkillsCallout, FRAMEWORK_DISPLAY_TO_SLUG in utils/frameworks.ts, and the features/products/skills cross-check in verify-frameworks.cjs - and its own doc comment says so. Nothing enforced that it is unique, while `slug` uniqueness was pinned. A duplicate is easy to introduce from a copy-pasted entry, Object.fromEntries silently keeps the last one, and SkillsCallout would then build the OTHER framework's agent-skills link and report the wrong framework to analytics - with verify:frameworks still green, because it only asks whether a display is IN the registry, never whether it appears once. Now pinned, and mutation-checked: duplicating a display fails the new row. test:frameworks 17 passed, test:docs-gate 37 passed, verify:frameworks OK, tsc clean. Co-Authored-By: Claude Opus 5 (1M context) --- scripts/docs-gate/index.cjs | 22 ++++++++-------------- scripts/test-frameworks.cjs | 21 +++++++++++++++++++++ 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/scripts/docs-gate/index.cjs b/scripts/docs-gate/index.cjs index 4da0d5fca0..ea21d7332b 100644 --- a/scripts/docs-gate/index.cjs +++ b/scripts/docs-gate/index.cjs @@ -17,18 +17,6 @@ function sh(cmd) { return execSync(cmd, { encoding: "utf8", stdio: ["ignore", "pipe", "inherit"] }).trim(); } -/** - * Like sh(), but for a lookup whose failure is EXPECTED and meaningless. - * - * `git show :` cannot succeed for a file the PR adds, and sh() - * inherits git's stderr on purpose, so a PR adding forty pages printed forty - * `fatal: path ... exists on disk, but not in ...` lines before the gate said - * anything - which reads as a crashed gate rather than as forty new files. - */ -function shQuiet(cmd) { - return execSync(cmd, { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim(); -} - function changedDocs() { // Ratchet against the PR's target branch, not a hardcoded main — so a PR into // release/** diffs against that release branch, not main's fork point. @@ -157,14 +145,20 @@ function frontmatterOnly(files, base) { for (const f of files) { let before; try { - // shQuiet: a file the PR ADDS has no base blob, and that failure is - // both expected and meaningless here - see the note on shQuiet. // execFileSync with an argv, not a shell string: `f` is a path from git // output, and interpolating it into a command line is a class of bug // rather than a present one. No doc path in the repo carries a shell // metacharacter today, and a failure here falls back to "treat as // body-changed", which is the safe direction - so this removes the class // rather than fixing a symptom. + // + // The `"ignore"` on stderr is what keeps the output readable: a file the + // PR ADDS has no base blob, so git prints `fatal: path ... exists on + // disk, but not in ...` for every one of them. That failure is expected + // and meaningless here - the catch below treats the file as body-changed, + // which is correct for a new file - but forty of those lines ahead of the + // gate's own output reads as a crashed gate rather than as forty new + // pages. before = execFileSync("git", ["show", `${base}:${f}`], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], diff --git a/scripts/test-frameworks.cjs b/scripts/test-frameworks.cjs index b40e8b5c59..f5d13eeb32 100644 --- a/scripts/test-frameworks.cjs +++ b/scripts/test-frameworks.cjs @@ -252,4 +252,25 @@ check("every registry slug is unique", () => { assert.strictEqual(new Set(slugs).size, slugs.length); }); +// `display` is load-bearing in the same way `slug` is, and was pinned in +// neither place. FRAMEWORK_URL_PATH and FRAMEWORK_SLUG (SkillsCallout), +// FRAMEWORK_DISPLAY_TO_SLUG (utils/frameworks.ts) and the +// features/products/skills cross-check in verify-frameworks.cjs all key off it. +// +// A duplicate is easy to introduce - a copy-pasted entry whose display was not +// updated - and Object.fromEntries silently keeps only the last, so SkillsCallout +// would build the OTHER framework's agent-skills link and report the wrong +// framework to analytics. verify-frameworks stays green through all of it, +// because it only ever asks whether a display is IN the registry, never whether +// it appears once. +check("every registry display name is unique", () => { + const displays = registry.FRAMEWORKS.map((f) => f.display); + const dupes = displays.filter((d, i) => displays.indexOf(d) !== i); + assert.deepStrictEqual( + dupes, + [], + `display names must be unique - they are map keys. Duplicated: ${dupes.join(", ")}`, + ); +}); + console.log(`\n${passed} passed\n`);