slovo/scripts/check-stdlib-api-tiers.js

81 lines
2.7 KiB
JavaScript
Executable File

#!/usr/bin/env node
"use strict";
const fs = require("fs");
const path = require("path");
const repoRoot = path.resolve(__dirname, "..");
const catalogPath = path.join(repoRoot, "docs", "language", "STDLIB_API.md");
const catalog = fs.readFileSync(catalogPath, "utf8");
function fail(message) {
console.error(`stdlib API tier check failed: ${message}`);
process.exit(1);
}
function requireText(text, message) {
if (!catalog.includes(text)) {
fail(message);
}
}
function moduleSection(moduleName) {
const marker = `### std.${moduleName}\n`;
const start = catalog.indexOf(marker);
if (start < 0) {
fail(`missing std.${moduleName} module section`);
}
const next = catalog.indexOf("\n### std.", start + marker.length);
return next < 0 ? catalog.slice(start) : catalog.slice(start, next);
}
function requireModuleTier(moduleName, expectedTier) {
const section = moduleSection(moduleName);
if (!section.includes(`- Tiers: \`${expectedTier}\``)) {
fail(`std.${moduleName} is not marked as ${expectedTier}`);
}
}
function requireHelperTier(moduleName, helperName, expectedTier) {
const section = moduleSection(moduleName);
const helperPattern = new RegExp(`^- \`${expectedTier}\` \`${helperName} `, "m");
if (!helperPattern.test(section)) {
fail(`std.${moduleName}.${helperName} is not marked as ${expectedTier}`);
}
}
if (/experimental`: not used|experimental not used/i.test(catalog)) {
fail("catalog still contains stale wording that says experimental is unused");
}
requireText("- `beta-supported`:", "missing beta-supported tier definition");
requireText("- `experimental`:", "missing experimental tier definition");
requireText("- `internal`:", "missing internal tier definition");
requireText("- `experimental` helper signatures:", "missing experimental summary count");
requireText("Concrete `std.vec_*` modules are beta-supported as concrete helper families only; this does not freeze a generic collection API.", "missing concrete vector boundary");
if (!/^- `experimental` `[^`]+`/m.test(catalog)) {
fail("catalog does not list any experimental helper signatures");
}
for (const moduleName of ["json", "net", "random", "time"]) {
requireModuleTier(moduleName, "experimental");
}
for (const helperName of [
"open_text_read_result",
"read_open_text_result",
"close_result",
"read_text_via_handle_result",
"close_ok",
]) {
requireHelperTier("fs", helperName, "experimental");
}
for (const moduleName of ["vec_bool", "vec_f64", "vec_i32", "vec_i64", "vec_string"]) {
const section = moduleSection(moduleName);
if (!section.includes("- Note: concrete-only vector helper family; no generic collection freeze.")) {
fail(`std.${moduleName} is missing the concrete vector boundary note`);
}
}