Corrective Action: Unnecessary Full Website Builds for SSR-Only Changes
Date: March 15, 2026 Category: Verification Failure Impact: ~7 minutes wasted per code change; recurring pattern across many sessions Resolution Time: Same session — protocol defined, not yet internalized
Incident
What Happened
V ran a full website build (npx pnpm build, 414 seconds) after adding 3 new SSR components and updating 1 navigation component in the Command Center Collective section. All 4 files are server-rendered pages (export const prerender = false). No static content was modified. A 15-second type check (tsc --noEmit) would have caught any TypeScript errors.
Chris flagged this as a recurring pattern: "i feel like we have tried to fix this build habit so many times. why are we building the whole damn website during each update to a section of the website."
Timeline
| Time | Event |
|---|---|
| Session start | Created 3 new files (PlatformArchitecture.tsx, DataFlowDiagram.tsx, platform-architecture.astro) + updated CommandCenterNav.astro |
| Pre-commit | Ran cd apps/website && npx pnpm build — took 414 seconds |
| Post-build | Committed (5b02d46e) and pushed to production |
| Chris review | "why are we building the whole damn website during each update to a section of the website" |
Root Cause
V defaulted to running a full static site build before every commit, despite the build-verification skill (skills/build-verification/SKILL.md) explicitly documenting a 4-tier verification system that exists to prevent this exact behavior.
Category: Verification Failure
The skill clearly states:
- Tier 2 (type check, ~10s): For TypeScript/component changes — adding new props, changing type definitions, refactoring imports
- Anti-Pattern: "Don't: Run full build for every change. Wastes 3-5 minutes per iteration."
The skill was never loaded or consulted. V treated npx pnpm build as the default verification step regardless of change type. This is a training data pattern: LLMs default to "run the full build" because that's the safest, most conservative approach — but it's the wrong approach for server-rendered pages that Vercel builds on-demand at request time.
The SSR Distinction
Astro pages with export const prerender = false are server-rendered on each request by Vercel's serverless functions. They are NOT included in the static build output. Running the full build for SSR-only changes:
- Regenerates 635+ episode pages, 23 show pages, 50+ blog posts — none of which were affected
- Takes 5-7 minutes for zero benefit
- Blocks the commit/push cycle unnecessarily
The correct verification for SSR + TypeScript changes is tsc --noEmit (~15 seconds), which catches type errors without generating any static output.
Why This Keeps Happening
The build-verification skill exists at skills/build-verification/SKILL.md but:
- Not in enforcement layer. It's a "development skill," not an enforcement trigger. V's self-correction protocol (
vf-self-correction.md) has no trigger for "running full builds unnecessarily." - Not in MEMORY.md. The build notes say "Website build: ~5-6 minutes" as a neutral fact, not as a warning about when it's inappropriate.
- Not loaded at session start. Enforcement skills are mandatory at session start; the build-verification skill is loaded only when explicitly needed.
- Training data default. "Build before commit" is a deeply ingrained pattern. Without an active trigger catching the behavior, it reasserts every session.
Fix Applied
Immediate Resolution
For this specific commit, the full build succeeded and the code was pushed. No code fix needed — the components work correctly. The fix is procedural.
Verification Approach for SSR Pages
Confirmed that tsc --noEmit in apps/website/ completes in ~15 seconds and catches type errors in new components. Pre-existing type errors (Sanity schemas, tailwind config, test files) are unrelated to new work.
The npx astro check command requires @astrojs/check (not installed). tsc --noEmit is the working alternative.
Decision Matrix (SSR Changes)
| Change Type | Verification | Time |
|---|---|---|
| SSR page + TypeScript components | tsc --noEmit |
~15s |
| SSR page + visual changes | Push, verify on Vercel preview | 0s local |
| Static page content/data changes | Full build required | 5-7min |
| Route structure / getStaticPaths | Full build required | 5-7min |
| Build config (astro.config.mjs) | Full build required | 5-7min |
Prevention Measures
Rules Added
| Layer | File | Rule |
|---|---|---|
| Self-Correction | skills/enforcement/vf-self-correction.md |
Infrastructure Trigger: "Running full website build for SSR-only changes" |
| Critical Lessons | memory/MEMORY.md |
Build verification tier rule |
| Anti-Rationalization | skills/enforcement/vf-self-correction.md |
"Better safe than sorry — run the full build" rationalization |
Detection Triggers
Infrastructure Trigger: If V is about to run npx pnpm build or npm run build in apps/website/, STOP and check: Do ANY of the changed files affect static content (getStaticPaths, data fetching, build config)? If not, use tsc --noEmit instead.
Rationalization Trigger: "Better safe than sorry — let me run the full build" → The build-verification skill exists for this exact decision. Running a 7-minute build "just to be safe" for an SSR-only change is not safety — it's waste. tsc --noEmit catches type errors. Vercel catches runtime errors on deploy. The full build adds nothing for SSR pages.
Lessons
The build-verification skill documented the correct behavior since its creation, but documentation alone does not change behavior. Skills that define operational constraints must be surfaced as enforcement triggers — the same mechanism that prevents forbidden language and architecture anti-patterns. If a behavior is important enough to document as an anti-pattern, it's important enough to trigger self-correction.
Related Incidents
- This is a recurring pattern Chris has flagged multiple times across sessions
- The build-verification skill (
skills/build-verification/SKILL.md) was created specifically to address this, but its guidance was never internalized into the enforcement layer - No previous CAR exists for this specific incident — it accumulated as informal corrections that didn't persist across sessions