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
@@ -0,0 +1,72 @@
import { describe, it, expect } from 'vitest';
import { detectBuilder } from '../src/builder-detect.ts';
describe('detectBuilder', () => {
it('reports elementor when the plugin is active and post meta has _elementor_edit_mode', () => {
expect(
detectBuilder({
theme: 'hello-elementor',
plugins: [{ slug: 'elementor', active: true }],
posts: [{ id: 1, slug: 'home', title: 'Home', content: '', meta: { _elementor_edit_mode: 'builder' } }],
}),
).toBe('elementor');
});
it('reports beaver when beaver-builder is active and _fl_builder_data is present', () => {
expect(
detectBuilder({
theme: 'bb-theme',
plugins: [{ slug: 'beaver-builder-lite-version', active: true }],
posts: [{ id: 1, slug: 'home', title: 'Home', content: '', meta: { _fl_builder_data: '{}' } }],
}),
).toBe('beaver');
});
it('reports divi when the theme is Divi and _et_pb_use_builder is on', () => {
expect(
detectBuilder({
theme: 'Divi',
plugins: [],
posts: [{ id: 1, slug: 'home', title: 'Home', content: '', meta: { _et_pb_use_builder: 'on' } }],
}),
).toBe('divi');
});
it('reports gutenberg when content has block markup and no builder plugin', () => {
expect(
detectBuilder({
theme: 'twentytwentyfour',
plugins: [],
posts: [{ id: 1, slug: 'home', title: 'Home', content: '<!-- wp:heading --><h1>Hi</h1><!-- /wp:heading -->', meta: {} }],
}),
).toBe('gutenberg');
});
it('reports classic when content is HTML and no builder plugin is active', () => {
expect(
detectBuilder({
theme: 'twentytwentyone',
plugins: [],
posts: [{ id: 1, slug: 'home', title: 'Home', content: '<h1>Hi</h1>', meta: {} }],
}),
).toBe('classic');
});
it('prefers elementor over gutenberg markup when both are present', () => {
expect(
detectBuilder({
theme: 'hello-elementor',
plugins: [{ slug: 'elementor', active: true }],
posts: [
{
id: 1,
slug: 'home',
title: 'Home',
content: '<!-- wp:heading --><h1>Hi</h1><!-- /wp:heading -->',
meta: { _elementor_data: '[]' },
},
],
}),
).toBe('elementor');
});
});
+54
View File
@@ -0,0 +1,54 @@
import { describe, it, expect } from 'vitest';
import { exportDbSubset } from '../src/subset.ts';
import { mediaProxyTarget, stageReplacement } from '../src/media-proxy.ts';
import type { SiteExport } from '../src/types.ts';
const dump = (): SiteExport => ({
origin: 'https://example.com',
tables: {
wp_posts: [{ ID: 1, post_title: 'Home' }],
wp_postmeta: [{ post_id: 1, meta_key: '_edit_lock', meta_value: '1' }],
wp_options: [
{ option_name: 'blogname', option_value: 'Biz' },
{ option_name: 'woocommerce_stripe_secret_key', option_value: 'sk_live_xxx' },
{ option_name: 'smtp_pass', option_value: 'secret' },
],
wp_wc_orders: [{ id: 99, total: '40.00' }],
wp_comments: [{ comment_ID: 1, comment_content: 'hi' }],
},
uploads: [{ path: '/wp-content/uploads/2024/hero.jpg', bytes: 2_147_483_648 }],
});
describe('exportDbSubset', () => {
it('keeps posts, postmeta, and options for a content playbook', () => {
expect(exportDbSubset(dump(), { playbook: 'content', postIds: [1] }).tables).toEqual(
expect.arrayContaining(['wp_posts', 'wp_postmeta', 'wp_options']),
);
});
it('drops Woo orders from a content-edit slice', () => {
expect(exportDbSubset(dump(), { playbook: 'content', postIds: [1] }).tables).not.toContain('wp_wc_orders');
});
it('drops comments from a content-edit slice', () => {
expect(exportDbSubset(dump(), { playbook: 'content', postIds: [1] }).tables).not.toContain('wp_comments');
});
it('redacts option names ending in _key, _secret, or smtp_pass', () => {
const options = exportDbSubset(dump(), { playbook: 'content', postIds: [1] }).options;
expect(options.every((name) => !/(_key|_secret|smtp_pass)$/.test(name))).toBe(true);
});
});
describe('media proxy', () => {
it('does not copy the uploads library', () => {
expect(mediaProxyTarget(dump(), '/wp-content/uploads/2024/hero.jpg')).toBe(
'https://example.com/wp-content/uploads/2024/hero.jpg',
);
});
it('copies a file only when it is replaced', () => {
const staged = stageReplacement(dump(), '/wp-content/uploads/2024/hero.jpg', 12);
expect(staged.copiedPaths).toEqual(['/wp-content/uploads/2024/hero.jpg']);
});
});
+22
View File
@@ -0,0 +1,22 @@
import { describe, it, expect } from 'vitest';
import { loadPrompts } from '../src/load-prompts.ts';
import { loadSite } from '../src/load-site.ts';
describe('golden prompts', () => {
it('loads twenty prompts', () => {
expect(loadPrompts()).toHaveLength(20);
});
it('covers at least two site fixtures', () => {
expect(new Set(loadPrompts().map((p) => p.site)).size).toBeGreaterThanOrEqual(2);
});
it('gives every prompt a preview_text, option, or screenshot assertion', () => {
const types = new Set(loadPrompts().map((p) => p.assert.type));
expect([...types].every((t) => t === 'preview_text' || t === 'option' || t === 'screenshot')).toBe(true);
});
it('points every prompt at a site fixture that exists', () => {
expect(loadPrompts().every((p) => loadSite(p.site).id === p.site)).toBe(true);
});
});
+86
View File
@@ -0,0 +1,86 @@
import { describe, it, expect } from 'vitest';
import { applyTool } from '../src/apply-tool.ts';
import { checkAssertion } from '../src/check-assertion.ts';
import { scoreGrokResponse } from '../src/score.ts';
import type { SiteFixture } from '../src/types.ts';
const site = (): SiteFixture => ({
id: 'gutenberg-business',
theme: 'twentytwentyfour',
plugins: [],
wordpressVersion: '6.6',
phpVersion: '8.2',
options: { blogname: 'Old Biz', blog_public: '1' },
posts: [
{
id: 1,
slug: 'homepage',
title: 'Home',
content: '<!-- wp:heading --><h1>Welcome to our site</h1><!-- /wp:heading -->',
meta: {},
},
],
uploads: [],
});
describe('applyTool', () => {
it('replaces the homepage heading', () => {
const next = applyTool(site(), {
name: 'edit_heading',
arguments: { page: 'homepage', newText: 'Welcome to My Business' },
});
expect(next.posts[0]?.content).toContain('Welcome to My Business');
});
});
describe('checkAssertion', () => {
it('passes preview_text when the page contains the string', () => {
const next = applyTool(site(), {
name: 'edit_heading',
arguments: { page: 'homepage', newText: 'Welcome to My Business' },
});
expect(
checkAssertion(next, { type: 'preview_text', page: 'homepage', contains: 'Welcome to My Business' }).ok,
).toBe(true);
});
it('fails preview_text when the string is absent', () => {
expect(
checkAssertion(site(), { type: 'preview_text', page: 'homepage', contains: 'Welcome to My Business' }).ok,
).toBe(false);
});
it('passes option when the value matches', () => {
const next = applyTool(site(), {
name: 'update_option',
arguments: { key: 'blogname', value: 'My Business' },
});
expect(checkAssertion(next, { type: 'option', key: 'blogname', value: 'My Business' }).ok).toBe(true);
});
});
describe('scoreGrokResponse', () => {
it('passes a Grok tool-call that satisfies the assertion', () => {
const verdict = scoreGrokResponse({
site: site(),
assert: { type: 'preview_text', page: 'homepage', contains: 'Welcome to My Business' },
grok: {
choices: [
{
message: {
tool_calls: [
{
function: {
name: 'edit_heading',
arguments: JSON.stringify({ page: 'homepage', newText: 'Welcome to My Business' }),
},
},
],
},
},
],
},
});
expect(verdict.passed).toBe(true);
});
});