Minor Changes
-
#64
e1e4e8dThanks @MohamedH1998! - Addnimbus-docs check— a build-free preflight that reports readiness honestlyOne command a human, CI, or agent runs to catch setup, structural, authoring, and type problems before a build. It runs four categories — environment (Node floor, config locatable,
sitenot a placeholder, pagefind, wrangler), structure (config Zod, duplicate routes, MDX component resolution — the same validators the build gates on), authoring (the shipped lint rules), and types (a build-free type-check) — and normalizes every result into one envelope.The types category type-checks your TypeScript with your project's own
tsc, build-free — noastro build, noastro sync, nothing spawned (your TypeScript is resolved from your project, never bundled into the CLI). Astro transpiles rather than type-checks, so a type error never fails the build on its own; catching it in the preflight is the point. Becausetsccan't parse.astroSFCs, their internals and prop types are out of scope (that needsastro check); an injected ambientdeclare module "*.astro"keeps.tsfiles that import.astrocomponents from being false-flagged.The report separates two axes that a naive error count fuses: buildability vs. correctness, and evaluated vs. not-evaluated.
--jsoncarries three top-level signals:status(passed|failed|partial) — the whole-run verdict across every scope that ran.readiness(buildable|blocked|unknown) — derived from env + structure only: does the project clear Nimbus' buildability checks? A type error isstatus: failedbutreadiness: buildable(the site still builds — Astro strips types); a placeholdersiteisblocked.ok— kept for back-compat, still exactlyerrors === 0.
Exit is
1only whenstatus === "failed"(ok === false);partialandreadinessnever move it. Usage errors are2.Coverage is a first-class channel, not a fake warning. A sub-check that can't run yet — opt-in authoring rules or link-checking before
astro buildmaterializes.nimbus/lint.json/.nimbus/routes.json, or the type-check before.astro/types.d.tsexists — is reported as a note underscopes[].notes[{ code, reason, requiresBuild?, requiresInput? }], counted insummary.notes. A note is never afinding, never carries afix, and never affects the exit code; it resolves by making the missing thing exist (a build), not by--fix. A run that skipped types or authoring rules therefore never declares itself build-ready on an unverified scope. The headline is earned: "Buildable" on a scaffold whose correctness scopes are still notes, "Ready" only when every scope that ran evaluated clean with zero notes.--jsonemits{ ok, status, readiness, summary{errors,warnings,notes,fixable,durationMs}, scopes[{scope,status,reason?,notes[]}], findings[{scope,code,severity,file,line,message,fixable,fix}] }. An agent's fix loop terminates onstatus !== "failed" && summary.fixable === 0— apartialrun with nothing left to fix is a stop (optionally build, then re-check), not a--fixretry.--fixapplies safe fixes (installs, config rewrites via a static parse ofastro.config.ts), prompting on a TTY for values it can't invent (e.g. the productionsiteURL) and skipping them headless.--env/--structure/--lint/--typesrun a single category.initnow ends with the env readiness pass — using the same scope-status vocabulary — so a fresh scaffold hears about a placeholdersiteat setup time.
lintis preserved as a first-class command with its own "zero.mdx→ exit 1" guard;check --lintruns the same rules inside the preflight envelope. (Unlikelint, a config-only project with no.mdxis not an error forcheck.)Config validation for
siteis now stricter: it must be an absolutehttp(s)://URL with a host. Previously a value missing the//(e.g.https:example.com) slipped throughnew URL()and shipped a broken canonical origin; it is now rejected both build-free bycheckand at build time by the config gate.