chore: roll up in-progress changes across plugins

- claude-design: scaffold new plugin (plugin.json, CHANGELOG, README)
- llm-security: playground design-system updates (tokens, components,
  tier3 supplement, new tier4 project-view CSS)
- ms-ai-architect: v2 mockup screenshots + local screenshot script
- voyage: annotate.mjs update

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-05-16 21:02:23 +02:00
commit 69610d46bd
20 changed files with 928 additions and 12 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 740 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 735 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 475 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 473 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 668 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 665 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 742 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 740 KiB

View file

@ -0,0 +1,53 @@
#!/usr/bin/env node
// Mockup verification screenshots — sesjon 2 (DS-hoist).
// Captures the 4 mockup states × 2 themes to confirm visual identity
// after hoisting project-view CSS to shared DS.
//
// Output: playground/screenshots/v2-mockup/<state>-<theme>.png
import { chromium } from 'playwright';
import { fileURLToPath } from 'node:url';
import { dirname, resolve, join } from 'node:path';
import { mkdirSync, existsSync } from 'node:fs';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const PLUGIN_ROOT = resolve(__dirname, '..', '..');
const HTML_PATH = join(PLUGIN_ROOT, 'playground', 'v2-mockup.local.html');
const OUT_DIR = join(PLUGIN_ROOT, 'playground', 'screenshots', 'v2-mockup');
const HTML_URL = 'file://' + HTML_PATH;
const VIEWPORT = { width: 1440, height: 1200 };
const STATES = ['overview', 'artifact', 'empty', 'import'];
const THEMES = ['dark', 'light'];
if (!existsSync(OUT_DIR)) mkdirSync(OUT_DIR, { recursive: true });
const browser = await chromium.launch();
const ctx = await browser.newContext({ viewport: VIEWPORT, deviceScaleFactor: 2 });
const page = await ctx.newPage();
await page.goto(HTML_URL, { waitUntil: 'load' });
for (const theme of THEMES) {
await page.evaluate((t) => {
document.documentElement.setAttribute('data-theme', t);
const btns = document.querySelectorAll('[data-action="set-theme"]');
btns.forEach((b) => b.setAttribute('aria-pressed', b.getAttribute('data-target') === t ? 'true' : 'false'));
}, theme);
await page.waitForTimeout(200);
for (const state of STATES) {
await page.evaluate((s) => {
const btn = document.querySelector(`[data-action="set-state"][data-target="${s}"]`);
if (btn) btn.click();
}, state);
await page.waitForTimeout(300);
const outPath = join(OUT_DIR, `${state}-${theme}.png`);
await page.screenshot({ path: outPath, fullPage: true });
console.log(`${state}-${theme}.png`);
}
}
await browser.close();
console.log('\nDone. 8 screenshots → ' + OUT_DIR);