@brandlab-digital/conformance 3.13.0 → 3.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/dist/analytics-e2e.d.ts +10 -16
- package/dist/analytics-e2e.d.ts.map +1 -1
- package/dist/analytics-e2e.js +61 -3
- package/dist/analytics-e2e.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +4 -1
- package/dist/cli.js.map +1 -1
- package/dist/current-release.js +5 -5
- package/dist/current-release.js.map +1 -1
- package/dist/estate.d.ts +28 -0
- package/dist/estate.d.ts.map +1 -1
- package/dist/estate.js +35 -12
- package/dist/estate.js.map +1 -1
- package/dist/project.d.ts +20 -0
- package/dist/project.d.ts.map +1 -1
- package/dist/project.js +92 -2
- package/dist/project.js.map +1 -1
- package/dist/ready-cli.d.ts.map +1 -1
- package/dist/ready-cli.js +8 -3
- package/dist/ready-cli.js.map +1 -1
- package/dist/rule-registry.d.ts +5 -0
- package/dist/rule-registry.d.ts.map +1 -1
- package/dist/rule-registry.js +1 -0
- package/dist/rule-registry.js.map +1 -1
- package/dist/site-system/checks.d.ts +26 -1
- package/dist/site-system/checks.d.ts.map +1 -1
- package/dist/site-system/checks.js +3 -0
- package/dist/site-system/checks.js.map +1 -1
- package/dist/site-system/report.d.ts.map +1 -1
- package/dist/site-system/report.js +19 -5
- package/dist/site-system/report.js.map +1 -1
- package/dist/site-system/rule-modules.d.ts.map +1 -1
- package/dist/site-system/rule-modules.js +5 -0
- package/dist/site-system/rule-modules.js.map +1 -1
- package/dist/site-system/rules/delivery/h13-inbox.d.ts +23 -0
- package/dist/site-system/rules/delivery/h13-inbox.d.ts.map +1 -0
- package/dist/site-system/rules/delivery/h13-inbox.js +208 -0
- package/dist/site-system/rules/delivery/h13-inbox.js.map +1 -0
- package/dist/site-system/rules/delivery/index.d.ts +12 -0
- package/dist/site-system/rules/delivery/index.d.ts.map +1 -0
- package/dist/site-system/rules/delivery/index.js +7 -0
- package/dist/site-system/rules/delivery/index.js.map +1 -0
- package/dist/site-system/rules/full/e1-pattern.d.ts +4 -0
- package/dist/site-system/rules/full/e1-pattern.d.ts.map +1 -0
- package/dist/site-system/rules/full/e1-pattern.js +47 -0
- package/dist/site-system/rules/full/e1-pattern.js.map +1 -0
- package/dist/site-system/rules/full/estate.d.ts +16 -1
- package/dist/site-system/rules/full/estate.d.ts.map +1 -1
- package/dist/site-system/rules/full/estate.js +23 -4
- package/dist/site-system/rules/full/estate.js.map +1 -1
- package/dist/site-system/rules/full/geography.d.ts +8 -2
- package/dist/site-system/rules/full/geography.d.ts.map +1 -1
- package/dist/site-system/rules/full/geography.js +6 -2
- package/dist/site-system/rules/full/geography.js.map +1 -1
- package/dist/site-system/rules/full/index.d.ts +2 -2
- package/dist/site-system/rules/full/index.d.ts.map +1 -1
- package/dist/site-system/rules/full/index.js +15 -4
- package/dist/site-system/rules/full/index.js.map +1 -1
- package/dist/site-system/rules/full/k12-slots.d.ts +4 -0
- package/dist/site-system/rules/full/k12-slots.d.ts.map +1 -0
- package/dist/site-system/rules/full/k12-slots.js +40 -0
- package/dist/site-system/rules/full/k12-slots.js.map +1 -0
- package/dist/site-system/rules/full/loc-index.d.ts +5 -0
- package/dist/site-system/rules/full/loc-index.d.ts.map +1 -1
- package/dist/site-system/rules/full/loc-index.js +43 -2
- package/dist/site-system/rules/full/loc-index.js.map +1 -1
- package/dist/site-system/rules/full/strategy.d.ts +4 -0
- package/dist/site-system/rules/full/strategy.d.ts.map +1 -1
- package/dist/site-system/rules/full/strategy.js +19 -3
- package/dist/site-system/rules/full/strategy.js.map +1 -1
- package/dist/site-system/rules/sections/k2-skin-coverage.d.ts +2 -2
- package/dist/site-system/rules/sections/k2-skin-coverage.d.ts.map +1 -1
- package/dist/site-system/rules/sections/k2-skin-coverage.js +6 -2
- package/dist/site-system/rules/sections/k2-skin-coverage.js.map +1 -1
- package/dist/site-system/runners.js +1 -1
- package/dist/site-system/runners.js.map +1 -1
- package/package.json +2 -2
package/dist/ready-cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ready-cli.js","sourceRoot":"","sources":["../src/ready-cli.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\nimport { existsSync, mkdirSync, readFileSync, realpathSync, writeFileSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, relative, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { detectInstalledBrandlabRelease, evaluateBrandlabProject } from \"./project.js\";\nimport type { SiteSystemFinding } from \"./site-system/checks.js\";\nimport { readSiteSystemProjectConfig } from \"./site-system/config.js\";\nimport { readSiteSystemJourneyReport } from \"./site-system/playwright-report.js\";\nimport { appendSiteSystemRecord, readSiteSystemRecords } from \"./site-system/records.js\";\nimport {\n buildSiteSystemReadyReport,\n renderSiteSystemReadyMarkdown,\n SITE_SYSTEM_READY_REPORT_PATHS,\n type SiteSystemReadyReport,\n type SiteSystemVerifyResult,\n} from \"./site-system/report.js\";\nimport { SITE_SYSTEM_RENDERED_RUNNERS } from \"./site-system/rule-modules.js\";\nimport {\n isSiteSystemFinding,\n runSiteSystemRenderedRunners,\n type SiteSystemRenderedRunner,\n} from \"./site-system/runners.js\";\nimport { loadSiteSystemPages, planSiteSystemSamplePaths, type SiteSystemFetch } from \"./site-system/samples.js\";\nimport { SITE_SYSTEM_RECORDED_CHECK_IDS } from \"./site-system/steps.js\";\n\ninterface ReadyReportOptions {\n command: \"report\";\n root: string;\n playwrightReport: string;\n baseUrl?: string;\n buildDir: string;\n findings: string[];\n installedRelease?: string;\n launch: boolean;\n}\n\ninterface ReadyRecordOptions {\n command: \"record\";\n root: string;\n id: string;\n evidence?: string;\n note?: string;\n}\n\ntype ReadyCliOptions = ReadyReportOptions | ReadyRecordOptions | { command: \"help\" };\n\ninterface CliIo {\n stdout: (value: string) => void;\n stderr: (value: string) => void;\n}\n\nexport interface BrandlabReadyCliDependencies {\n /** The rule modules to run (default: SITE_SYSTEM_RENDERED_RUNNERS). */\n runners?: readonly SiteSystemRenderedRunner[];\n fetch?: SiteSystemFetch;\n now?: () => Date;\n}\n\nconst DEFAULT_PLAYWRIGHT_REPORT = \"test-results/site-system.json\";\n/** The checks a --findings file may set: K10 (the lenient harness) and the other recorded checks. */\nconst SUPPLIABLE_IDS = new Set<string>(SITE_SYSTEM_RECORDED_CHECK_IDS);\nconst DEFAULT_BUILD_DIR = \".next\";\n\nconst HELP = `Brandlab ready gate\n\nWrites docs/ready/ready-report.md and .json for the Site System tier declared in\nbrandlab.config.ts (siteSystem: { tier }), and records launch-day and human steps.\n\nUsage:\n brandlab-ready [--root <path>]\n [--playwright-report <path>] journey results (default ${DEFAULT_PLAYWRIGHT_REPORT})\n [--base-url <url>] fetch the sample pages from the running site\n [--build-dir <path>] otherwise read their HTML from the build (default ${DEFAULT_BUILD_DIR})\n [--findings <path>]... K10 or X1 results as SiteSystemFinding JSON (the lenient harness)\n [--installed-release <version>]\n [--launch] also require every launch-day and human step\n brandlab-ready record <id> --evidence <where the proof is> [--note <text>] [--root <path>]\n\nExit status:\n 0 ready at the declared tier, or nothing blocks (no tier declared, or none of its checks released)\n 1 a blocking check failed or did not run, home or the contact page could not be read, a --base-url\n sample did not answer with HTML, or brandlab.config.ts could not be read in full\n (with --launch, also a step not recorded)\n 2 the gate could not run (bad arguments, an unreadable config or records file)\n`;\n\nexport function parseBrandlabReadyArgs(argv: readonly string[]): ReadyCliOptions {\n if (argv.includes(\"--help\") || argv.includes(\"-h\")) return { command: \"help\" };\n if (argv[0] === \"record\") return parseRecordArgs(argv.slice(1));\n const parsed: ReadyReportOptions = {\n command: \"report\",\n root: process.cwd(),\n playwrightReport: DEFAULT_PLAYWRIGHT_REPORT,\n buildDir: DEFAULT_BUILD_DIR,\n findings: [],\n launch: false,\n };\n for (let index = 0; index < argv.length; index += 1) {\n const argument = argv[index];\n if (argument === \"--root\") parsed.root = resolve(requireValue(argv, ++index, argument));\n else if (argument === \"--playwright-report\") parsed.playwrightReport = requireValue(argv, ++index, argument);\n else if (argument === \"--build-dir\") parsed.buildDir = requireValue(argv, ++index, argument);\n else if (argument === \"--findings\") parsed.findings.push(requireValue(argv, ++index, argument));\n else if (argument === \"--installed-release\") parsed.installedRelease = requireValue(argv, ++index, argument);\n else if (argument === \"--launch\") parsed.launch = true;\n else if (argument === \"--base-url\") {\n const value = requireValue(argv, ++index, argument);\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n throw new Error(`--base-url ${value} is not a URL.`);\n }\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") throw new Error(\"--base-url must be an http or https URL.\");\n parsed.baseUrl = value;\n } else {\n throw new Error(`Unknown argument ${argument}.`);\n }\n }\n return parsed;\n}\n\nfunction parseRecordArgs(argv: readonly string[]): ReadyRecordOptions {\n const parsed: ReadyRecordOptions = { command: \"record\", root: process.cwd(), id: \"\" };\n for (let index = 0; index < argv.length; index += 1) {\n const argument = argv[index]!;\n if (argument === \"--evidence\") parsed.evidence = requireValue(argv, ++index, argument);\n else if (argument === \"--note\") parsed.note = requireValue(argv, ++index, argument);\n else if (argument === \"--root\") parsed.root = resolve(requireValue(argv, ++index, argument));\n else if (!argument.startsWith(\"--\") && !parsed.id) parsed.id = argument;\n else throw new Error(`Unknown argument ${argument}.`);\n }\n if (!parsed.id) throw new Error(\"record needs a step id, for example: brandlab-ready record X3 --evidence <PR link>.\");\n if (parsed.evidence === undefined) throw new Error(`record ${parsed.id} needs --evidence <where the proof is>.`);\n return parsed;\n}\n\nexport async function runBrandlabReadyCli(\n argv: readonly string[],\n io: CliIo = {\n stdout: (value) => process.stdout.write(value),\n stderr: (value) => process.stderr.write(value),\n },\n dependencies: BrandlabReadyCliDependencies = {},\n): Promise<number> {\n let options: ReadyCliOptions;\n try {\n options = parseBrandlabReadyArgs(argv);\n } catch (error) {\n io.stderr(`${errorMessage(error)}\\n\\n${HELP}`);\n return 2;\n }\n if (options.command === \"help\") {\n io.stdout(HELP);\n return 0;\n }\n const now = dependencies.now ?? (() => new Date());\n try {\n if (options.command === \"record\") {\n const { path, record } = appendSiteSystemRecord(options.root, {\n id: options.id,\n evidence: options.evidence ?? \"\",\n ...(options.note !== undefined ? { note: options.note } : {}),\n now: now(),\n });\n io.stdout(`Recorded ${record.id} in ${path}.\\n`);\n return 0;\n }\n const report = await createReadyReport(options, dependencies, now());\n const markdownPath = join(options.root, SITE_SYSTEM_READY_REPORT_PATHS.markdown);\n mkdirSync(dirname(markdownPath), { recursive: true });\n writeFileSync(markdownPath, renderSiteSystemReadyMarkdown(report));\n writeFileSync(join(options.root, SITE_SYSTEM_READY_REPORT_PATHS.json), `${JSON.stringify(report, null, 2)}\\n`);\n const problems = report.problems.length;\n io.stdout(\n `${report.verdict.summary}.\\n` +\n (problems > 0 ? `The report lists ${problems} problem${problems === 1 ? \"\" : \"s\"} with the inputs.\\n` : \"\") +\n `Wrote ${SITE_SYSTEM_READY_REPORT_PATHS.markdown} and ${SITE_SYSTEM_READY_REPORT_PATHS.json}.\\n`,\n );\n return report.verdict.exitCode;\n } catch (error) {\n io.stderr(`${errorMessage(error)}\\n`);\n return 2;\n }\n}\n\nasync function createReadyReport(\n options: ReadyReportOptions,\n dependencies: BrandlabReadyCliDependencies,\n now: Date,\n): Promise<SiteSystemReadyReport> {\n const root = options.root;\n const config = readSiteSystemProjectConfig(root);\n const release = options.installedRelease ?? detectInstalledBrandlabRelease(readPackageJson(root));\n if (config.siteSystem && !release) {\n throw new Error(\n \"The installed Brandlab release could not be read from package.json. Pin all four Brandlab packages to one exact version, or pass --installed-release.\",\n );\n }\n const problems: string[] = [...config.problems];\n const findings: SiteSystemFinding[] = [];\n\n // Journeys: the Playwright JSON report of the site-system spec.\n const journeyPath = resolveIn(root, options.playwrightReport);\n let journeyReport: string | null = null;\n let journeyTests = 0;\n if (!existsSync(journeyPath)) {\n problems.push(`No Playwright report at ${displayPath(root, journeyPath)}, so the journey checks did not run (run the site-system journeys with the JSON reporter first).`);\n } else {\n journeyReport = displayPath(root, journeyPath);\n const parsed = readJson(journeyPath);\n if (parsed === undefined) {\n problems.push(`${journeyReport} is not valid JSON, so the journey checks did not run.`);\n } else {\n const journeys = readSiteSystemJourneyReport(parsed);\n findings.push(...journeys.findings);\n problems.push(...journeys.problems);\n journeyTests = journeys.tests;\n }\n }\n\n // Rendered and static rule modules over the sampled pages.\n const buildDir = resolveIn(root, options.buildDir);\n const prerenderManifest = readJson(join(buildDir, \"prerender-manifest.json\"));\n const paths = planSiteSystemSamplePaths({\n representativeRoutes: config.representativeRoutes,\n samples: config.siteSystem?.samples ?? [],\n prerenderManifest,\n });\n if (!options.baseUrl && prerenderManifest === undefined) {\n problems.push(`No production build at ${displayPath(root, buildDir)}: run next build first, or pass --base-url.`);\n }\n const loaded = options.baseUrl || prerenderManifest !== undefined\n ? await loadSiteSystemPages({ paths, buildDir, baseUrl: options.baseUrl, fetch: dependencies.fetch })\n : { pages: [], missing: paths, source: \"build\" as const, problems: [] };\n problems.push(...loaded.problems);\n if (loaded.pages.length === 0) problems.push(\"No page HTML was available, so the rule modules ran on the project files only.\");\n // Every runner runs: static rules read the project, rendered rules report not-applicable without pages.\n const runners = dependencies.runners ?? SITE_SYSTEM_RENDERED_RUNNERS;\n const rendered = await runSiteSystemRenderedRunners(runners, {\n baseUrl: options.baseUrl ?? \"\",\n pages: loaded.pages,\n missing: loaded.missing,\n projectRoot: root,\n siteSystem: config.siteSystem,\n buildDir,\n });\n findings.push(...rendered.findings);\n problems.push(...rendered.problems);\n\n // Fail closed: a config the gate cannot read in full, and (for a declared tier) pages it could not read.\n const blockers: string[] = [];\n if (!config.complete) blockers.push(\"brandlab.config.ts could not be read in full\");\n if (config.siteSystem) {\n if (loaded.source === \"base-url\" && loaded.missing.length > 0) {\n blockers.push(`${loaded.missing.length} sample page${loaded.missing.length === 1 ? \"\" : \"s\"} did not answer with HTML`);\n } else {\n if (loaded.missing.includes(\"/\")) blockers.push(\"the home page could not be read\");\n const contact = config.representativeRoutes.contact;\n if (contact && loaded.missing.includes(contact)) blockers.push(\"the contact page could not be read\");\n }\n }\n\n // Results other tools wrote as SiteSystemFinding JSON.\n for (const file of options.findings) {\n const path = resolveIn(root, file);\n const parsed = readJson(path);\n const list = Array.isArray(parsed) ? parsed : isRecord(parsed) && Array.isArray(parsed.findings) ? parsed.findings : null;\n if (!list) {\n problems.push(`${displayPath(root, path)} is missing or is not a list of findings, so it was ignored.`);\n continue;\n }\n const valid = list.filter(isSiteSystemFinding);\n if (valid.length < list.length) {\n problems.push(`${list.length - valid.length} result(s) in ${displayPath(root, path)} name an unknown check or status, so they were ignored.`);\n }\n // Supplied files carry harness and recorded results only; they cannot pass a journey or rule check.\n const refused = [...new Set(valid.filter((finding) => !SUPPLIABLE_IDS.has(finding.checkId)).map((finding) => finding.checkId))];\n if (refused.length > 0) {\n problems.push(`${displayPath(root, path)} sets ${refused.join(\", \")}, but --findings may only set ${[...SUPPLIABLE_IDS].join(\" and \")}, so those results were ignored.`);\n }\n findings.push(...valid.filter((finding) => SUPPLIABLE_IDS.has(finding.checkId)));\n }\n\n // The existing brandlab-verify families the shell tier carries.\n let verify: SiteSystemVerifyResult | null = null;\n try {\n verify = evaluateBrandlabProject({\n root,\n ...(options.installedRelease !== undefined ? { installedRelease: options.installedRelease } : {}),\n });\n } catch (error) {\n problems.push(`brandlab-verify could not run (${errorMessage(error)}), so its search, contact and analytics checks did not run.`);\n }\n\n return buildSiteSystemReadyReport({\n projectId: config.projectId,\n siteSystem: config.siteSystem,\n release,\n findings,\n verify,\n launchRecords: readSiteSystemRecords(root, \"launch\"),\n humanRecords: readSiteSystemRecords(root, \"human\"),\n exceptions: config.exceptions,\n inputs: {\n journeyReport,\n journeyTests,\n pageSource: loaded.pages.length === 0 ? \"none\" : loaded.source,\n pages: loaded.pages.map((page) => page.path),\n runners: runners.length,\n findingFiles: options.findings.map((file) => displayPath(root, resolveIn(root, file))),\n },\n problems,\n now,\n launch: options.launch,\n blockers,\n });\n}\n\nfunction readPackageJson(root: string): Parameters<typeof detectInstalledBrandlabRelease>[0] {\n const parsed = readJson(join(root, \"package.json\"));\n return isRecord(parsed) ? (parsed as Parameters<typeof detectInstalledBrandlabRelease>[0]) : null;\n}\n\n/** Parsed JSON, or undefined when the file is missing or invalid. */\nfunction readJson(path: string): unknown {\n if (!existsSync(path)) return undefined;\n try {\n return JSON.parse(readFileSync(path, \"utf8\"));\n } catch {\n return undefined;\n }\n}\n\nfunction resolveIn(root: string, path: string): string {\n return isAbsolute(path) ? path : resolve(root, path);\n}\n\nfunction displayPath(root: string, path: string): string {\n const relativePath = relative(root, path);\n return relativePath && !relativePath.startsWith(\"..\") && !isAbsolute(relativePath) ? relativePath : path;\n}\n\nfunction requireValue(argv: readonly string[], index: number, argument: string): string {\n const value = argv[index];\n if (value === undefined || value.startsWith(\"--\")) throw new Error(`${argument} requires a value.`);\n return value;\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nexport function isBrandlabReadyCliEntrypoint(moduleUrl: string, argvPath: string | undefined): boolean {\n if (!argvPath) return false;\n try {\n return realpathSync(fileURLToPath(moduleUrl)) === realpathSync(resolve(argvPath));\n } catch {\n return false;\n }\n}\n\nif (isBrandlabReadyCliEntrypoint(import.meta.url, process.argv[1])) {\n runBrandlabReadyCli(process.argv.slice(2)).then((code) => {\n process.exitCode = code;\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ready-cli.js","sourceRoot":"","sources":["../src/ready-cli.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\nimport { existsSync, mkdirSync, readFileSync, realpathSync, writeFileSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, relative, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { detectBrandlabCanaryRelease, detectInstalledBrandlabRelease, evaluateBrandlabProject } from \"./project.js\";\nimport type { SiteSystemFinding } from \"./site-system/checks.js\";\nimport { readSiteSystemProjectConfig } from \"./site-system/config.js\";\nimport { readSiteSystemJourneyReport } from \"./site-system/playwright-report.js\";\nimport { appendSiteSystemRecord, readSiteSystemRecords } from \"./site-system/records.js\";\nimport {\n buildSiteSystemReadyReport,\n renderSiteSystemReadyMarkdown,\n SITE_SYSTEM_READY_REPORT_PATHS,\n type SiteSystemReadyReport,\n type SiteSystemVerifyResult,\n} from \"./site-system/report.js\";\nimport { SITE_SYSTEM_RENDERED_RUNNERS } from \"./site-system/rule-modules.js\";\nimport {\n isSiteSystemFinding,\n runSiteSystemRenderedRunners,\n type SiteSystemRenderedRunner,\n} from \"./site-system/runners.js\";\nimport { loadSiteSystemPages, planSiteSystemSamplePaths, type SiteSystemFetch } from \"./site-system/samples.js\";\nimport { SITE_SYSTEM_RECORDED_CHECK_IDS } from \"./site-system/steps.js\";\n\ninterface ReadyReportOptions {\n command: \"report\";\n root: string;\n playwrightReport: string;\n baseUrl?: string;\n buildDir: string;\n findings: string[];\n installedRelease?: string;\n launch: boolean;\n}\n\ninterface ReadyRecordOptions {\n command: \"record\";\n root: string;\n id: string;\n evidence?: string;\n note?: string;\n}\n\ntype ReadyCliOptions = ReadyReportOptions | ReadyRecordOptions | { command: \"help\" };\n\ninterface CliIo {\n stdout: (value: string) => void;\n stderr: (value: string) => void;\n}\n\nexport interface BrandlabReadyCliDependencies {\n /** The rule modules to run (default: SITE_SYSTEM_RENDERED_RUNNERS). */\n runners?: readonly SiteSystemRenderedRunner[];\n fetch?: SiteSystemFetch;\n now?: () => Date;\n}\n\nconst DEFAULT_PLAYWRIGHT_REPORT = \"test-results/site-system.json\";\n/** The checks a --findings file may set: K10 (the lenient harness) and the other recorded checks. */\nconst SUPPLIABLE_IDS = new Set<string>(SITE_SYSTEM_RECORDED_CHECK_IDS);\nconst DEFAULT_BUILD_DIR = \".next\";\n\nconst HELP = `Brandlab ready gate\n\nWrites docs/ready/ready-report.md and .json for the Site System tier declared in\nbrandlab.config.ts (siteSystem: { tier }), and records launch-day and human steps.\n\nUsage:\n brandlab-ready [--root <path>]\n [--playwright-report <path>] journey results (default ${DEFAULT_PLAYWRIGHT_REPORT})\n [--base-url <url>] fetch the sample pages from the running site\n [--build-dir <path>] otherwise read their HTML from the build (default ${DEFAULT_BUILD_DIR})\n [--findings <path>]... K10 or X1 results as SiteSystemFinding JSON (the lenient harness)\n [--installed-release <version>]\n [--launch] also require every launch-day and human step\n brandlab-ready record <id> --evidence <where the proof is> [--note <text>] [--root <path>]\n\nExit status:\n 0 ready at the declared tier, or nothing blocks (no tier declared, or none of its checks released)\n 1 a blocking check failed or did not run, home or the contact page could not be read, a --base-url\n sample did not answer with HTML, or brandlab.config.ts could not be read in full\n (with --launch, also a step not recorded)\n 2 the gate could not run (bad arguments, an unreadable config or records file)\n`;\n\nexport function parseBrandlabReadyArgs(argv: readonly string[]): ReadyCliOptions {\n if (argv.includes(\"--help\") || argv.includes(\"-h\")) return { command: \"help\" };\n if (argv[0] === \"record\") return parseRecordArgs(argv.slice(1));\n const parsed: ReadyReportOptions = {\n command: \"report\",\n root: process.cwd(),\n playwrightReport: DEFAULT_PLAYWRIGHT_REPORT,\n buildDir: DEFAULT_BUILD_DIR,\n findings: [],\n launch: false,\n };\n for (let index = 0; index < argv.length; index += 1) {\n const argument = argv[index];\n if (argument === \"--root\") parsed.root = resolve(requireValue(argv, ++index, argument));\n else if (argument === \"--playwright-report\") parsed.playwrightReport = requireValue(argv, ++index, argument);\n else if (argument === \"--build-dir\") parsed.buildDir = requireValue(argv, ++index, argument);\n else if (argument === \"--findings\") parsed.findings.push(requireValue(argv, ++index, argument));\n else if (argument === \"--installed-release\") parsed.installedRelease = requireValue(argv, ++index, argument);\n else if (argument === \"--launch\") parsed.launch = true;\n else if (argument === \"--base-url\") {\n const value = requireValue(argv, ++index, argument);\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n throw new Error(`--base-url ${value} is not a URL.`);\n }\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") throw new Error(\"--base-url must be an http or https URL.\");\n parsed.baseUrl = value;\n } else {\n throw new Error(`Unknown argument ${argument}.`);\n }\n }\n return parsed;\n}\n\nfunction parseRecordArgs(argv: readonly string[]): ReadyRecordOptions {\n const parsed: ReadyRecordOptions = { command: \"record\", root: process.cwd(), id: \"\" };\n for (let index = 0; index < argv.length; index += 1) {\n const argument = argv[index]!;\n if (argument === \"--evidence\") parsed.evidence = requireValue(argv, ++index, argument);\n else if (argument === \"--note\") parsed.note = requireValue(argv, ++index, argument);\n else if (argument === \"--root\") parsed.root = resolve(requireValue(argv, ++index, argument));\n else if (!argument.startsWith(\"--\") && !parsed.id) parsed.id = argument;\n else throw new Error(`Unknown argument ${argument}.`);\n }\n if (!parsed.id) throw new Error(\"record needs a step id, for example: brandlab-ready record X3 --evidence <PR link>.\");\n if (parsed.evidence === undefined) throw new Error(`record ${parsed.id} needs --evidence <where the proof is>.`);\n return parsed;\n}\n\nexport async function runBrandlabReadyCli(\n argv: readonly string[],\n io: CliIo = {\n stdout: (value) => process.stdout.write(value),\n stderr: (value) => process.stderr.write(value),\n },\n dependencies: BrandlabReadyCliDependencies = {},\n): Promise<number> {\n let options: ReadyCliOptions;\n try {\n options = parseBrandlabReadyArgs(argv);\n } catch (error) {\n io.stderr(`${errorMessage(error)}\\n\\n${HELP}`);\n return 2;\n }\n if (options.command === \"help\") {\n io.stdout(HELP);\n return 0;\n }\n const now = dependencies.now ?? (() => new Date());\n try {\n if (options.command === \"record\") {\n const { path, record } = appendSiteSystemRecord(options.root, {\n id: options.id,\n evidence: options.evidence ?? \"\",\n ...(options.note !== undefined ? { note: options.note } : {}),\n now: now(),\n });\n io.stdout(`Recorded ${record.id} in ${path}.\\n`);\n return 0;\n }\n const report = await createReadyReport(options, dependencies, now());\n const markdownPath = join(options.root, SITE_SYSTEM_READY_REPORT_PATHS.markdown);\n mkdirSync(dirname(markdownPath), { recursive: true });\n writeFileSync(markdownPath, renderSiteSystemReadyMarkdown(report));\n writeFileSync(join(options.root, SITE_SYSTEM_READY_REPORT_PATHS.json), `${JSON.stringify(report, null, 2)}\\n`);\n const problems = report.problems.length;\n io.stdout(\n `${report.verdict.summary}.\\n` +\n (problems > 0 ? `The report lists ${problems} problem${problems === 1 ? \"\" : \"s\"} with the inputs.\\n` : \"\") +\n `Wrote ${SITE_SYSTEM_READY_REPORT_PATHS.markdown} and ${SITE_SYSTEM_READY_REPORT_PATHS.json}.\\n`,\n );\n return report.verdict.exitCode;\n } catch (error) {\n io.stderr(`${errorMessage(error)}\\n`);\n return 2;\n }\n}\n\nasync function createReadyReport(\n options: ReadyReportOptions,\n dependencies: BrandlabReadyCliDependencies,\n now: Date,\n): Promise<SiteSystemReadyReport> {\n const root = options.root;\n const config = readSiteSystemProjectConfig(root);\n const packageJson = readPackageJson(root);\n // A canary (X.Y.Z-canary.N) gates checks as its line X.Y.Z, but never launches.\n const canary = options.installedRelease ? null : detectBrandlabCanaryRelease(packageJson);\n const release = options.installedRelease ?? detectInstalledBrandlabRelease(packageJson) ?? canary?.version ?? null;\n if (config.siteSystem && !release) {\n throw new Error(\n \"The installed Brandlab release could not be read from package.json. Pin all four Brandlab packages to one exact version (or one canary), or pass --installed-release.\",\n );\n }\n const problems: string[] = [...config.problems];\n const findings: SiteSystemFinding[] = [];\n\n // Journeys: the Playwright JSON report of the site-system spec.\n const journeyPath = resolveIn(root, options.playwrightReport);\n let journeyReport: string | null = null;\n let journeyTests = 0;\n if (!existsSync(journeyPath)) {\n problems.push(`No Playwright report at ${displayPath(root, journeyPath)}, so the journey checks did not run (run the site-system journeys with the JSON reporter first).`);\n } else {\n journeyReport = displayPath(root, journeyPath);\n const parsed = readJson(journeyPath);\n if (parsed === undefined) {\n problems.push(`${journeyReport} is not valid JSON, so the journey checks did not run.`);\n } else {\n const journeys = readSiteSystemJourneyReport(parsed);\n findings.push(...journeys.findings);\n problems.push(...journeys.problems);\n journeyTests = journeys.tests;\n }\n }\n\n // Rendered and static rule modules over the sampled pages.\n const buildDir = resolveIn(root, options.buildDir);\n const prerenderManifest = readJson(join(buildDir, \"prerender-manifest.json\"));\n const paths = planSiteSystemSamplePaths({\n representativeRoutes: config.representativeRoutes,\n samples: config.siteSystem?.samples ?? [],\n prerenderManifest,\n });\n if (!options.baseUrl && prerenderManifest === undefined) {\n problems.push(`No production build at ${displayPath(root, buildDir)}: run next build first, or pass --base-url.`);\n }\n const loaded = options.baseUrl || prerenderManifest !== undefined\n ? await loadSiteSystemPages({ paths, buildDir, baseUrl: options.baseUrl, fetch: dependencies.fetch })\n : { pages: [], missing: paths, source: \"build\" as const, problems: [] };\n problems.push(...loaded.problems);\n if (loaded.pages.length === 0) problems.push(\"No page HTML was available, so the rule modules ran on the project files only.\");\n // Every runner runs: static rules read the project, rendered rules report not-applicable without pages.\n const runners = dependencies.runners ?? SITE_SYSTEM_RENDERED_RUNNERS;\n const rendered = await runSiteSystemRenderedRunners(runners, {\n baseUrl: options.baseUrl ?? \"\",\n pages: loaded.pages,\n missing: loaded.missing,\n projectRoot: root,\n siteSystem: config.siteSystem,\n buildDir,\n });\n findings.push(...rendered.findings);\n problems.push(...rendered.problems);\n\n // Fail closed: a config the gate cannot read in full, and (for a declared tier) pages it could not read.\n const blockers: string[] = [];\n if (canary && options.launch) blockers.push(`the Brandlab packages are the canary ${canary.version}, not a published release`);\n if (!config.complete) blockers.push(\"brandlab.config.ts could not be read in full\");\n if (config.siteSystem) {\n if (loaded.source === \"base-url\" && loaded.missing.length > 0) {\n blockers.push(`${loaded.missing.length} sample page${loaded.missing.length === 1 ? \"\" : \"s\"} did not answer with HTML`);\n } else {\n if (loaded.missing.includes(\"/\")) blockers.push(\"the home page could not be read\");\n const contact = config.representativeRoutes.contact;\n if (contact && loaded.missing.includes(contact)) blockers.push(\"the contact page could not be read\");\n }\n }\n\n // Results other tools wrote as SiteSystemFinding JSON.\n for (const file of options.findings) {\n const path = resolveIn(root, file);\n const parsed = readJson(path);\n const list = Array.isArray(parsed) ? parsed : isRecord(parsed) && Array.isArray(parsed.findings) ? parsed.findings : null;\n if (!list) {\n problems.push(`${displayPath(root, path)} is missing or is not a list of findings, so it was ignored.`);\n continue;\n }\n const valid = list.filter(isSiteSystemFinding);\n if (valid.length < list.length) {\n problems.push(`${list.length - valid.length} result(s) in ${displayPath(root, path)} name an unknown check or status, so they were ignored.`);\n }\n // Supplied files carry harness and recorded results only; they cannot pass a journey or rule check.\n const refused = [...new Set(valid.filter((finding) => !SUPPLIABLE_IDS.has(finding.checkId)).map((finding) => finding.checkId))];\n if (refused.length > 0) {\n problems.push(`${displayPath(root, path)} sets ${refused.join(\", \")}, but --findings may only set ${[...SUPPLIABLE_IDS].join(\" and \")}, so those results were ignored.`);\n }\n findings.push(...valid.filter((finding) => SUPPLIABLE_IDS.has(finding.checkId)));\n }\n\n // The existing brandlab-verify families the shell tier carries.\n let verify: SiteSystemVerifyResult | null = null;\n try {\n verify = evaluateBrandlabProject({\n root,\n ...(options.installedRelease !== undefined ? { installedRelease: options.installedRelease } : {}),\n });\n } catch (error) {\n problems.push(`brandlab-verify could not run (${errorMessage(error)}), so its search, contact and analytics checks did not run.`);\n }\n\n return buildSiteSystemReadyReport({\n projectId: config.projectId,\n siteSystem: config.siteSystem,\n release,\n findings,\n verify,\n launchRecords: readSiteSystemRecords(root, \"launch\"),\n humanRecords: readSiteSystemRecords(root, \"human\"),\n exceptions: config.exceptions,\n inputs: {\n journeyReport,\n journeyTests,\n pageSource: loaded.pages.length === 0 ? \"none\" : loaded.source,\n pages: loaded.pages.map((page) => page.path),\n runners: runners.length,\n findingFiles: options.findings.map((file) => displayPath(root, resolveIn(root, file))),\n },\n problems,\n now,\n launch: options.launch,\n blockers,\n });\n}\n\nfunction readPackageJson(root: string): Parameters<typeof detectInstalledBrandlabRelease>[0] {\n const parsed = readJson(join(root, \"package.json\"));\n return isRecord(parsed) ? (parsed as Parameters<typeof detectInstalledBrandlabRelease>[0]) : null;\n}\n\n/** Parsed JSON, or undefined when the file is missing or invalid. */\nfunction readJson(path: string): unknown {\n if (!existsSync(path)) return undefined;\n try {\n return JSON.parse(readFileSync(path, \"utf8\"));\n } catch {\n return undefined;\n }\n}\n\nfunction resolveIn(root: string, path: string): string {\n return isAbsolute(path) ? path : resolve(root, path);\n}\n\nfunction displayPath(root: string, path: string): string {\n const relativePath = relative(root, path);\n return relativePath && !relativePath.startsWith(\"..\") && !isAbsolute(relativePath) ? relativePath : path;\n}\n\nfunction requireValue(argv: readonly string[], index: number, argument: string): string {\n const value = argv[index];\n if (value === undefined || value.startsWith(\"--\")) throw new Error(`${argument} requires a value.`);\n return value;\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nexport function isBrandlabReadyCliEntrypoint(moduleUrl: string, argvPath: string | undefined): boolean {\n if (!argvPath) return false;\n try {\n return realpathSync(fileURLToPath(moduleUrl)) === realpathSync(resolve(argvPath));\n } catch {\n return false;\n }\n}\n\nif (isBrandlabReadyCliEntrypoint(import.meta.url, process.argv[1])) {\n runBrandlabReadyCli(process.argv.slice(2)).then((code) => {\n process.exitCode = code;\n });\n}\n"]}
|
package/dist/rule-registry.d.ts
CHANGED
|
@@ -21,6 +21,11 @@ export declare const BRANDLAB_STATIC_RULES: readonly [{
|
|
|
21
21
|
readonly surface: "release";
|
|
22
22
|
readonly checkId: "release-consistency";
|
|
23
23
|
readonly summary: "All four Brandlab packages are pinned to one exact release.";
|
|
24
|
+
}, {
|
|
25
|
+
readonly ruleId: "brandlab-release-canary";
|
|
26
|
+
readonly surface: "release";
|
|
27
|
+
readonly checkId: "release-consistency";
|
|
28
|
+
readonly summary: "A canary (X.Y.Z-canary.N) is reported as a warning, checked against its line's contract when present, and never counts as a published release.";
|
|
24
29
|
}, {
|
|
25
30
|
readonly ruleId: "brandlab-release-unsupported";
|
|
26
31
|
readonly surface: "release";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rule-registry.d.ts","sourceRoot":"","sources":["../src/rule-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AAE5E;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,2BAA2B,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,qBAAqB
|
|
1
|
+
{"version":3,"file":"rule-registry.d.ts","sourceRoot":"","sources":["../src/rule-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AAE5E;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,2BAA2B,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6DgB,CAAC;AAEnD,6FAA6F;AAC7F,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAM3F"}
|
package/dist/rule-registry.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export const BRANDLAB_STATIC_RULES = [
|
|
2
2
|
{ ruleId: "brandlab-release-package-json-missing", surface: "release", checkId: "release-consistency", summary: "package.json is present and readable.", },
|
|
3
3
|
{ ruleId: "brandlab-release-installed-version-unresolved", surface: "release", checkId: "release-consistency", summary: "All four Brandlab packages are pinned to one exact release.", },
|
|
4
|
+
{ ruleId: "brandlab-release-canary", surface: "release", checkId: "release-consistency", summary: "A canary (X.Y.Z-canary.N) is reported as a warning, checked against its line's contract when present, and never counts as a published release.", },
|
|
4
5
|
{ ruleId: "brandlab-release-unsupported", surface: "release", checkId: "release-consistency", summary: "The installed release is the one this checker certifies.", },
|
|
5
6
|
{ ruleId: "brandlab-release-declared-installed-mismatch", surface: "release", checkId: "release-consistency", summary: "The declared and detected releases agree.", },
|
|
6
7
|
{ ruleId: "brandlab-release-package-lock-<state>", surface: "release", checkId: "release-consistency", summary: "A valid npm lockfile v2 or v3 is committed.", },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rule-registry.js","sourceRoot":"","sources":["../src/rule-registry.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BrandlabVerificationCheckId } from \"./verification-policy.js\";\n\n/**\n * Every static rule the evaluator can run, the check it evaluates and what it\n * proves. `<placeholder>` segments stand for the concrete package, capability,\n * key or state named in each finding. The generated rule reference is built\n * from this list, and tests keep it identical to the evaluator.\n */\nexport interface BrandlabStaticRule {\n ruleId: string;\n surface: string;\n checkId: BrandlabVerificationCheckId;\n summary: string;\n}\n\nexport const BRANDLAB_STATIC_RULES = [\n { ruleId: \"brandlab-release-package-json-missing\", surface: \"release\", checkId: \"release-consistency\", summary: \"package.json is present and readable.\", },\n { ruleId: \"brandlab-release-installed-version-unresolved\", surface: \"release\", checkId: \"release-consistency\", summary: \"All four Brandlab packages are pinned to one exact release.\", },\n { ruleId: \"brandlab-release-unsupported\", surface: \"release\", checkId: \"release-consistency\", summary: \"The installed release is the one this checker certifies.\", },\n { ruleId: \"brandlab-release-declared-installed-mismatch\", surface: \"release\", checkId: \"release-consistency\", summary: \"The declared and detected releases agree.\", },\n { ruleId: \"brandlab-release-package-lock-<state>\", surface: \"release\", checkId: \"release-consistency\", summary: \"A valid npm lockfile v2 or v3 is committed.\", },\n { ruleId: \"brandlab-release-package-pin-mismatch\", surface: \"release\", checkId: \"release-consistency\", summary: \"Each package is declared once and locked at the exact release.\", },\n { ruleId: \"brandlab-release-package-resolution-mismatch\", surface: \"release\", checkId: \"release-consistency\", summary: \"The lockfile resolves each package from the canonical npm registry with integrity.\", },\n { ruleId: \"brandlab-release-package-integrity-mismatch\", surface: \"release\", checkId: \"release-consistency\", summary: \"With --release-manifest, lockfile integrity equals the immutable release record.\", },\n { ruleId: \"brandlab-runtime-<package>\", surface: \"runtime\", checkId: \"runtime-supported\", summary: \"next, react, react-dom and typescript use versions the release permits.\", },\n { ruleId: \"brandlab-runtime-react-pair\", surface: \"runtime\", checkId: \"runtime-supported\", summary: \"react and react-dom are declared and locked at the same version.\", },\n { ruleId: \"brandlab-runtime-node\", surface: \"runtime\", checkId: \"runtime-supported\", summary: \"engines.node matches the release in package.json and the lockfile.\", },\n { ruleId: \"brandlab-runtime-package-manager\", surface: \"runtime\", checkId: \"runtime-supported\", summary: \"packageManager is the release's npm version.\", },\n { ruleId: \"brandlab-runtime-sharp\", surface: \"runtime\", checkId: \"runtime-supported\", summary: \"Sharp is pinned only by overrides.sharp with one lockfile resolution.\", },\n { ruleId: \"brandlab-runtime-image-initialisation\", surface: \"runtime\", checkId: \"runtime-supported\", summary: \"next.config imports the shared image-runtime guard first.\", },\n { ruleId: \"brandlab-runtime-next-config\", surface: \"runtime\", checkId: \"runtime-supported\", summary: \"next.config exports defineBrandlabNextConfig, which owns headers, image formats and Preview noindex.\", },\n { ruleId: \"brandlab-runtime-image-remote-patterns\", surface: \"runtime\", checkId: \"runtime-supported\", summary: \"Image remote patterns are https on public hosts (from 3.3.3 a production build refuses http and local ones, and wildcard hosts that admit a local address); any other wildcard host, or every path of another site's host, is a warning.\", },\n { ruleId: \"brandlab-environment-<capability>-<key>\", surface: \"environment\", checkId: \"runtime-supported\", summary: \".env.example documents each variable an enabled capability reads, including the contract's recipient key.\", },\n { ruleId: \"brandlab-environment-retired-contact-state\", surface: \"environment\", checkId: \"runtime-supported\", summary: \".env.example lists no retired contact state variables.\", },\n { ruleId: \"brandlab-source-dangerously-set-inner-html\", surface: \"security\", checkId: \"runtime-supported\", summary: \"No project-owned dangerouslySetInnerHTML; only SchemaScript and SafeRichText inject markup.\", },\n { ruleId: \"brandlab-source-public-secret\", surface: \"security\", checkId: \"runtime-supported\", summary: \"No API key, secret or token behind a NEXT_PUBLIC_ name.\", },\n { ruleId: \"brandlab-config-missing\", surface: \"routes\", checkId: \"route-identity\", summary: \"brandlab.config.ts exists.\", },\n { ruleId: \"brandlab-config-invalid\", surface: \"routes\", checkId: \"route-identity\", summary: \"brandlab.config.ts is a literal defineBrandlabProject with projectId.\", },\n { ruleId: \"brandlab-routes-catalogue\", surface: \"routes\", checkId: \"route-identity\", summary: \"Exactly one module declares the route catalogue with defineRouteCatalog.\", },\n { ruleId: \"brandlab-routes-location-estate\", surface: \"routes\", checkId: \"route-identity\", summary: \"A project that publishes locations declares them in src/data/locations/estate.ts with defineLocationEstate.\", },\n { ruleId: \"brandlab-redirects-table\", surface: \"routes\", checkId: \"route-identity\", summary: \"Exactly one module declares the redirect table with defineRedirects.\", },\n { ruleId: \"brandlab-contact-recipient-env\", surface: \"contact\", checkId: \"contact-runtime\", summary: \"The contact contract declares delivery.recipientEnv as a literal key.\", },\n { ruleId: \"brandlab-source-local-contact-delivery\", surface: \"contact\", checkId: \"contact-runtime\", summary: \"Email delivery is left to the shared contact runtime.\", },\n { ruleId: \"brandlab-source-local-contact-email-renderer\", surface: \"contact\", checkId: \"contact-runtime\", summary: \"Contact email rendering is left to the shared contact runtime.\", },\n { ruleId: \"brandlab-source-local-contact-attachments\", surface: \"contact\", checkId: \"contact-runtime\", summary: \"Attachment preparation is left to the shared contact runtime.\", },\n { ruleId: \"brandlab-source-contact-draft-persistence\", surface: \"contact\", checkId: \"contact-runtime\", summary: \"Contact details are never persisted in browser storage.\", },\n { ruleId: \"brandlab-source-retired-contact-state\", surface: \"contact\", checkId: \"contact-runtime\", summary: \"No retired contact state service variables in source.\", },\n { ruleId: \"brandlab-contact-provider-route\", surface: \"contact\", checkId: \"contact-provider-errors\", summary: \"POST /api/contact is created by the shared handler, so provider errors are handled by the runtime.\", },\n { ruleId: \"brandlab-analytics-pii-payload\", surface: \"analytics\", checkId: \"analytics-privacy\", summary: \"No lead fields, messages or attachment details in analytics payloads, and no project-set user_data.\", },\n { ruleId: \"brandlab-source-retired-analytics-event\", surface: \"analytics\", checkId: \"analytics-conversion\", summary: \"Only current event names are sent: contact_form for accepted enquiries and phone_link_click as a tap diagnostic.\", },\n { ruleId: \"brandlab-source-local-google-tag-bootstrap\", surface: \"analytics\", checkId: \"analytics-conversion\", summary: \"The Google tag bootstrap is owned by the shared runtime.\", },\n { ruleId: \"brandlab-analytics-google-tag-owner\", surface: \"analytics\", checkId: \"analytics-conversion\", summary: \"Exactly one BrandlabGoogleTag, rendered by the root layout.\", },\n { ruleId: \"brandlab-analytics-google-tag-consent\", surface: \"analytics\", checkId: \"analytics-privacy\", summary: \"BrandlabGoogleTag takes its ad_user_data consent default from the analytics binding: no adUserData attribute.\", },\n { ruleId: \"brandlab-analytics-contract\", surface: \"analytics\", checkId: \"analytics-conversion\", summary: \"Exactly one module declares the analytics binding with defineBrandlabAnalytics.\", },\n { ruleId: \"brandlab-analytics-instrumentation\", surface: \"analytics\", checkId: \"analytics-conversion\", summary: \"src/instrumentation-client.ts calls installBrandlabInstrumentation, which reports one phone_link_click per tap.\", },\n { ruleId: \"brandlab-analytics-retired-phone-api\", surface: \"analytics\", checkId: \"analytics-conversion\", summary: \"No trackPhoneCall; taps are reported once as phone_link_click.\", },\n { ruleId: \"brandlab-analytics-web-vitals\", surface: \"analytics\", checkId: \"analytics-conversion\", summary: \"No web-vitals reporter, web_vital event or webVitals flag.\", },\n { ruleId: \"brandlab-robots-package-route\", surface: \"robots\", checkId: \"search-routing\", summary: \"robots is a thin binding of @brandlab-digital/site-next/robots with no static public/robots.txt.\", },\n { ruleId: \"brandlab-sitemap-package-route\", surface: \"sitemap\", checkId: \"search-routing\", summary: \"The sitemap route uses the shared sitemap API over the route catalogue, with no static public/sitemap.xml.\", },\n { ruleId: \"brandlab-sitemap-split-mode\", surface: \"sitemap\", checkId: \"search-routing\", summary: \"/sitemaps/[chunk] exists exactly when brandlab.config sets sitemap.mode: 'split'.\", },\n { ruleId: \"brandlab-metadata-route-builder\", surface: \"metadata\", checkId: \"search-routing\", summary: \"Page metadata comes from createRouteMetadataBuilder(site, routes).\", },\n { ruleId: \"brandlab-site-identity\", surface: \"metadata\", checkId: \"search-routing\", summary: \"Exactly one module declares the site identity (canonical URL, locale, titles) with defineBrandlabSite.\", },\n { ruleId: \"brandlab-source-raw-json-ld\", surface: \"schema\", checkId: \"structured-data\", summary: \"JSON-LD is rendered only by the shared schema component.\", },\n { ruleId: \"brandlab-source-self-serving-rating-schema\", surface: \"schema\", checkId: \"structured-data\", summary: \"No self-serving AggregateRating schema.\", },\n { ruleId: \"brandlab-source-faq-howto-schema\", surface: \"schema\", checkId: \"structured-data\", summary: \"No FAQPage or HowTo markup.\", },\n { ruleId: \"brandlab-sitemap-build-time-lastmod\", surface: \"sitemap\", checkId: \"search-routing\", summary: \"Sitemap lastmod comes from content dates (lastSignificantChange), never new Date() or Date.now().\", },\n { ruleId: \"brandlab-source-synthetic-offer-schema\", surface: \"schema\", checkId: \"structured-data\", summary: \"No invented Offer markup.\", },\n { ruleId: \"brandlab-source-local-google-reviews-fetch\", surface: \"reviews\", checkId: \"structured-data\", summary: \"Google Places reviews are fetched only by the shared review runtime.\", },\n { ruleId: \"brandlab-business-facts\", surface: \"business\", checkId: \"business-identity\", summary: \"Exactly one module declares the business facts with defineBrandlabBusiness.\", },\n { ruleId: \"brandlab-content-implementation-wording\", surface: \"content\", checkId: \"public-output-safety\", summary: \"Everything that renders publicly (pages, components, metadata, schema, alt text, MDX, Markdown and JSON content) carries finished copy, not template, helper, scaffold or placeholder wording.\", },\n { ruleId: \"brandlab-source-root-missing\", surface: \"source\", checkId: \"source-safety\", summary: \"Project source sits under a recognised root so the source rules can run.\", },\n { ruleId: \"brandlab-source-platform-reimplementation\", surface: \"source\", checkId: \"source-safety\", summary: \"Protected platform surfaces (SchemaScript, SafeRichText, contact, sitemap, analytics APIs) are imported, not redeclared.\", },\n { ruleId: \"brandlab-source-retired-api\", surface: \"source\", checkId: \"source-safety\", summary: \"No API, option or configuration key removed in 3.0 (TrackedTelephoneLink, shouldIndexSite, buildRobotsMetadata, buildSeoMetadata and the duplicate metadata builders, isBrandlabProductionDeployment, resolveBrowserAnalyticsConfig, resolveBrandlabGoogleTagConfig, the contact submission controller and its lead-tracking helpers (use useBrandlabContactForm), header profiles and isProduction, xRobotsTag, contentSecurityPolicyMode, leadDiagnostics, ALLOW_INDEXING, NEXT_PUBLIC_SITE_URL, profile, routes.aliases).\", },\n { ruleId: \"brandlab-ci-workflow-pinned\", surface: \"project-verification\", checkId: \"project-build\", summary: \"Every reused workflow and action is pinned to a 40-character commit SHA.\", },\n { ruleId: \"brandlab-deployment-vercelignore-lockfile\", surface: \"deployment\", checkId: \"deployment-binding\", summary: \".vercelignore never excludes package.json or package-lock.json.\", },\n] as const satisfies readonly BrandlabStaticRule[];\n\n/** Whether a concrete rule ID (from a finding or evaluation) belongs to a registry entry. */\nexport function matchesBrandlabStaticRule(rule: BrandlabStaticRule, ruleId: string): boolean {\n if (rule.ruleId === ruleId) return true;\n if (!rule.ruleId.includes(\"<\")) return false;\n const stem = rule.ruleId.slice(0, rule.ruleId.indexOf(\"-<\"));\n const pattern = new RegExp(`^${rule.ruleId.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\").replace(/<[a-z]+>/g, \"[a-z0-9-]+\")}$`);\n return ruleId === stem || pattern.test(ruleId);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"rule-registry.js","sourceRoot":"","sources":["../src/rule-registry.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BrandlabVerificationCheckId } from \"./verification-policy.js\";\n\n/**\n * Every static rule the evaluator can run, the check it evaluates and what it\n * proves. `<placeholder>` segments stand for the concrete package, capability,\n * key or state named in each finding. The generated rule reference is built\n * from this list, and tests keep it identical to the evaluator.\n */\nexport interface BrandlabStaticRule {\n ruleId: string;\n surface: string;\n checkId: BrandlabVerificationCheckId;\n summary: string;\n}\n\nexport const BRANDLAB_STATIC_RULES = [\n { ruleId: \"brandlab-release-package-json-missing\", surface: \"release\", checkId: \"release-consistency\", summary: \"package.json is present and readable.\", },\n { ruleId: \"brandlab-release-installed-version-unresolved\", surface: \"release\", checkId: \"release-consistency\", summary: \"All four Brandlab packages are pinned to one exact release.\", },\n { ruleId: \"brandlab-release-canary\", surface: \"release\", checkId: \"release-consistency\", summary: \"A canary (X.Y.Z-canary.N) is reported as a warning, checked against its line's contract when present, and never counts as a published release.\", },\n { ruleId: \"brandlab-release-unsupported\", surface: \"release\", checkId: \"release-consistency\", summary: \"The installed release is the one this checker certifies.\", },\n { ruleId: \"brandlab-release-declared-installed-mismatch\", surface: \"release\", checkId: \"release-consistency\", summary: \"The declared and detected releases agree.\", },\n { ruleId: \"brandlab-release-package-lock-<state>\", surface: \"release\", checkId: \"release-consistency\", summary: \"A valid npm lockfile v2 or v3 is committed.\", },\n { ruleId: \"brandlab-release-package-pin-mismatch\", surface: \"release\", checkId: \"release-consistency\", summary: \"Each package is declared once and locked at the exact release.\", },\n { ruleId: \"brandlab-release-package-resolution-mismatch\", surface: \"release\", checkId: \"release-consistency\", summary: \"The lockfile resolves each package from the canonical npm registry with integrity.\", },\n { ruleId: \"brandlab-release-package-integrity-mismatch\", surface: \"release\", checkId: \"release-consistency\", summary: \"With --release-manifest, lockfile integrity equals the immutable release record.\", },\n { ruleId: \"brandlab-runtime-<package>\", surface: \"runtime\", checkId: \"runtime-supported\", summary: \"next, react, react-dom and typescript use versions the release permits.\", },\n { ruleId: \"brandlab-runtime-react-pair\", surface: \"runtime\", checkId: \"runtime-supported\", summary: \"react and react-dom are declared and locked at the same version.\", },\n { ruleId: \"brandlab-runtime-node\", surface: \"runtime\", checkId: \"runtime-supported\", summary: \"engines.node matches the release in package.json and the lockfile.\", },\n { ruleId: \"brandlab-runtime-package-manager\", surface: \"runtime\", checkId: \"runtime-supported\", summary: \"packageManager is the release's npm version.\", },\n { ruleId: \"brandlab-runtime-sharp\", surface: \"runtime\", checkId: \"runtime-supported\", summary: \"Sharp is pinned only by overrides.sharp with one lockfile resolution.\", },\n { ruleId: \"brandlab-runtime-image-initialisation\", surface: \"runtime\", checkId: \"runtime-supported\", summary: \"next.config imports the shared image-runtime guard first.\", },\n { ruleId: \"brandlab-runtime-next-config\", surface: \"runtime\", checkId: \"runtime-supported\", summary: \"next.config exports defineBrandlabNextConfig, which owns headers, image formats and Preview noindex.\", },\n { ruleId: \"brandlab-runtime-image-remote-patterns\", surface: \"runtime\", checkId: \"runtime-supported\", summary: \"Image remote patterns are https on public hosts (from 3.3.3 a production build refuses http and local ones, and wildcard hosts that admit a local address); any other wildcard host, or every path of another site's host, is a warning.\", },\n { ruleId: \"brandlab-environment-<capability>-<key>\", surface: \"environment\", checkId: \"runtime-supported\", summary: \".env.example documents each variable an enabled capability reads, including the contract's recipient key.\", },\n { ruleId: \"brandlab-environment-retired-contact-state\", surface: \"environment\", checkId: \"runtime-supported\", summary: \".env.example lists no retired contact state variables.\", },\n { ruleId: \"brandlab-source-dangerously-set-inner-html\", surface: \"security\", checkId: \"runtime-supported\", summary: \"No project-owned dangerouslySetInnerHTML; only SchemaScript and SafeRichText inject markup.\", },\n { ruleId: \"brandlab-source-public-secret\", surface: \"security\", checkId: \"runtime-supported\", summary: \"No API key, secret or token behind a NEXT_PUBLIC_ name.\", },\n { ruleId: \"brandlab-config-missing\", surface: \"routes\", checkId: \"route-identity\", summary: \"brandlab.config.ts exists.\", },\n { ruleId: \"brandlab-config-invalid\", surface: \"routes\", checkId: \"route-identity\", summary: \"brandlab.config.ts is a literal defineBrandlabProject with projectId.\", },\n { ruleId: \"brandlab-routes-catalogue\", surface: \"routes\", checkId: \"route-identity\", summary: \"Exactly one module declares the route catalogue with defineRouteCatalog.\", },\n { ruleId: \"brandlab-routes-location-estate\", surface: \"routes\", checkId: \"route-identity\", summary: \"A project that publishes locations declares them in src/data/locations/estate.ts with defineLocationEstate.\", },\n { ruleId: \"brandlab-redirects-table\", surface: \"routes\", checkId: \"route-identity\", summary: \"Exactly one module declares the redirect table with defineRedirects.\", },\n { ruleId: \"brandlab-contact-recipient-env\", surface: \"contact\", checkId: \"contact-runtime\", summary: \"The contact contract declares delivery.recipientEnv as a literal key.\", },\n { ruleId: \"brandlab-source-local-contact-delivery\", surface: \"contact\", checkId: \"contact-runtime\", summary: \"Email delivery is left to the shared contact runtime.\", },\n { ruleId: \"brandlab-source-local-contact-email-renderer\", surface: \"contact\", checkId: \"contact-runtime\", summary: \"Contact email rendering is left to the shared contact runtime.\", },\n { ruleId: \"brandlab-source-local-contact-attachments\", surface: \"contact\", checkId: \"contact-runtime\", summary: \"Attachment preparation is left to the shared contact runtime.\", },\n { ruleId: \"brandlab-source-contact-draft-persistence\", surface: \"contact\", checkId: \"contact-runtime\", summary: \"Contact details are never persisted in browser storage.\", },\n { ruleId: \"brandlab-source-retired-contact-state\", surface: \"contact\", checkId: \"contact-runtime\", summary: \"No retired contact state service variables in source.\", },\n { ruleId: \"brandlab-contact-provider-route\", surface: \"contact\", checkId: \"contact-provider-errors\", summary: \"POST /api/contact is created by the shared handler, so provider errors are handled by the runtime.\", },\n { ruleId: \"brandlab-analytics-pii-payload\", surface: \"analytics\", checkId: \"analytics-privacy\", summary: \"No lead fields, messages or attachment details in analytics payloads, and no project-set user_data.\", },\n { ruleId: \"brandlab-source-retired-analytics-event\", surface: \"analytics\", checkId: \"analytics-conversion\", summary: \"Only current event names are sent: contact_form for accepted enquiries and phone_link_click as a tap diagnostic.\", },\n { ruleId: \"brandlab-source-local-google-tag-bootstrap\", surface: \"analytics\", checkId: \"analytics-conversion\", summary: \"The Google tag bootstrap is owned by the shared runtime.\", },\n { ruleId: \"brandlab-analytics-google-tag-owner\", surface: \"analytics\", checkId: \"analytics-conversion\", summary: \"Exactly one BrandlabGoogleTag, rendered by the root layout.\", },\n { ruleId: \"brandlab-analytics-google-tag-consent\", surface: \"analytics\", checkId: \"analytics-privacy\", summary: \"BrandlabGoogleTag takes its ad_user_data consent default from the analytics binding: no adUserData attribute.\", },\n { ruleId: \"brandlab-analytics-contract\", surface: \"analytics\", checkId: \"analytics-conversion\", summary: \"Exactly one module declares the analytics binding with defineBrandlabAnalytics.\", },\n { ruleId: \"brandlab-analytics-instrumentation\", surface: \"analytics\", checkId: \"analytics-conversion\", summary: \"src/instrumentation-client.ts calls installBrandlabInstrumentation, which reports one phone_link_click per tap.\", },\n { ruleId: \"brandlab-analytics-retired-phone-api\", surface: \"analytics\", checkId: \"analytics-conversion\", summary: \"No trackPhoneCall; taps are reported once as phone_link_click.\", },\n { ruleId: \"brandlab-analytics-web-vitals\", surface: \"analytics\", checkId: \"analytics-conversion\", summary: \"No web-vitals reporter, web_vital event or webVitals flag.\", },\n { ruleId: \"brandlab-robots-package-route\", surface: \"robots\", checkId: \"search-routing\", summary: \"robots is a thin binding of @brandlab-digital/site-next/robots with no static public/robots.txt.\", },\n { ruleId: \"brandlab-sitemap-package-route\", surface: \"sitemap\", checkId: \"search-routing\", summary: \"The sitemap route uses the shared sitemap API over the route catalogue, with no static public/sitemap.xml.\", },\n { ruleId: \"brandlab-sitemap-split-mode\", surface: \"sitemap\", checkId: \"search-routing\", summary: \"/sitemaps/[chunk] exists exactly when brandlab.config sets sitemap.mode: 'split'.\", },\n { ruleId: \"brandlab-metadata-route-builder\", surface: \"metadata\", checkId: \"search-routing\", summary: \"Page metadata comes from createRouteMetadataBuilder(site, routes).\", },\n { ruleId: \"brandlab-site-identity\", surface: \"metadata\", checkId: \"search-routing\", summary: \"Exactly one module declares the site identity (canonical URL, locale, titles) with defineBrandlabSite.\", },\n { ruleId: \"brandlab-source-raw-json-ld\", surface: \"schema\", checkId: \"structured-data\", summary: \"JSON-LD is rendered only by the shared schema component.\", },\n { ruleId: \"brandlab-source-self-serving-rating-schema\", surface: \"schema\", checkId: \"structured-data\", summary: \"No self-serving AggregateRating schema.\", },\n { ruleId: \"brandlab-source-faq-howto-schema\", surface: \"schema\", checkId: \"structured-data\", summary: \"No FAQPage or HowTo markup.\", },\n { ruleId: \"brandlab-sitemap-build-time-lastmod\", surface: \"sitemap\", checkId: \"search-routing\", summary: \"Sitemap lastmod comes from content dates (lastSignificantChange), never new Date() or Date.now().\", },\n { ruleId: \"brandlab-source-synthetic-offer-schema\", surface: \"schema\", checkId: \"structured-data\", summary: \"No invented Offer markup.\", },\n { ruleId: \"brandlab-source-local-google-reviews-fetch\", surface: \"reviews\", checkId: \"structured-data\", summary: \"Google Places reviews are fetched only by the shared review runtime.\", },\n { ruleId: \"brandlab-business-facts\", surface: \"business\", checkId: \"business-identity\", summary: \"Exactly one module declares the business facts with defineBrandlabBusiness.\", },\n { ruleId: \"brandlab-content-implementation-wording\", surface: \"content\", checkId: \"public-output-safety\", summary: \"Everything that renders publicly (pages, components, metadata, schema, alt text, MDX, Markdown and JSON content) carries finished copy, not template, helper, scaffold or placeholder wording.\", },\n { ruleId: \"brandlab-source-root-missing\", surface: \"source\", checkId: \"source-safety\", summary: \"Project source sits under a recognised root so the source rules can run.\", },\n { ruleId: \"brandlab-source-platform-reimplementation\", surface: \"source\", checkId: \"source-safety\", summary: \"Protected platform surfaces (SchemaScript, SafeRichText, contact, sitemap, analytics APIs) are imported, not redeclared.\", },\n { ruleId: \"brandlab-source-retired-api\", surface: \"source\", checkId: \"source-safety\", summary: \"No API, option or configuration key removed in 3.0 (TrackedTelephoneLink, shouldIndexSite, buildRobotsMetadata, buildSeoMetadata and the duplicate metadata builders, isBrandlabProductionDeployment, resolveBrowserAnalyticsConfig, resolveBrandlabGoogleTagConfig, the contact submission controller and its lead-tracking helpers (use useBrandlabContactForm), header profiles and isProduction, xRobotsTag, contentSecurityPolicyMode, leadDiagnostics, ALLOW_INDEXING, NEXT_PUBLIC_SITE_URL, profile, routes.aliases).\", },\n { ruleId: \"brandlab-ci-workflow-pinned\", surface: \"project-verification\", checkId: \"project-build\", summary: \"Every reused workflow and action is pinned to a 40-character commit SHA.\", },\n { ruleId: \"brandlab-deployment-vercelignore-lockfile\", surface: \"deployment\", checkId: \"deployment-binding\", summary: \".vercelignore never excludes package.json or package-lock.json.\", },\n] as const satisfies readonly BrandlabStaticRule[];\n\n/** Whether a concrete rule ID (from a finding or evaluation) belongs to a registry entry. */\nexport function matchesBrandlabStaticRule(rule: BrandlabStaticRule, ruleId: string): boolean {\n if (rule.ruleId === ruleId) return true;\n if (!rule.ruleId.includes(\"<\")) return false;\n const stem = rule.ruleId.slice(0, rule.ruleId.indexOf(\"-<\"));\n const pattern = new RegExp(`^${rule.ruleId.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\").replace(/<[a-z]+>/g, \"[a-z0-9-]+\")}$`);\n return ruleId === stem || pattern.test(ruleId);\n}\n"]}
|
|
@@ -25,6 +25,11 @@ export interface SiteSystemCheck {
|
|
|
25
25
|
readonly from: `3.${number}.0`;
|
|
26
26
|
readonly kind: SiteSystemCheckKind;
|
|
27
27
|
readonly summary: string;
|
|
28
|
+
/**
|
|
29
|
+
* `launch`: a not-run result blocks only under `brandlab-ready --launch`, where it counts as a failure. For checks
|
|
30
|
+
* that need production values in the shell (H13), so a CI run reports them as not run without failing the tier.
|
|
31
|
+
*/
|
|
32
|
+
readonly notRunBlocks?: "launch";
|
|
28
33
|
}
|
|
29
34
|
export declare const SITE_SYSTEM_CHECKS: readonly [{
|
|
30
35
|
readonly id: "N1";
|
|
@@ -302,12 +307,25 @@ export declare const SITE_SYSTEM_CHECKS: readonly [{
|
|
|
302
307
|
readonly from: "3.11.0";
|
|
303
308
|
readonly kind: "static";
|
|
304
309
|
readonly summary: "No image in /public carries location metadata.";
|
|
310
|
+
}, {
|
|
311
|
+
readonly id: "H13";
|
|
312
|
+
readonly tier: "enquiry";
|
|
313
|
+
readonly from: "3.14.0";
|
|
314
|
+
readonly kind: "static";
|
|
315
|
+
readonly notRunBlocks: "launch";
|
|
316
|
+
readonly summary: "The business inbox can receive enquiries: a real sender (no .invalid, example or sandbox domain), MX records for the inbox, the sender domain verified in Resend and the inbox not on Resend's suppression list (not run without the inbox variable and a full-access Resend key in the shell, which blocks only at launch).";
|
|
305
317
|
}, {
|
|
306
318
|
readonly id: "K12";
|
|
307
319
|
readonly tier: "full";
|
|
308
320
|
readonly from: "3.12.0";
|
|
309
321
|
readonly kind: "rendered";
|
|
310
322
|
readonly summary: "Section manifest: every required section rendered or skipped with a data-backed reason; conditional sections render when their data exists; canonical or recorded order.";
|
|
323
|
+
}, {
|
|
324
|
+
readonly id: "K12-slots";
|
|
325
|
+
readonly tier: "full";
|
|
326
|
+
readonly from: "3.14.0";
|
|
327
|
+
readonly kind: "rendered";
|
|
328
|
+
readonly summary: "Trade lines inside sections (matrix part B): for trees, the council permit note in LocalFacts on suburb and service-in-suburb pages and the qualifications and insurance lines on the about page, or a data-backed reason they are hidden.";
|
|
311
329
|
}, {
|
|
312
330
|
readonly id: "E5";
|
|
313
331
|
readonly tier: "full";
|
|
@@ -386,6 +404,12 @@ export declare const SITE_SYSTEM_CHECKS: readonly [{
|
|
|
386
404
|
readonly from: "3.12.0";
|
|
387
405
|
readonly kind: "static";
|
|
388
406
|
readonly summary: "No location route is noindex or left out of the sitemap unless the recorded wave schedule dates it (Romie's 20 Oct decision: every suburb page stays indexed).";
|
|
407
|
+
}, {
|
|
408
|
+
readonly id: "E1-pattern";
|
|
409
|
+
readonly tier: "full";
|
|
410
|
+
readonly from: "3.14.0";
|
|
411
|
+
readonly kind: "rendered";
|
|
412
|
+
readonly summary: "Location pages outside the recorded titles have the H1 \"{Service} {Place}\" (no \"in\", no \"the\") and a title that starts with it, at most 60 characters.";
|
|
389
413
|
}, {
|
|
390
414
|
readonly id: "W3";
|
|
391
415
|
readonly tier: "full";
|
|
@@ -414,7 +438,8 @@ export declare function siteSystemCheckBlocks(check: Pick<SiteSystemCheck, "id"
|
|
|
414
438
|
/** One result of one check, from any runner. `brandlab-ready` merges them into the ready report. */
|
|
415
439
|
export interface SiteSystemFinding {
|
|
416
440
|
readonly checkId: SiteSystemCheckId;
|
|
417
|
-
|
|
441
|
+
/** `not-run`: the rule could not judge the check here (a missing key or input); it names what to supply. */
|
|
442
|
+
readonly status: "pass" | "fail" | "not-run" | "not-applicable";
|
|
418
443
|
/** The page path or file the result is about, when it is about one. */
|
|
419
444
|
readonly target?: string;
|
|
420
445
|
/** One plain sentence: what passed or what is wrong and where. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../../src/site-system/checks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,eAAO,MAAM,iBAAiB,uCAAwC,CAAC;AACvE,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhE,kFAAkF;AAClF,MAAM,MAAM,oBAAoB,GAAG,cAAc,GAAG,WAAW,CAAC;AAEhE,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE/E,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,EAAE,KAAK,MAAM,IAAI,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../../src/site-system/checks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,eAAO,MAAM,iBAAiB,uCAAwC,CAAC;AACvE,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhE,kFAAkF;AAClF,MAAM,MAAM,oBAAoB,GAAG,cAAc,GAAG,WAAW,CAAC;AAEhE,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE/E,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,EAAE,KAAK,MAAM,IAAI,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,QAAQ,CAAC;CAClC;AAED,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyEgB,CAAC;AAEhD,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC;AAI1E,8DAA8D;AAC9D,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAG7D;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,IAAI,CAAC,eAAe,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC,EACpD,IAAI,EAAE;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GAClE,OAAO,CAIT;AAED,oGAAoG;AACpG,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;IACpC,4GAA4G;IAC5G,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,gBAAgB,CAAC;IAChE,uEAAuE;IACvE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,kEAAkE;IAClE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,4FAA4F;IAC5F,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAC;CAC/B"}
|
|
@@ -63,8 +63,10 @@ export const SITE_SYSTEM_CHECKS = [
|
|
|
63
63
|
{ id: "T7", tier: "enquiry", from: "3.11.0", kind: "rendered", summary: "No image is the main image of two pages." },
|
|
64
64
|
{ id: "T8", tier: "enquiry", from: "3.11.0", kind: "rendered", summary: 'Prices: GST flag set; no "+ GST" or "from $X" teasers on cards and menus; one band per job site-wide.' },
|
|
65
65
|
{ id: "T9", tier: "enquiry", from: "3.11.0", kind: "static", summary: "No image in /public carries location metadata." },
|
|
66
|
+
{ id: "H13", tier: "enquiry", from: "3.14.0", kind: "static", notRunBlocks: "launch", summary: "The business inbox can receive enquiries: a real sender (no .invalid, example or sandbox domain), MX records for the inbox, the sender domain verified in Resend and the inbox not on Resend's suppression list (not run without the inbox variable and a full-access Resend key in the shell, which blocks only at launch)." },
|
|
66
67
|
// full: page families, location estates, section manifests, links and the data contract
|
|
67
68
|
{ id: "K12", tier: "full", from: "3.12.0", kind: "rendered", summary: "Section manifest: every required section rendered or skipped with a data-backed reason; conditional sections render when their data exists; canonical or recorded order." },
|
|
69
|
+
{ id: "K12-slots", tier: "full", from: "3.14.0", kind: "rendered", summary: "Trade lines inside sections (matrix part B): for trees, the council permit note in LocalFacts on suburb and service-in-suburb pages and the qualifications and insurance lines on the about page, or a data-backed reason they are hidden." },
|
|
68
70
|
{ id: "E5", tier: "full", from: "3.12.0", kind: "static", summary: "No orphan indexable pages, from the route catalogue and link data." },
|
|
69
71
|
{ id: "E10", tier: "full", from: "3.12.0", kind: "static", summary: "Phrase-owner uniqueness in strategy data; no service-in-suburb page for the suburb page phrase; no service-region hub for the main trade." },
|
|
70
72
|
{ id: "L3", tier: "full", from: "3.12.0", kind: "static", summary: "Neighbours by real distance." },
|
|
@@ -78,6 +80,7 @@ export const SITE_SYSTEM_CHECKS = [
|
|
|
78
80
|
{ id: "W9", tier: "full", from: "3.13.0", kind: "journey", summary: "URL variants: an unknown slug in each family answers the shared 404, the uppercase slug the same 404 or one permanent redirect to its lowercase form; a tracking query serves the same cached page as the clean URL." },
|
|
79
81
|
{ id: "W9-params", tier: "full", from: "3.13.0", kind: "static", summary: "Pages under a dynamic route never read searchParams, so a query string cannot make an estate page dynamic." },
|
|
80
82
|
{ id: "LOC-INDEX", tier: "full", from: "3.12.0", kind: "static", summary: "No location route is noindex or left out of the sitemap unless the recorded wave schedule dates it (Romie's 20 Oct decision: every suburb page stays indexed)." },
|
|
83
|
+
{ id: "E1-pattern", tier: "full", from: "3.14.0", kind: "rendered", summary: 'Location pages outside the recorded titles have the H1 "{Service} {Place}" (no "in", no "the") and a title that starts with it, at most 60 characters.' },
|
|
81
84
|
{ id: "W3", tier: "full", from: "3.13.0", kind: "static", summary: "No estate family (suburb, service-in-suburb, region, council) refreshes more often than every 7 days unless siteSystem.refreshExceptions records the reason and a decision id." },
|
|
82
85
|
// new builds and redesigns
|
|
83
86
|
{ id: "D4", tier: "new-build", from: "3.8.0", kind: "static", summary: "Same-trade distinctness: at least four of seven look levers differ from every listed competitor (advisory in 3.8.0, blocking from 3.9.0)." },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checks.js","sourceRoot":"","sources":["../../src/site-system/checks.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The Site System v2 ready gate: every check, the adoption tier it blocks at and the release that brings it.\n *\n * A site declares `siteSystem: { tier }` in brandlab.config.ts. Checks of that tier and the tiers below it block;\n * checks of higher tiers report without blocking. A check blocks only from the release named here, so new checks\n * arrive with version bumps and never turn the fleet red at once. Holdouts use the project's Romie-owned\n * `exceptions` record. D6 (leave reviews as they are) removes every review-exclusion clause; D7 (no call tracking)\n * means no number-swap check.\n *\n * `kind` says where a check runs:\n * - `journey`: the Playwright site-system journeys (`defineBrandlabSiteSystemTests`), in the site's e2e run;\n * - `rendered`: rules over the built site's server HTML and assets (`brandlab-ready` reads them);\n * - `static`: source and data rules (`brandlab-verify` and `brandlab-ready`);\n * - `record`: launch-day and human steps recorded with `brandlab-ready record <id> --evidence <ref>`.\n */\n\nexport const SITE_SYSTEM_TIERS = [\"shell\", \"enquiry\", \"full\"] as const;\nexport type SiteSystemTier = (typeof SITE_SYSTEM_TIERS)[number];\n\n/** The design check D4 blocks every new build and redesign, whatever its tier. */\nexport type SiteSystemCheckScope = SiteSystemTier | \"new-build\";\n\nexport type SiteSystemCheckKind = \"journey\" | \"rendered\" | \"static\" | \"record\";\n\nexport interface SiteSystemCheck {\n readonly id: string;\n readonly tier: SiteSystemCheckScope;\n /** The first release in which the check blocks at its tier. */\n readonly from: `3.${number}.0`;\n readonly kind: SiteSystemCheckKind;\n readonly summary: string;\n}\n\nexport const SITE_SYSTEM_CHECKS = [\n // shell: header, nav, call bar, placements, crawlable links, contrast and targets, call links, budgets, legal\n { id: \"N1\", tier: \"shell\", from: \"3.9.0\", kind: \"rendered\", summary: \"Required nav links, About in the first two, services before Areas, Contact last, labels from the closed list, recorded orders kept.\" },\n { id: \"N2\", tier: \"shell\", from: \"3.8.0\", kind: \"rendered\", summary: \"Every dropdown link and hub link is an <a href> in the server HTML.\" },\n { id: \"N3\", tier: \"shell\", from: \"3.8.0\", kind: \"journey\", summary: \"Hover opens after a short delay and a diagonal path stays open; mouse-out closes; nothing sticks open.\" },\n { id: \"N4\", tier: \"shell\", from: \"3.8.0\", kind: \"journey\", summary: \"A chevron click after hover keeps the panel open; a link click closes it; click, Enter and outside click work.\" },\n { id: \"N5\", tier: \"shell\", from: \"3.8.0\", kind: \"journey\", summary: \"Keyboard and ARIA: aria-expanded follows the panel, Arrow keys move, Escape closes and returns focus; axe passes open and closed.\" },\n { id: \"N6\", tier: \"shell\", from: \"3.8.0\", kind: \"journey\", summary: \"The header stays at the top with the phone and quote visible at every desktop width; the compact band shows them from 1024 to 1279 px.\" },\n { id: \"N8\", tier: \"shell\", from: \"3.9.0\", kind: \"journey\", summary: \"The drawer is a modal dialog that traps focus and resets; the call bar uses placement fab; back-to-top appears (from 3.11.0).\" },\n { id: \"K1\", tier: \"shell\", from: \"3.9.0\", kind: \"rendered\", summary: \"Shared components in use for the parts the tier covers (data-bl present); no literal tel: outside PhoneLink.\" },\n { id: \"K3\", tier: \"shell\", from: \"3.8.0\", kind: \"journey\", summary: \"Text contrast 4.5:1 and non-text 3:1 in the browser.\" },\n { id: \"K4\", tier: \"shell\", from: \"3.8.0\", kind: \"journey\", summary: \"Targets at least 24 px, and 44 px for primary actions (call, quote, menu).\" },\n { id: \"K5\", tier: \"shell\", from: \"3.8.0\", kind: \"journey\", summary: \"Focus is never fully hidden by the sticky header or call bar at 390 px, in Chromium and WebKit.\" },\n { id: \"K6\", tier: \"shell\", from: \"3.8.0\", kind: \"journey\", summary: \"Phone and quote in the same relative order on every page, in the header, hero and call bar.\" },\n { id: \"K7\", tier: \"shell\", from: \"3.8.0\", kind: \"rendered\", summary: \"Dropdown links, accordion and tab panels and full review text are in the server HTML.\" },\n { id: \"K10\", tier: \"shell\", from: \"3.8.0\", kind: \"record\", summary: \"Adoption parity in the lenient harness: no section, link or text lost against the baseline.\" },\n { id: \"C4\", tier: \"shell\", from: \"3.8.0\", kind: \"journey\", summary: \"Phone taps report an allowed placement (header, footer, hero, cta, fab, contact, location, page).\" },\n { id: \"C5\", tier: \"shell\", from: \"3.8.0\", kind: \"rendered\", summary: \"Call-to-action labels come from the closed list or a recorded label.\" },\n { id: \"C9\", tier: \"shell\", from: \"3.8.0\", kind: \"rendered\", summary: \"No interstitial overlay in the first screen.\" },\n { id: \"C10\", tier: \"shell\", from: \"3.8.0\", kind: \"rendered\", summary: \"Every tel: href is E.164 (national digits for 13, 1300 and 1800) and matches the evidence-file phone.\" },\n { id: \"E1\", tier: \"shell\", from: \"3.8.0\", kind: \"static\", summary: \"Title patterns on new or changed URLs; recorded titles unchanged.\" },\n { id: \"E2\", tier: \"shell\", from: \"3.8.0\", kind: \"rendered\", summary: \"Exactly one H1 on every page, rendered once.\" },\n { id: \"E8\", tier: \"shell\", from: \"3.8.0\", kind: \"rendered\", summary: \"No banned phrase from any of the three layers, environmental claims included.\" },\n { id: \"T3\", tier: \"shell\", from: \"3.8.0\", kind: \"rendered\", summary: \"A licence line renders wherever licensed work is advertised, with the licensee where it differs.\" },\n { id: \"T4\", tier: \"shell\", from: \"3.8.0\", kind: \"rendered\", summary: \"No hard-coded rating or review numbers; proof claims resolve to renderable evidence.\" },\n { id: \"T11\", tier: \"shell\", from: \"3.8.0\", kind: \"static\", summary: \"No page for work over $5,000 outside the licence classes held; licence conditions carried.\" },\n { id: \"X1\", tier: \"shell\", from: \"3.8.0\", kind: \"record\", summary: \"Legacy URLs answer 200 or one redirect hop; earning-URL depth, titles and dollar figures kept.\" },\n { id: \"B1\", tier: \"shell\", from: \"3.8.0\", kind: \"rendered\", summary: \"Lab budgets: JavaScript, third-party requests, hero image and HTML within budget; no unrecorded chat widget, pixel, heatmap or tag manager.\" },\n { id: \"L10-hero\", tier: \"shell\", from: \"3.8.0\", kind: \"rendered\", summary: 'No kilometre figures, \"km from\" or \"based in\" in hero copy.' },\n { id: \"W2\", tier: \"shell\", from: \"3.13.0\", kind: \"journey\", summary: \"Prefetch by link role at 390 x 844 and 1440 x 900: at most 8 pages on landing and 12 after a full scroll; none from footer, area, nearby, map or finder links, hidden links or the current page; prefetch bytes above twice the page's HTML warn.\" },\n { id: \"W5\", tier: \"shell\", from: \"3.13.0\", kind: \"static\", summary: \"vercel.json regions equal hosting.originRegion (syd1 by default); any other region has an origin-region-v1 decision whose reviewBy has not passed.\" },\n { id: \"W10\", tier: \"shell\", from: \"3.13.0\", kind: \"rendered\", summary: \"robots.txt and the recorded firewall rules leave every search and answer crawler open; no Crawl-delay for them.\" },\n\n // enquiry: the form, thank-you page, reviews, proof strip, footer, CTA band, contact page, prices, media, density\n { id: \"C1\", tier: \"enquiry\", from: \"3.8.0\", kind: \"journey\", summary: \"Money pages: the form in the first section; at 390 x 844 the H1, a call and a quote action in the first viewport; at 1440 x 900 the form.\" },\n { id: \"C2\", tier: \"enquiry\", from: \"3.8.0\", kind: \"rendered\", summary: 'Form layout and labels; phone and email required; no helper or reassurance lines, no \"(required)\", no job select.' },\n { id: \"E9\", tier: \"enquiry\", from: \"3.8.0\", kind: \"rendered\", summary: \"Every cost guide carries at least 8 dollar figures in a renderable price state.\" },\n { id: \"T5\", tier: \"enquiry\", from: \"3.8.0\", kind: \"rendered\", summary: \"Reviews from the feed, with Google's rating, count and link beside any selection; none on the contact page; no empty reviews section.\" },\n { id: \"K8\", tier: \"enquiry\", from: \"3.8.0\", kind: \"rendered\", summary: \"Section contract: no empty section, one H2 each, at most one band tone, neighbours differ, proof within the first five sections.\" },\n { id: \"C7\", tier: \"enquiry\", from: \"3.10.0\", kind: \"rendered\", summary: \"Thank-you page: a reply time, a tel: link and noindex, follow.\" },\n { id: \"C8\", tier: \"enquiry\", from: \"3.10.0\", kind: \"rendered\", summary: \"Forgiving form: tolerant phone input (13, 1300 and 1800 too), autocomplete tokens, no capture on the photo input.\" },\n { id: \"C11\", tier: \"enquiry\", from: \"3.10.0\", kind: \"static\", summary: \"The test marker is stripped before delivery and reporting; /api/contact is rate-limited.\" },\n { id: \"N9\", tier: \"enquiry\", from: \"3.11.0\", kind: \"rendered\", summary: 'Footer content: column 1 brand, licences, socials and contact; services, areas and company columns; © name, ABN and legal links; no CTA, \"based in\", hours or guides column.' },\n { id: \"K2\", tier: \"enquiry\", from: \"3.11.0\", kind: \"rendered\", summary: \"Every rendered shared component has a skin entry; no reference-skin class ships.\" },\n { id: \"K11\", tier: \"enquiry\", from: \"3.11.0\", kind: \"rendered\", summary: \"Density: no section with more than one H2, more than 8 cards or more than 2 calls to action; measure and section padding within limits.\" },\n { id: \"K12-contact\", tier: \"enquiry\", from: \"3.11.0\", kind: \"rendered\", summary: \"The contact page is the page header, then the contact block, and nothing else.\" },\n { id: \"T6\", tier: \"enquiry\", from: \"3.11.0\", kind: \"static\", summary: \"Every image has a media.ts entry with provenance.\" },\n { id: \"T7\", tier: \"enquiry\", from: \"3.11.0\", kind: \"rendered\", summary: \"No image is the main image of two pages.\" },\n { id: \"T8\", tier: \"enquiry\", from: \"3.11.0\", kind: \"rendered\", summary: 'Prices: GST flag set; no \"+ GST\" or \"from $X\" teasers on cards and menus; one band per job site-wide.' },\n { id: \"T9\", tier: \"enquiry\", from: \"3.11.0\", kind: \"static\", summary: \"No image in /public carries location metadata.\" },\n\n // full: page families, location estates, section manifests, links and the data contract\n { id: \"K12\", tier: \"full\", from: \"3.12.0\", kind: \"rendered\", summary: \"Section manifest: every required section rendered or skipped with a data-backed reason; conditional sections render when their data exists; canonical or recorded order.\" },\n { id: \"E5\", tier: \"full\", from: \"3.12.0\", kind: \"static\", summary: \"No orphan indexable pages, from the route catalogue and link data.\" },\n { id: \"E10\", tier: \"full\", from: \"3.12.0\", kind: \"static\", summary: \"Phrase-owner uniqueness in strategy data; no service-in-suburb page for the suburb page phrase; no service-region hub for the main trade.\" },\n { id: \"L3\", tier: \"full\", from: \"3.12.0\", kind: \"static\", summary: \"Neighbours by real distance.\" },\n { id: \"L4\", tier: \"full\", from: \"3.12.0\", kind: \"rendered\", summary: \"No copy rotated by page address, no name-swapped FAQs, no other suburb's job without the nearby label.\" },\n { id: \"L6\", tier: \"full\", from: \"3.12.0\", kind: \"static\", summary: \"Location pages have 6 or more inbound links from 3 or more page types.\" },\n { id: \"L7\", tier: \"full\", from: \"3.12.0\", kind: \"static\", summary: \"Location pages are 3 clicks or fewer from home.\" },\n { id: \"L8\", tier: \"full\", from: \"3.12.0\", kind: \"static\", summary: \"A hub per family per region.\" },\n { id: \"L9\", tier: \"full\", from: \"3.12.0\", kind: \"rendered\", summary: \"Data contract on service-in-suburb pages: typical prices or the cost-guide link, reviews or their fallback, the quote path (form with the suburb prefilled, phone, call bar); the nearby job card or none.\" },\n { id: \"L10\", tier: \"full\", from: \"3.12.0\", kind: \"rendered\", summary: 'No kilometre figures, \"km from\", \"based in\" or year stamps as local detail in location copy.' },\n { id: \"S4\", tier: \"full\", from: \"3.12.0\", kind: \"static\", summary: \"No hand-written per-service or per-suburb files; no dynamic route with zero pages.\" },\n { id: \"W9\", tier: \"full\", from: \"3.13.0\", kind: \"journey\", summary: \"URL variants: an unknown slug in each family answers the shared 404, the uppercase slug the same 404 or one permanent redirect to its lowercase form; a tracking query serves the same cached page as the clean URL.\" },\n { id: \"W9-params\", tier: \"full\", from: \"3.13.0\", kind: \"static\", summary: \"Pages under a dynamic route never read searchParams, so a query string cannot make an estate page dynamic.\" },\n { id: \"LOC-INDEX\", tier: \"full\", from: \"3.12.0\", kind: \"static\", summary: \"No location route is noindex or left out of the sitemap unless the recorded wave schedule dates it (Romie's 20 Oct decision: every suburb page stays indexed).\" },\n { id: \"W3\", tier: \"full\", from: \"3.13.0\", kind: \"static\", summary: \"No estate family (suburb, service-in-suburb, region, council) refreshes more often than every 7 days unless siteSystem.refreshExceptions records the reason and a decision id.\" },\n\n // new builds and redesigns\n { id: \"D4\", tier: \"new-build\", from: \"3.8.0\", kind: \"static\", summary: \"Same-trade distinctness: at least four of seven look levers differ from every listed competitor (advisory in 3.8.0, blocking from 3.9.0).\" },\n] as const satisfies readonly SiteSystemCheck[];\n\nexport type SiteSystemCheckId = (typeof SITE_SYSTEM_CHECKS)[number][\"id\"];\n\nconst TIER_RANK: Record<SiteSystemTier, number> = { shell: 0, enquiry: 1, full: 2 };\n\n/** A release as one comparable number: \"3.8.0\" < \"3.10.0\". */\nexport function siteSystemReleaseRank(version: string): number {\n const [major = 0, minor = 0, patch = 0] = version.split(/[.-]/).map((part) => Number.parseInt(part, 10) || 0);\n return major * 1_000_000 + minor * 1_000 + patch;\n}\n\n/**\n * Whether a check blocks for a site at `tier` on `release`. Checks of higher tiers, and checks newer than the\n * installed release, report without blocking. D4 blocks new builds and redesigns from 3.9.0 whatever their tier.\n */\nexport function siteSystemCheckBlocks(\n check: Pick<SiteSystemCheck, \"id\" | \"tier\" | \"from\">,\n site: { tier: SiteSystemTier; release: string; newBuild?: boolean },\n): boolean {\n if (check.tier === \"new-build\") return site.newBuild === true && siteSystemReleaseRank(site.release) >= siteSystemReleaseRank(\"3.9.0\");\n if (siteSystemReleaseRank(site.release) < siteSystemReleaseRank(check.from)) return false;\n return TIER_RANK[check.tier] <= TIER_RANK[site.tier];\n}\n\n/** One result of one check, from any runner. `brandlab-ready` merges them into the ready report. */\nexport interface SiteSystemFinding {\n readonly checkId: SiteSystemCheckId;\n readonly status: \"pass\" | \"fail\" | \"not-applicable\";\n /** The page path or file the result is about, when it is about one. */\n readonly target?: string;\n /** One plain sentence: what passed or what is wrong and where. */\n readonly message: string;\n /** A warning never blocks: the check still passes and the report shows \"pass (warning)\". */\n readonly severity?: \"warning\";\n}\n"]}
|
|
1
|
+
{"version":3,"file":"checks.js","sourceRoot":"","sources":["../../src/site-system/checks.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The Site System v2 ready gate: every check, the adoption tier it blocks at and the release that brings it.\n *\n * A site declares `siteSystem: { tier }` in brandlab.config.ts. Checks of that tier and the tiers below it block;\n * checks of higher tiers report without blocking. A check blocks only from the release named here, so new checks\n * arrive with version bumps and never turn the fleet red at once. Holdouts use the project's Romie-owned\n * `exceptions` record. D6 (leave reviews as they are) removes every review-exclusion clause; D7 (no call tracking)\n * means no number-swap check.\n *\n * `kind` says where a check runs:\n * - `journey`: the Playwright site-system journeys (`defineBrandlabSiteSystemTests`), in the site's e2e run;\n * - `rendered`: rules over the built site's server HTML and assets (`brandlab-ready` reads them);\n * - `static`: source and data rules (`brandlab-verify` and `brandlab-ready`);\n * - `record`: launch-day and human steps recorded with `brandlab-ready record <id> --evidence <ref>`.\n */\n\nexport const SITE_SYSTEM_TIERS = [\"shell\", \"enquiry\", \"full\"] as const;\nexport type SiteSystemTier = (typeof SITE_SYSTEM_TIERS)[number];\n\n/** The design check D4 blocks every new build and redesign, whatever its tier. */\nexport type SiteSystemCheckScope = SiteSystemTier | \"new-build\";\n\nexport type SiteSystemCheckKind = \"journey\" | \"rendered\" | \"static\" | \"record\";\n\nexport interface SiteSystemCheck {\n readonly id: string;\n readonly tier: SiteSystemCheckScope;\n /** The first release in which the check blocks at its tier. */\n readonly from: `3.${number}.0`;\n readonly kind: SiteSystemCheckKind;\n readonly summary: string;\n /**\n * `launch`: a not-run result blocks only under `brandlab-ready --launch`, where it counts as a failure. For checks\n * that need production values in the shell (H13), so a CI run reports them as not run without failing the tier.\n */\n readonly notRunBlocks?: \"launch\";\n}\n\nexport const SITE_SYSTEM_CHECKS = [\n // shell: header, nav, call bar, placements, crawlable links, contrast and targets, call links, budgets, legal\n { id: \"N1\", tier: \"shell\", from: \"3.9.0\", kind: \"rendered\", summary: \"Required nav links, About in the first two, services before Areas, Contact last, labels from the closed list, recorded orders kept.\" },\n { id: \"N2\", tier: \"shell\", from: \"3.8.0\", kind: \"rendered\", summary: \"Every dropdown link and hub link is an <a href> in the server HTML.\" },\n { id: \"N3\", tier: \"shell\", from: \"3.8.0\", kind: \"journey\", summary: \"Hover opens after a short delay and a diagonal path stays open; mouse-out closes; nothing sticks open.\" },\n { id: \"N4\", tier: \"shell\", from: \"3.8.0\", kind: \"journey\", summary: \"A chevron click after hover keeps the panel open; a link click closes it; click, Enter and outside click work.\" },\n { id: \"N5\", tier: \"shell\", from: \"3.8.0\", kind: \"journey\", summary: \"Keyboard and ARIA: aria-expanded follows the panel, Arrow keys move, Escape closes and returns focus; axe passes open and closed.\" },\n { id: \"N6\", tier: \"shell\", from: \"3.8.0\", kind: \"journey\", summary: \"The header stays at the top with the phone and quote visible at every desktop width; the compact band shows them from 1024 to 1279 px.\" },\n { id: \"N8\", tier: \"shell\", from: \"3.9.0\", kind: \"journey\", summary: \"The drawer is a modal dialog that traps focus and resets; the call bar uses placement fab; back-to-top appears (from 3.11.0).\" },\n { id: \"K1\", tier: \"shell\", from: \"3.9.0\", kind: \"rendered\", summary: \"Shared components in use for the parts the tier covers (data-bl present); no literal tel: outside PhoneLink.\" },\n { id: \"K3\", tier: \"shell\", from: \"3.8.0\", kind: \"journey\", summary: \"Text contrast 4.5:1 and non-text 3:1 in the browser.\" },\n { id: \"K4\", tier: \"shell\", from: \"3.8.0\", kind: \"journey\", summary: \"Targets at least 24 px, and 44 px for primary actions (call, quote, menu).\" },\n { id: \"K5\", tier: \"shell\", from: \"3.8.0\", kind: \"journey\", summary: \"Focus is never fully hidden by the sticky header or call bar at 390 px, in Chromium and WebKit.\" },\n { id: \"K6\", tier: \"shell\", from: \"3.8.0\", kind: \"journey\", summary: \"Phone and quote in the same relative order on every page, in the header, hero and call bar.\" },\n { id: \"K7\", tier: \"shell\", from: \"3.8.0\", kind: \"rendered\", summary: \"Dropdown links, accordion and tab panels and full review text are in the server HTML.\" },\n { id: \"K10\", tier: \"shell\", from: \"3.8.0\", kind: \"record\", summary: \"Adoption parity in the lenient harness: no section, link or text lost against the baseline.\" },\n { id: \"C4\", tier: \"shell\", from: \"3.8.0\", kind: \"journey\", summary: \"Phone taps report an allowed placement (header, footer, hero, cta, fab, contact, location, page).\" },\n { id: \"C5\", tier: \"shell\", from: \"3.8.0\", kind: \"rendered\", summary: \"Call-to-action labels come from the closed list or a recorded label.\" },\n { id: \"C9\", tier: \"shell\", from: \"3.8.0\", kind: \"rendered\", summary: \"No interstitial overlay in the first screen.\" },\n { id: \"C10\", tier: \"shell\", from: \"3.8.0\", kind: \"rendered\", summary: \"Every tel: href is E.164 (national digits for 13, 1300 and 1800) and matches the evidence-file phone.\" },\n { id: \"E1\", tier: \"shell\", from: \"3.8.0\", kind: \"static\", summary: \"Title patterns on new or changed URLs; recorded titles unchanged.\" },\n { id: \"E2\", tier: \"shell\", from: \"3.8.0\", kind: \"rendered\", summary: \"Exactly one H1 on every page, rendered once.\" },\n { id: \"E8\", tier: \"shell\", from: \"3.8.0\", kind: \"rendered\", summary: \"No banned phrase from any of the three layers, environmental claims included.\" },\n { id: \"T3\", tier: \"shell\", from: \"3.8.0\", kind: \"rendered\", summary: \"A licence line renders wherever licensed work is advertised, with the licensee where it differs.\" },\n { id: \"T4\", tier: \"shell\", from: \"3.8.0\", kind: \"rendered\", summary: \"No hard-coded rating or review numbers; proof claims resolve to renderable evidence.\" },\n { id: \"T11\", tier: \"shell\", from: \"3.8.0\", kind: \"static\", summary: \"No page for work over $5,000 outside the licence classes held; licence conditions carried.\" },\n { id: \"X1\", tier: \"shell\", from: \"3.8.0\", kind: \"record\", summary: \"Legacy URLs answer 200 or one redirect hop; earning-URL depth, titles and dollar figures kept.\" },\n { id: \"B1\", tier: \"shell\", from: \"3.8.0\", kind: \"rendered\", summary: \"Lab budgets: JavaScript, third-party requests, hero image and HTML within budget; no unrecorded chat widget, pixel, heatmap or tag manager.\" },\n { id: \"L10-hero\", tier: \"shell\", from: \"3.8.0\", kind: \"rendered\", summary: 'No kilometre figures, \"km from\" or \"based in\" in hero copy.' },\n { id: \"W2\", tier: \"shell\", from: \"3.13.0\", kind: \"journey\", summary: \"Prefetch by link role at 390 x 844 and 1440 x 900: at most 8 pages on landing and 12 after a full scroll; none from footer, area, nearby, map or finder links, hidden links or the current page; prefetch bytes above twice the page's HTML warn.\" },\n { id: \"W5\", tier: \"shell\", from: \"3.13.0\", kind: \"static\", summary: \"vercel.json regions equal hosting.originRegion (syd1 by default); any other region has an origin-region-v1 decision whose reviewBy has not passed.\" },\n { id: \"W10\", tier: \"shell\", from: \"3.13.0\", kind: \"rendered\", summary: \"robots.txt and the recorded firewall rules leave every search and answer crawler open; no Crawl-delay for them.\" },\n\n // enquiry: the form, thank-you page, reviews, proof strip, footer, CTA band, contact page, prices, media, density\n { id: \"C1\", tier: \"enquiry\", from: \"3.8.0\", kind: \"journey\", summary: \"Money pages: the form in the first section; at 390 x 844 the H1, a call and a quote action in the first viewport; at 1440 x 900 the form.\" },\n { id: \"C2\", tier: \"enquiry\", from: \"3.8.0\", kind: \"rendered\", summary: 'Form layout and labels; phone and email required; no helper or reassurance lines, no \"(required)\", no job select.' },\n { id: \"E9\", tier: \"enquiry\", from: \"3.8.0\", kind: \"rendered\", summary: \"Every cost guide carries at least 8 dollar figures in a renderable price state.\" },\n { id: \"T5\", tier: \"enquiry\", from: \"3.8.0\", kind: \"rendered\", summary: \"Reviews from the feed, with Google's rating, count and link beside any selection; none on the contact page; no empty reviews section.\" },\n { id: \"K8\", tier: \"enquiry\", from: \"3.8.0\", kind: \"rendered\", summary: \"Section contract: no empty section, one H2 each, at most one band tone, neighbours differ, proof within the first five sections.\" },\n { id: \"C7\", tier: \"enquiry\", from: \"3.10.0\", kind: \"rendered\", summary: \"Thank-you page: a reply time, a tel: link and noindex, follow.\" },\n { id: \"C8\", tier: \"enquiry\", from: \"3.10.0\", kind: \"rendered\", summary: \"Forgiving form: tolerant phone input (13, 1300 and 1800 too), autocomplete tokens, no capture on the photo input.\" },\n { id: \"C11\", tier: \"enquiry\", from: \"3.10.0\", kind: \"static\", summary: \"The test marker is stripped before delivery and reporting; /api/contact is rate-limited.\" },\n { id: \"N9\", tier: \"enquiry\", from: \"3.11.0\", kind: \"rendered\", summary: 'Footer content: column 1 brand, licences, socials and contact; services, areas and company columns; © name, ABN and legal links; no CTA, \"based in\", hours or guides column.' },\n { id: \"K2\", tier: \"enquiry\", from: \"3.11.0\", kind: \"rendered\", summary: \"Every rendered shared component has a skin entry; no reference-skin class ships.\" },\n { id: \"K11\", tier: \"enquiry\", from: \"3.11.0\", kind: \"rendered\", summary: \"Density: no section with more than one H2, more than 8 cards or more than 2 calls to action; measure and section padding within limits.\" },\n { id: \"K12-contact\", tier: \"enquiry\", from: \"3.11.0\", kind: \"rendered\", summary: \"The contact page is the page header, then the contact block, and nothing else.\" },\n { id: \"T6\", tier: \"enquiry\", from: \"3.11.0\", kind: \"static\", summary: \"Every image has a media.ts entry with provenance.\" },\n { id: \"T7\", tier: \"enquiry\", from: \"3.11.0\", kind: \"rendered\", summary: \"No image is the main image of two pages.\" },\n { id: \"T8\", tier: \"enquiry\", from: \"3.11.0\", kind: \"rendered\", summary: 'Prices: GST flag set; no \"+ GST\" or \"from $X\" teasers on cards and menus; one band per job site-wide.' },\n { id: \"T9\", tier: \"enquiry\", from: \"3.11.0\", kind: \"static\", summary: \"No image in /public carries location metadata.\" },\n { id: \"H13\", tier: \"enquiry\", from: \"3.14.0\", kind: \"static\", notRunBlocks: \"launch\", summary: \"The business inbox can receive enquiries: a real sender (no .invalid, example or sandbox domain), MX records for the inbox, the sender domain verified in Resend and the inbox not on Resend's suppression list (not run without the inbox variable and a full-access Resend key in the shell, which blocks only at launch).\" },\n\n // full: page families, location estates, section manifests, links and the data contract\n { id: \"K12\", tier: \"full\", from: \"3.12.0\", kind: \"rendered\", summary: \"Section manifest: every required section rendered or skipped with a data-backed reason; conditional sections render when their data exists; canonical or recorded order.\" },\n { id: \"K12-slots\", tier: \"full\", from: \"3.14.0\", kind: \"rendered\", summary: \"Trade lines inside sections (matrix part B): for trees, the council permit note in LocalFacts on suburb and service-in-suburb pages and the qualifications and insurance lines on the about page, or a data-backed reason they are hidden.\" },\n { id: \"E5\", tier: \"full\", from: \"3.12.0\", kind: \"static\", summary: \"No orphan indexable pages, from the route catalogue and link data.\" },\n { id: \"E10\", tier: \"full\", from: \"3.12.0\", kind: \"static\", summary: \"Phrase-owner uniqueness in strategy data; no service-in-suburb page for the suburb page phrase; no service-region hub for the main trade.\" },\n { id: \"L3\", tier: \"full\", from: \"3.12.0\", kind: \"static\", summary: \"Neighbours by real distance.\" },\n { id: \"L4\", tier: \"full\", from: \"3.12.0\", kind: \"rendered\", summary: \"No copy rotated by page address, no name-swapped FAQs, no other suburb's job without the nearby label.\" },\n { id: \"L6\", tier: \"full\", from: \"3.12.0\", kind: \"static\", summary: \"Location pages have 6 or more inbound links from 3 or more page types.\" },\n { id: \"L7\", tier: \"full\", from: \"3.12.0\", kind: \"static\", summary: \"Location pages are 3 clicks or fewer from home.\" },\n { id: \"L8\", tier: \"full\", from: \"3.12.0\", kind: \"static\", summary: \"A hub per family per region.\" },\n { id: \"L9\", tier: \"full\", from: \"3.12.0\", kind: \"rendered\", summary: \"Data contract on service-in-suburb pages: typical prices or the cost-guide link, reviews or their fallback, the quote path (form with the suburb prefilled, phone, call bar); the nearby job card or none.\" },\n { id: \"L10\", tier: \"full\", from: \"3.12.0\", kind: \"rendered\", summary: 'No kilometre figures, \"km from\", \"based in\" or year stamps as local detail in location copy.' },\n { id: \"S4\", tier: \"full\", from: \"3.12.0\", kind: \"static\", summary: \"No hand-written per-service or per-suburb files; no dynamic route with zero pages.\" },\n { id: \"W9\", tier: \"full\", from: \"3.13.0\", kind: \"journey\", summary: \"URL variants: an unknown slug in each family answers the shared 404, the uppercase slug the same 404 or one permanent redirect to its lowercase form; a tracking query serves the same cached page as the clean URL.\" },\n { id: \"W9-params\", tier: \"full\", from: \"3.13.0\", kind: \"static\", summary: \"Pages under a dynamic route never read searchParams, so a query string cannot make an estate page dynamic.\" },\n { id: \"LOC-INDEX\", tier: \"full\", from: \"3.12.0\", kind: \"static\", summary: \"No location route is noindex or left out of the sitemap unless the recorded wave schedule dates it (Romie's 20 Oct decision: every suburb page stays indexed).\" },\n { id: \"E1-pattern\", tier: \"full\", from: \"3.14.0\", kind: \"rendered\", summary: 'Location pages outside the recorded titles have the H1 \"{Service} {Place}\" (no \"in\", no \"the\") and a title that starts with it, at most 60 characters.' },\n { id: \"W3\", tier: \"full\", from: \"3.13.0\", kind: \"static\", summary: \"No estate family (suburb, service-in-suburb, region, council) refreshes more often than every 7 days unless siteSystem.refreshExceptions records the reason and a decision id.\" },\n\n // new builds and redesigns\n { id: \"D4\", tier: \"new-build\", from: \"3.8.0\", kind: \"static\", summary: \"Same-trade distinctness: at least four of seven look levers differ from every listed competitor (advisory in 3.8.0, blocking from 3.9.0).\" },\n] as const satisfies readonly SiteSystemCheck[];\n\nexport type SiteSystemCheckId = (typeof SITE_SYSTEM_CHECKS)[number][\"id\"];\n\nconst TIER_RANK: Record<SiteSystemTier, number> = { shell: 0, enquiry: 1, full: 2 };\n\n/** A release as one comparable number: \"3.8.0\" < \"3.10.0\". */\nexport function siteSystemReleaseRank(version: string): number {\n const [major = 0, minor = 0, patch = 0] = version.split(/[.-]/).map((part) => Number.parseInt(part, 10) || 0);\n return major * 1_000_000 + minor * 1_000 + patch;\n}\n\n/**\n * Whether a check blocks for a site at `tier` on `release`. Checks of higher tiers, and checks newer than the\n * installed release, report without blocking. D4 blocks new builds and redesigns from 3.9.0 whatever their tier.\n */\nexport function siteSystemCheckBlocks(\n check: Pick<SiteSystemCheck, \"id\" | \"tier\" | \"from\">,\n site: { tier: SiteSystemTier; release: string; newBuild?: boolean },\n): boolean {\n if (check.tier === \"new-build\") return site.newBuild === true && siteSystemReleaseRank(site.release) >= siteSystemReleaseRank(\"3.9.0\");\n if (siteSystemReleaseRank(site.release) < siteSystemReleaseRank(check.from)) return false;\n return TIER_RANK[check.tier] <= TIER_RANK[site.tier];\n}\n\n/** One result of one check, from any runner. `brandlab-ready` merges them into the ready report. */\nexport interface SiteSystemFinding {\n readonly checkId: SiteSystemCheckId;\n /** `not-run`: the rule could not judge the check here (a missing key or input); it names what to supply. */\n readonly status: \"pass\" | \"fail\" | \"not-run\" | \"not-applicable\";\n /** The page path or file the result is about, when it is about one. */\n readonly target?: string;\n /** One plain sentence: what passed or what is wrong and where. */\n readonly message: string;\n /** A warning never blocks: the check still passes and the report shows \"pass (warning)\". */\n readonly severity?: \"warning\";\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/site-system/report.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/site-system/report.ts"],"names":[],"mappings":"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"}
|
|
@@ -71,7 +71,7 @@ export function buildSiteSystemReadyReport(input) {
|
|
|
71
71
|
};
|
|
72
72
|
const checks = SITE_SYSTEM_CHECKS.map((check) => {
|
|
73
73
|
const blocks = site ? siteSystemCheckBlocks(check, site) : false;
|
|
74
|
-
const merged = mergeFindings(findings.filter((finding) => finding.checkId === check.id), notRunMessage(check));
|
|
74
|
+
const merged = launchOnlyNotRun(check, blocks, input.launch === true, mergeFindings(findings.filter((finding) => finding.checkId === check.id), notRunMessage(check)));
|
|
75
75
|
const { status, messages } = applyException(check.id, blocks, merged.status, merged.messages);
|
|
76
76
|
return {
|
|
77
77
|
id: check.id,
|
|
@@ -134,8 +134,20 @@ export function buildSiteSystemReadyReport(input) {
|
|
|
134
134
|
};
|
|
135
135
|
}
|
|
136
136
|
/**
|
|
137
|
-
*
|
|
138
|
-
*
|
|
137
|
+
* A check whose not-run blocks only at launch (H13): under `--launch` a blocking not-run is a failure; otherwise it
|
|
138
|
+
* stays not run with a note, and the verdict does not count it.
|
|
139
|
+
*/
|
|
140
|
+
function launchOnlyNotRun(check, blocks, launch, merged) {
|
|
141
|
+
if (check.notRunBlocks !== "launch" || merged.status !== "not-run" || !blocks)
|
|
142
|
+
return merged;
|
|
143
|
+
if (launch)
|
|
144
|
+
return { ...merged, status: "fail", messages: merged.messages.map((message) => `Launch needs this check to run. ${message}`) };
|
|
145
|
+
return { ...merged, messages: [...merged.messages, "It blocks only at launch (brandlab-ready --launch)."] };
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Any fail fails the check; otherwise a rule's own not-run result (naming what it needed) leaves it not run; otherwise
|
|
149
|
+
* any pass passes it; only not-applicable results make it not applicable. A warning is a pass that carries its message
|
|
150
|
+
* as a warning, whatever status it names.
|
|
139
151
|
*/
|
|
140
152
|
function mergeFindings(findings, notRun) {
|
|
141
153
|
const warnings = [...new Set(findings.filter((finding) => finding.severity === "warning").map((finding) => finding.message))];
|
|
@@ -143,7 +155,7 @@ function mergeFindings(findings, notRun) {
|
|
|
143
155
|
if (warnings.length > 0 && !results.some((finding) => finding.status !== "not-applicable")) {
|
|
144
156
|
return { status: "pass", messages: [], warnings };
|
|
145
157
|
}
|
|
146
|
-
for (const status of ["fail", "pass", "not-applicable"]) {
|
|
158
|
+
for (const status of ["fail", "not-run", "pass", "not-applicable"]) {
|
|
147
159
|
const scoped = results.filter((finding) => finding.status === status);
|
|
148
160
|
if (scoped.length > 0)
|
|
149
161
|
return { status, messages: [...new Set(scoped.map((finding) => finding.message))], warnings };
|
|
@@ -202,7 +214,9 @@ function readyStep(step, file, record) {
|
|
|
202
214
|
function readyVerdict(input) {
|
|
203
215
|
const blocking = input.checks.filter((check) => check.blocks);
|
|
204
216
|
const failed = blocking.filter((check) => check.status === "fail").map((check) => check.id);
|
|
205
|
-
const
|
|
217
|
+
const launchOnly = new Set(SITE_SYSTEM_CHECKS.filter((check) => check.notRunBlocks === "launch").map((check) => check.id));
|
|
218
|
+
// A launch-only check that did not run is reported, not counted: under --launch it is already a failure.
|
|
219
|
+
const notRun = blocking.filter((check) => check.status === "not-run" && !launchOnly.has(check.id)).map((check) => check.id);
|
|
206
220
|
const excepted = blocking.filter((check) => check.status === "excepted").map((check) => check.id);
|
|
207
221
|
const stepsToRecord = input.steps.filter((step) => !step.recorded).map((step) => step.id);
|
|
208
222
|
const adopted = input.settings !== null;
|