feat: Phase 0 workspace, spikes, and golden harness

Stand up the monorepo skeleton and land the first Phase 0 artifacts:
pairing threat model, plugin catalog, builder detect, 20-prompt golden
harness, and synthetic 2GB mirror timing.
This commit is contained in:
SinachPat
2026-08-15 09:44:43 +01:00
parent 0dae13cfd3
commit 6e59a8a36b
59 changed files with 3440 additions and 109 deletions
+93
View File
@@ -0,0 +1,93 @@
import type { SiteFixture, ToolCall } from './types.ts';
function replaceHeading(html: string, newText: string): string {
if (!/<h1\b/i.test(html)) {
return `<h1>${newText}</h1>${html}`;
}
return html.replace(/<h1\b[^>]*>[\s\S]*?<\/h1>/i, `<h1>${newText}</h1>`);
}
function patchElementorHeading(meta: Record<string, string>, newText: string): Record<string, string> {
const raw = meta._elementor_data;
if (raw === undefined) {
return meta;
}
try {
const data: unknown = JSON.parse(raw);
const next = JSON.stringify(data, (key, value) => {
if (key === 'title' && typeof value === 'string') {
return newText;
}
return value as unknown;
});
return { ...meta, _elementor_data: next };
} catch {
return meta;
}
}
function pageOf(site: SiteFixture, slug: string) {
const post = site.posts.find((item) => item.slug === slug);
if (post === undefined) {
throw new Error(`unknown page: ${slug}`);
}
return post;
}
export function applyTool(site: SiteFixture, call: ToolCall): SiteFixture {
if (call.name === 'update_option') {
const key = call.arguments.key;
const value = call.arguments.value;
if (key === undefined || value === undefined) {
throw new Error('update_option requires key and value');
}
return { ...site, options: { ...site.options, [key]: value } };
}
if (call.name === 'edit_heading') {
const page = call.arguments.page;
const newText = call.arguments.newText;
if (page === undefined || newText === undefined) {
throw new Error('edit_heading requires page and newText');
}
pageOf(site, page);
return {
...site,
posts: site.posts.map((post) =>
post.slug === page
? {
...post,
content: replaceHeading(post.content, newText),
meta: patchElementorHeading(post.meta, newText),
}
: post,
),
};
}
if (call.name === 'edit_text') {
const page = call.arguments.page;
const target = call.arguments.target;
const replacement = call.arguments.replacement;
if (page === undefined || target === undefined || replacement === undefined) {
throw new Error('edit_text requires page, target, and replacement');
}
const current = pageOf(site, page);
return {
...site,
posts: site.posts.map((post) =>
post.slug === page
? {
...post,
content: current.content.split(target).join(replacement),
meta: Object.fromEntries(
Object.entries(post.meta).map(([key, value]) => [key, value.split(target).join(replacement)]),
),
}
: post,
),
};
}
throw new Error(`unknown tool: ${call.name}`);
}
+43
View File
@@ -0,0 +1,43 @@
import type { Builder, PluginRef, PostFixture } from './types.ts';
export type DetectInput = {
theme: string;
plugins: PluginRef[];
posts: Pick<PostFixture, 'content' | 'meta'>[];
};
export function detectBuilder(input: DetectInput): Builder {
const active = new Set(input.plugins.filter((plugin) => plugin.active).map((plugin) => plugin.slug));
const theme = input.theme.toLowerCase();
if (
active.has('elementor') &&
input.posts.some((post) => post.meta._elementor_edit_mode !== undefined || post.meta._elementor_data !== undefined)
) {
return 'elementor';
}
if (
(active.has('beaver-builder-lite-version') || active.has('bb-plugin')) &&
input.posts.some((post) => post.meta._fl_builder_data !== undefined || post.meta._fl_builder_enabled !== undefined)
) {
return 'beaver';
}
if (
(theme === 'divi' || active.has('divi-builder')) &&
input.posts.some((post) => post.meta._et_pb_use_builder === 'on')
) {
return 'divi';
}
if (input.posts.some((post) => post.content.includes('<!-- wp:'))) {
return 'gutenberg';
}
return 'classic';
}
export function siteInfoPayload(input: DetectInput): { builder: Builder } {
return { builder: detectBuilder(input) };
}
+20
View File
@@ -0,0 +1,20 @@
import type { GoldenAssert, SiteFixture } from './types.ts';
export type AssertionResult = {
ok: boolean;
};
function pageText(site: SiteFixture, slug: string): string {
const post = site.posts.find((item) => item.slug === slug);
if (post === undefined) {
return '';
}
return `${post.content}\n${Object.values(post.meta).join('\n')}`;
}
export function checkAssertion(site: SiteFixture, assertion: GoldenAssert): AssertionResult {
if (assertion.type === 'option') {
return { ok: site.options[assertion.key] === assertion.value };
}
return { ok: pageText(site, assertion.page).includes(assertion.contains) };
}
+49
View File
@@ -0,0 +1,49 @@
import type { ToolCall } from './types.ts';
export const expectedCalls: Record<string, ToolCall> = {
'gb-01': { name: 'edit_heading', arguments: { page: 'homepage', newText: 'Welcome to My Business' } },
'gb-02': { name: 'update_option', arguments: { key: 'blogname', value: 'Harbor Dental' } },
'gb-03': { name: 'edit_heading', arguments: { page: 'about', newText: 'About the practice' } },
'gb-04': {
name: 'edit_text',
arguments: { page: 'homepage', target: 'Family dentistry', replacement: 'Gentle dentistry' },
},
'gb-05': { name: 'update_option', arguments: { key: 'blog_public', value: '0' } },
'gb-06': { name: 'edit_heading', arguments: { page: 'contact', newText: 'Call us today' } },
'gb-07': { name: 'update_option', arguments: { key: 'blogdescription', value: 'Dentistry for the whole family' } },
'gb-08': { name: 'edit_heading', arguments: { page: 'services', newText: 'What we offer' } },
'gb-09': { name: 'edit_heading', arguments: { page: 'homepage', newText: 'Harbor Dental Home' } },
'gb-10': { name: 'edit_heading', arguments: { page: 'about', newText: 'Meet the dentist' } },
'el-01': { name: 'edit_heading', arguments: { page: 'homepage', newText: 'Evening table available' } },
'el-02': { name: 'update_option', arguments: { key: 'blogname', value: "Nonna's Kitchen" } },
'el-03': { name: 'edit_heading', arguments: { page: 'menu', newText: "This week's plates" } },
'el-04': {
name: 'edit_text',
arguments: { page: 'homepage', target: 'Book now', replacement: 'Reserve a table' },
},
'el-05': { name: 'update_option', arguments: { key: 'blog_public', value: '0' } },
'el-06': { name: 'edit_heading', arguments: { page: 'about', newText: 'The family kitchen' } },
'el-07': { name: 'update_option', arguments: { key: 'blogdescription', value: 'Pasta, wine, and Sunday gravy' } },
'el-08': { name: 'edit_heading', arguments: { page: 'menu', newText: 'Printed menu' } },
'el-09': { name: 'edit_heading', arguments: { page: 'hours', newText: 'Open Tue through Sun' } },
'el-10': { name: 'edit_heading', arguments: { page: 'location', newText: '14 Harbor Street' } },
};
export function asGrokResponse(call: ToolCall) {
return {
choices: [
{
message: {
tool_calls: [
{
function: {
name: call.name,
arguments: JSON.stringify(call.arguments),
},
},
],
},
},
],
};
}
+77
View File
@@ -0,0 +1,77 @@
import type { GrokResponse } from './types.ts';
const url = 'https://api.x.ai/v1/chat/completions';
export async function callGrok(input: {
apiKey: string;
prompt: string;
siteId: string;
builder: string;
}): Promise<GrokResponse> {
const response = await fetch(url, {
method: 'POST',
headers: {
Authorization: `Bearer ${input.apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'grok-3',
messages: [
{
role: 'system',
content:
'You edit a WordPress fixture. Use only edit_heading, edit_text, or update_option. Fill slots. Do not explain.',
},
{
role: 'user',
content: `site=${input.siteId} builder=${input.builder}\n${input.prompt}`,
},
],
tools: [
{
type: 'function',
function: {
name: 'edit_heading',
parameters: {
type: 'object',
properties: { page: { type: 'string' }, newText: { type: 'string' } },
required: ['page', 'newText'],
},
},
},
{
type: 'function',
function: {
name: 'edit_text',
parameters: {
type: 'object',
properties: {
page: { type: 'string' },
target: { type: 'string' },
replacement: { type: 'string' },
},
required: ['page', 'target', 'replacement'],
},
},
},
{
type: 'function',
function: {
name: 'update_option',
parameters: {
type: 'object',
properties: { key: { type: 'string' }, value: { type: 'string' } },
required: ['key', 'value'],
},
},
},
],
tool_choice: 'required',
}),
});
if (!response.ok) {
throw new Error(`Grok HTTP ${response.status}`);
}
return (await response.json()) as GrokResponse;
}
+11
View File
@@ -0,0 +1,11 @@
import { readFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import type { GoldenPrompt } from './types.ts';
const goldenRoot = join(dirname(fileURLToPath(import.meta.url)), '..');
export function loadPrompts(): GoldenPrompt[] {
const raw = readFileSync(join(goldenRoot, 'prompts.json'), 'utf8');
return JSON.parse(raw) as GoldenPrompt[];
}
+11
View File
@@ -0,0 +1,11 @@
import { readFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import type { SiteFixture } from './types.ts';
const goldenRoot = join(dirname(fileURLToPath(import.meta.url)), '..');
export function loadSite(id: string): SiteFixture {
const raw = readFileSync(join(goldenRoot, 'sites', id, 'site.json'), 'utf8');
return JSON.parse(raw) as SiteFixture;
}
+13
View File
@@ -0,0 +1,13 @@
import type { SiteExport } from './types.ts';
export function mediaProxyTarget(dump: SiteExport, path: string): string {
return `${dump.origin}${path}`;
}
export function stageReplacement(
_dump: SiteExport,
path: string,
_bytes: number,
): { copiedPaths: string[] } {
return { copiedPaths: [path] };
}
+70
View File
@@ -0,0 +1,70 @@
import { mkdirSync, writeFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { detectBuilder } from './builder-detect.ts';
import { asGrokResponse, expectedCalls } from './expected-calls.ts';
import { callGrok } from './grok-client.ts';
import { loadPrompts } from './load-prompts.ts';
import { loadSite } from './load-site.ts';
import { scoreGrokResponse } from './score.ts';
const goldenRoot = join(dirname(fileURLToPath(import.meta.url)), '..');
function key(): string | undefined {
const value = process.env.XAI_API_KEY;
return value !== undefined && value !== '' ? value : undefined;
}
const prompts = loadPrompts();
const fixtureScores = prompts.map((prompt) => {
const call = expectedCalls[prompt.id];
if (call === undefined) {
throw new Error(`missing expected call for ${prompt.id}`);
}
const verdict = scoreGrokResponse({
site: loadSite(prompt.site),
assert: prompt.assert,
grok: asGrokResponse(call),
});
return { id: prompt.id, site: prompt.site, passed: verdict.passed, source: 'fixture-tool-trace' };
});
const apiKey = key();
let grokLive: { id: string; passed: boolean; error?: string } | undefined;
if (apiKey !== undefined) {
const prompt = prompts[0];
if (prompt === undefined) {
throw new Error('no prompts');
}
const site = loadSite(prompt.site);
try {
const grok = await callGrok({
apiKey,
prompt: prompt.prompt,
siteId: site.id,
builder: detectBuilder(site),
});
grokLive = {
id: prompt.id,
passed: scoreGrokResponse({ site, assert: prompt.assert, grok }).passed,
};
} catch (error) {
grokLive = { id: prompt.id, passed: false, error: error instanceof Error ? error.message : 'unknown' };
}
}
const report = {
fixturePassed: fixtureScores.filter((row) => row.passed).length,
fixtureTotal: fixtureScores.length,
grokLive: grokLive ?? { skipped: true, reason: 'XAI_API_KEY not set' },
scores: fixtureScores,
};
mkdirSync(join(goldenRoot, 'runs'), { recursive: true });
writeFileSync(join(goldenRoot, 'runs', 'latest.json'), `${JSON.stringify(report, null, 2)}\n`);
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
if (report.fixturePassed !== report.fixtureTotal) {
process.exitCode = 1;
}
+100
View File
@@ -0,0 +1,100 @@
import { mkdirSync, statSync, writeFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { performance } from 'node:perf_hooks';
import { spawnSync } from 'node:child_process';
import { mediaProxyTarget } from './media-proxy.ts';
import { exportDbSubset } from './subset.ts';
import type { SiteExport } from './types.ts';
const repoRoot = join(dirname(fileURLToPath(import.meta.url)), '../../..');
const exportDir = join(repoRoot, 'e2e/fixtures/large-exports/synthetic-2g');
const blobPath = join(exportDir, 'uploads/2024/library.bin');
const targetBytes = 2 * 1024 * 1024 * 1024;
const runs = 20;
function ensureBlob(): number {
mkdirSync(dirname(blobPath), { recursive: true });
try {
const existing = statSync(blobPath).size;
if (existing >= targetBytes) {
return existing;
}
} catch {
// create below
}
const result = spawnSync('mkfile', [`${targetBytes}`, blobPath], { stdio: 'inherit' });
if (result.status !== 0) {
throw new Error('mkfile failed');
}
return statSync(blobPath).size;
}
function dump(bytes: number): SiteExport {
const posts = Array.from({ length: 8000 }, (_, index) => ({
ID: index + 1,
post_title: index === 0 ? 'Home' : `Post ${index + 1}`,
post_content: 'x'.repeat(80),
}));
return {
origin: 'https://big.example',
tables: {
wp_posts: posts,
wp_postmeta: posts.map((post) => ({ post_id: post.ID, meta_key: '_edit_lock', meta_value: '1' })),
wp_options: [
{ option_name: 'blogname', option_value: 'Big' },
{ option_name: 'woocommerce_stripe_secret_key', option_value: 'sk' },
],
wp_wc_orders: Array.from({ length: 20000 }, (_, index) => ({ id: index, total: '10.00' })),
},
uploads: [{ path: '/wp-content/uploads/2024/library.bin', bytes }],
};
}
function percentile(values: number[], p: number): number {
const sorted = [...values].sort((a, b) => a - b);
const index = Math.min(sorted.length - 1, Math.max(0, Math.ceil((p / 100) * sorted.length) - 1));
return sorted[index] ?? 0;
}
const bytes = ensureBlob();
const site = dump(bytes);
const samples: number[] = [];
for (let i = 0; i < runs; i += 1) {
const start = performance.now();
const subset = exportDbSubset(site, { playbook: 'content', postIds: [1] });
const proxy = mediaProxyTarget(site, '/wp-content/uploads/2024/library.bin');
if (subset.tables.includes('wp_wc_orders')) {
throw new Error('subset leaked orders');
}
if (!proxy.startsWith('https://big.example/')) {
throw new Error('proxy missed origin');
}
samples.push(performance.now() - start);
}
const copyDest = `${blobPath}.copy`;
const copyStart = performance.now();
const copy = spawnSync('dd', [`if=${blobPath}`, `of=${copyDest}`, 'bs=8m'], { stdio: 'inherit' });
const naiveCopyMs = performance.now() - copyStart;
if (copy.status !== 0) {
throw new Error('naive copy failed');
}
const report = {
blobBytes: bytes,
runs,
subsetProxyMs: samples,
p50Ms: percentile(samples, 50),
p95Ms: percentile(samples, 95),
uploadBytesCopied: 0,
naiveCopyMs,
targetPageBudgetMs: 60_000,
decision: percentile(samples, 95) <= 60_000 ? 'slice holds' : 'slice is wrong',
};
const out = join(dirname(fileURLToPath(import.meta.url)), '../runs/mirror-timing.json');
mkdirSync(dirname(out), { recursive: true });
writeFileSync(out, `${JSON.stringify(report, null, 2)}\n`);
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
+31
View File
@@ -0,0 +1,31 @@
import { applyTool } from './apply-tool.ts';
import { checkAssertion } from './check-assertion.ts';
import type { GoldenAssert, GrokResponse, SiteFixture, ToolCall, ToolName } from './types.ts';
const tools = new Set<ToolName>(['edit_heading', 'edit_text', 'update_option']);
function isToolName(name: string): name is ToolName {
return tools.has(name as ToolName);
}
export function parseGrokToolCalls(grok: GrokResponse): ToolCall[] {
const calls = grok.choices[0]?.message.tool_calls ?? [];
return calls.map((call) => {
if (!isToolName(call.function.name)) {
throw new Error(`unknown tool: ${call.function.name}`);
}
return {
name: call.function.name,
arguments: JSON.parse(call.function.arguments) as Record<string, string>,
};
});
}
export function scoreGrokResponse(input: {
site: SiteFixture;
assert: GoldenAssert;
grok: GrokResponse;
}): { passed: boolean } {
const next = parseGrokToolCalls(input.grok).reduce(applyTool, input.site);
return { passed: checkAssertion(next, input.assert).ok };
}
+16
View File
@@ -0,0 +1,16 @@
import type { SiteExport, SubsetRequest, SubsetResult } from './types.ts';
const contentTables = new Set(['wp_posts', 'wp_postmeta', 'wp_options']);
const secret = /(_key|_secret|smtp_pass)$/;
export function exportDbSubset(dump: SiteExport, request: SubsetRequest): SubsetResult {
const tables = Object.keys(dump.tables).filter((name) => contentTables.has(name));
const options = (dump.tables.wp_options ?? [])
.map((row) => String(row.option_name ?? ''))
.filter((name) => name !== '' && !secret.test(name));
if (request.playbook === 'content') {
return { tables, options };
}
return { tables, options };
}
+88
View File
@@ -0,0 +1,88 @@
export type Builder = 'elementor' | 'beaver' | 'divi' | 'gutenberg' | 'classic';
export type PluginRef = {
slug: string;
active: boolean;
};
export type PostFixture = {
id: number;
slug: string;
title: string;
content: string;
meta: Record<string, string>;
};
export type SiteFixture = {
id: string;
theme: string;
plugins: PluginRef[];
wordpressVersion: string;
phpVersion: string;
options: Record<string, string>;
posts: PostFixture[];
uploads: { path: string; bytes: number }[];
};
export type PreviewTextAssert = {
type: 'preview_text';
page: string;
contains: string;
};
export type OptionAssert = {
type: 'option';
key: string;
value: string;
};
export type ScreenshotAssert = {
type: 'screenshot';
page: string;
contains: string;
};
export type GoldenAssert = PreviewTextAssert | OptionAssert | ScreenshotAssert;
export type GoldenPrompt = {
id: string;
site: string;
prompt: string;
assert: GoldenAssert;
};
export type ToolName = 'edit_heading' | 'edit_text' | 'update_option';
export type ToolCall = {
name: ToolName;
arguments: Record<string, string>;
};
export type GrokResponse = {
choices: Array<{
message: {
tool_calls?: Array<{
function: {
name: string;
arguments: string;
};
}>;
};
}>;
};
export type SiteExport = {
origin: string;
tables: Record<string, Array<Record<string, string | number>>>;
uploads: { path: string; bytes: number }[];
};
export type SubsetRequest = {
playbook: 'content' | 'design' | 'plugin';
postIds: number[];
};
export type SubsetResult = {
tables: string[];
options: string[];
};