feat(site-builder): stamp git sha + date into the editor bundle

package.json's version is hand-maintained and never changes between
builds, so a bug report can't identify which bundle produced it.
Vite's `define` injects __EDITOR_BUILD__ (short git SHA + build date)
at compile time; editorBuild() in build-stamp.ts is the only safe way
to read it, falling back to 'dev' since vitest does not apply Vite's
`define` and the identifier is otherwise undeclared. The execSync
call falls back to 'nogit' when building outside a git checkout
(release tarballs), verified by building from a directory with no
git ancestry at all.

Also wires editorBuild() into a startup console.log in main.tsx --
without any reference to it, Vite tree-shakes the unused module out
of the bundle entirely and __EDITOR_BUILD__ never gets substituted,
silently leaving every bug report saying 'dev'. Task 19 will add the
real call site when it assembles the report payload.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-09 10:59:38 -07:00
co-authored by Claude Opus 5
parent fc8918c1f9
commit 024f9fdd46
4 changed files with 39 additions and 0 deletions
+7
View File
@@ -3,12 +3,19 @@ import ReactDOM from 'react-dom/client';
import { App } from './App';
import { WhpConfig } from './types';
import { installConsoleErrorBuffer } from './utils/console-buffer';
import { editorBuild } from './utils/build-stamp';
import './styles/editor.css';
// Installed before React mounts so errors thrown during the first render are
// captured too.
installConsoleErrorBuffer();
// Logged so the build that produced a given session is visible in the
// browser console; also the only current reference to `editorBuild()`,
// which keeps the __EDITOR_BUILD__-reading module from being tree-shaken
// out of the bundle before Task 19 wires it into the report payload.
console.log(`[site-builder] build ${editorBuild()}`);
// Read WHP_CONFIG injected by PHP wrapper (or null for standalone dev)
const whpConfig: WhpConfig | null = (window as any).WHP_CONFIG || null;
+10
View File
@@ -0,0 +1,10 @@
/**
* Reads the compile-time `__EDITOR_BUILD__` define.
*
* vitest does not apply Vite's `define`, and `npm run dev` in a non-git
* checkout may not either, so every read goes through here. `typeof` on an
* undeclared identifier is safe in JS -- it does not throw.
*/
export function editorBuild(): string {
return typeof __EDITOR_BUILD__ !== 'undefined' ? __EDITOR_BUILD__ : 'dev';
}
+5
View File
@@ -0,0 +1,5 @@
/// <reference types="vite/client" />
/** Injected by vite.config.ts `define`. Absent under vitest -- always read
* it through `utils/build-stamp.ts`'s `editorBuild()`, never directly. */
declare const __EDITOR_BUILD__: string;