mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-12 06:06:37 +03:00
Oracle: re-record the Sep-1 verb fixes ported to the Rust engine
Five fixes landed on main in JS between the swap branch and its rebase and were ported to the engine; the goldens they touch are re-recorded from the fixed binary, each engine output first diffed byte-for-byte against the upstream JS on the same inputs. DELTAS.md documents every case with its upstream hash. - critique-* (usage/unknown/latest-existing/write-then-read/write-monorepo-child): the #660 critique close path (identity + fingerprint freshness, ~NNNN collision suffix, closed flag, close verb, latest --json). Upstream5211bdf4. - detect-* (new overused-font fixture cases, dir/scope/no-advisory sweeps): the #678 overused-font primary-face change (a system stack keeps its system face, so a Roboto fallback no longer flags). Upstream2cfd6076. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WaJv2c4oN8wS7Ttq4XRqyx
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
aa65db332d
commit
a7a63180f5
@@ -1,84 +0,0 @@
|
||||
import { describe, it } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import { copyFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, unlinkSync, writeFileSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath, pathToFileURL } from 'node:url';
|
||||
|
||||
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
||||
const SOURCE_SCRIPT = path.join(ROOT, 'skill', 'scripts', 'generate-image.mjs');
|
||||
const EMBED_SCRIPT = path.join(ROOT, 'skill', 'scripts', 'embed-prompt.mjs');
|
||||
const PNG_B64 = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==';
|
||||
|
||||
function makeSpacedInstall({ withEmbed = true } = {}) {
|
||||
const parent = mkdtempSync(path.join(tmpdir(), 'gen-img-parent-'));
|
||||
const installDir = path.join(parent, 'impeccable space');
|
||||
mkdirSync(installDir, { recursive: true });
|
||||
copyFileSync(SOURCE_SCRIPT, path.join(installDir, 'generate-image.mjs'));
|
||||
if (withEmbed) copyFileSync(EMBED_SCRIPT, path.join(installDir, 'embed-prompt.mjs'));
|
||||
const preload = path.join(parent, 'fetch-mock.mjs');
|
||||
writeFileSync(preload, `globalThis.fetch = async () => ({ ok: true, json: async () => ({ data: [{ b64_json: '${PNG_B64}' }] }) });\n`);
|
||||
const cwd = mkdtempSync(path.join(tmpdir(), 'gen-img-cwd-'));
|
||||
return { parent, installDir, cwd, script: path.join(installDir, 'generate-image.mjs'), preload };
|
||||
}
|
||||
|
||||
function runGenerate(install, prompt) {
|
||||
const out = path.join(install.cwd, 'out.png');
|
||||
const env = { ...process.env, OPENAI_API_KEY: 'test-key' };
|
||||
delete env.IMPECCABLE_IMAGE_GEN_FAKE;
|
||||
const result = spawnSync(process.execPath, [
|
||||
'--import', pathToFileURL(install.preload).href,
|
||||
install.script,
|
||||
'--prompt', prompt,
|
||||
'--out', out,
|
||||
], {
|
||||
cwd: install.cwd,
|
||||
encoding: 'utf-8',
|
||||
env,
|
||||
});
|
||||
return { ...result, out, sidecar: `${out}.json` };
|
||||
}
|
||||
|
||||
function cleanup(install) {
|
||||
rmSync(install.parent, { recursive: true, force: true });
|
||||
rmSync(install.cwd, { recursive: true, force: true });
|
||||
}
|
||||
|
||||
describe('generate-image embed', () => {
|
||||
it('embeds prompt when install path contains a space', () => {
|
||||
const install = makeSpacedInstall({ withEmbed: true });
|
||||
try {
|
||||
const prompt = 'space-path embed test';
|
||||
const result = runGenerate(install, prompt);
|
||||
assert.equal(result.status, 0, result.stderr);
|
||||
assert.match(result.stdout, /prompt embedded/);
|
||||
assert.ok(existsSync(result.out));
|
||||
assert.ok(existsSync(result.sidecar));
|
||||
assert.equal(JSON.parse(readFileSync(result.sidecar, 'utf8')).prompt, prompt);
|
||||
unlinkSync(result.sidecar);
|
||||
const readBack = spawnSync(process.execPath, [path.join(install.installDir, 'embed-prompt.mjs'), result.out, '--read'], {
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
assert.equal(readBack.status, 0, readBack.stderr);
|
||||
assert.equal(readBack.stdout.trim(), prompt);
|
||||
} finally {
|
||||
cleanup(install);
|
||||
}
|
||||
});
|
||||
|
||||
it('warns when embed helper is missing but keeps image and sidecar', () => {
|
||||
const install = makeSpacedInstall({ withEmbed: false });
|
||||
try {
|
||||
const prompt = 'missing helper test';
|
||||
const result = runGenerate(install, prompt);
|
||||
assert.equal(result.status, 0, result.stderr);
|
||||
assert.doesNotMatch(result.stdout, /prompt embedded/);
|
||||
assert.match(result.stderr, /failed to embed prompt/);
|
||||
assert.ok(existsSync(result.out));
|
||||
assert.ok(existsSync(result.sidecar));
|
||||
} finally {
|
||||
cleanup(install);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -85,3 +85,17 @@ reviewed line by line, so they now pin the fixed behavior.
|
||||
- `hook-session-fresh-then-pending-then-stop`, `hook-session-two-sessions`: the Stop deep pass syncs the remembered set to the live scan, including findings the per-edit pass already surfaced, so a second Stop with nothing new is silent and a fixed-then-reintroduced finding fires again (upstream 3c442af7).
|
||||
- `hadmin-on`, `hadmin-on-twice`, `hadmin-off-then-status`, `hadmin-on-repairs-existing-manifest`, `hadmin-on-malformed-manifest-backup`: the Claude manifests `hooks on` writes match on `Edit|Write` and the description names the current tools; Claude Code folded multi-edit behavior into Edit (upstream 7d5c60d2).
|
||||
- `live-commit-mock-unreported-file-change`: the rollback-failure results share one constructor, which moved `unreportedFiles` and `notes` after `pageUrl` in the emitted JSON (upstream 1f2c3f9d).
|
||||
|
||||
## Recorded 2026-08-31: main's Sep-1 verb fixes ported after the rust-swap rebase
|
||||
|
||||
Five more fixes landed on main in JS between the swap branch and its rebase.
|
||||
Each was ported to the engine and the affected goldens re-recorded from the
|
||||
binary after a line-level review; the engine's output was also diffed
|
||||
byte-for-byte against the upstream JS on the same inputs before recording.
|
||||
|
||||
- `critique-usage`, `critique-unknown`: the usage line now lists the new `close` subcommand (upstream 5211bdf4, #660).
|
||||
- `critique-latest-existing`: `latest` applies the #660 identity/freshness path: a legacy snapshot carrying no fingerprint for a concrete local target is closed and `latest` exits 2 instead of printing the stale body (upstream 5211bdf4, #660).
|
||||
- `critique-write-then-read`: `write` stamps `target_identity`/`target_fingerprint`/`target_path`, uses a fixed-width `~NNNN` collision suffix when two snapshots share a UTC second, `latest` freshness-closes the read snapshot, and `trend` now surfaces the `closed` flag and identity fields (upstream 5211bdf4, #660).
|
||||
- `critique-write-monorepo-child`: `write` stamps the resolved `target_identity`, and a `latest` run from a sibling app resolves to a different identity so it exits 2 rather than returning the neighbor's backlog (upstream 5211bdf4, #660).
|
||||
- `detect-fixture-json-overused-font-html`, `detect-fixture-text-overused-font-html`: new fixture added on the swap branch; overused-font primary selection now skips only the CSS generics, so a system stack keeps its system face as primary and later web-font fallbacks like Roboto no longer flag (upstream 2cfd6076, #678).
|
||||
- `detect-dir-json-all-fixtures`, `detect-dir-text-all-fixtures`, `detect-dir-quiet-all-fixtures`, `detect-scope-type`, `detect-scope-both`, `detect-no-advisory-json`, `detect-no-advisory-text`: the directory sweep picks up the new overused-font fixture and the #678 primary-face change (upstream 2cfd6076, #678).
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"stdout": "---\ntotal_score: 72\np0_count: 1\np1_count: 3\ntarget: \"src/pages/index.astro\"\ntimestamp: \"<ISO>\"\nslug: src-pages-index-astro\n---\n# Critique: Home\n\nHero copy is generic; the CTA sits below the fold.\n",
|
||||
"stdout": "",
|
||||
"stderr": "",
|
||||
"exit": 0,
|
||||
"exit": 2,
|
||||
"signal": null,
|
||||
"files": {}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"stdout": "",
|
||||
"stderr": "usage: impeccable critique-storage <slug|write|latest|trend> [args]\n",
|
||||
"stderr": "usage: impeccable critique-storage <slug|write|latest|trend|close> [args]\n",
|
||||
"exit": 1,
|
||||
"signal": null,
|
||||
"files": {}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"stdout": "",
|
||||
"stderr": "usage: impeccable critique-storage <slug|write|latest|trend> [args]\n",
|
||||
"stderr": "usage: impeccable critique-storage <slug|write|latest|trend|close> [args]\n",
|
||||
"exit": 1,
|
||||
"signal": null,
|
||||
"files": {}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"signal": null
|
||||
},
|
||||
{
|
||||
"stdout": "---\ntimestamp: <STAMP>\nslug: src-app-tsx\n---\nChild critique.\n",
|
||||
"stdout": "---\ntarget_identity: \"file:<WS>/apps/a/src/App.tsx\"\ntarget_fingerprint: \"sha256:2ef6aa1a29b71cfc99d83be19dc97ec8cef0fc8636a8ab706a652b6ecd253b52\"\ntarget_path: <WS>/apps/a/src/App.tsx\ntimestamp: <STAMP>\nslug: src-app-tsx\n---\nChild critique.\n",
|
||||
"stderr": "",
|
||||
"exit": 0,
|
||||
"signal": null
|
||||
|
||||
@@ -7,31 +7,31 @@
|
||||
"signal": null
|
||||
},
|
||||
{
|
||||
"stdout": "---\ntotal_score: 81\np0_count: 0\np1_count: 2\ntarget: src/App.tsx\nnote: \"ratio 3:1 #hero\"\nslug: src-app-tsx\ntimestamp: <STAMP>\n---\n# Critique\n\nScore 81/100.\n",
|
||||
"stdout": "",
|
||||
"stderr": "",
|
||||
"exit": 2,
|
||||
"signal": null
|
||||
},
|
||||
{
|
||||
"stdout": "<WS>/.impeccable/critique/<STAMP>~0001__src-app-tsx.md\n",
|
||||
"stderr": "",
|
||||
"exit": 0,
|
||||
"signal": null
|
||||
},
|
||||
{
|
||||
"stdout": "<WS>/.impeccable/critique/<STAMP>__src-app-tsx.md\n",
|
||||
"stdout": "",
|
||||
"stderr": "",
|
||||
"exit": 2,
|
||||
"signal": null
|
||||
},
|
||||
{
|
||||
"stdout": "[\n {\n \"total_score\": 81,\n \"p0_count\": 0,\n \"p1_count\": 2,\n \"target\": \"src/App.tsx\",\n \"note\": \"ratio 3:1 #hero\",\n \"slug\": \"src-app-tsx\",\n \"timestamp\": \"<STAMP>\",\n \"target_identity\": \"file:<WS>/src/App.tsx\",\n \"closed\": true\n },\n {\n \"target_identity\": \"file:<WS>/src-app-tsx\",\n \"timestamp\": \"<STAMP>\",\n \"slug\": \"src-app-tsx\",\n \"closed\": true\n }\n]\n",
|
||||
"stderr": "",
|
||||
"exit": 0,
|
||||
"signal": null
|
||||
},
|
||||
{
|
||||
"stdout": "---\ntimestamp: <STAMP>\nslug: src-app-tsx\n---\nSecond pass.\n",
|
||||
"stderr": "",
|
||||
"exit": 0,
|
||||
"signal": null
|
||||
},
|
||||
{
|
||||
"stdout": "[\n {\n \"timestamp\": \"<STAMP>\",\n \"slug\": \"src-app-tsx\"\n }\n]\n",
|
||||
"stderr": "",
|
||||
"exit": 0,
|
||||
"signal": null
|
||||
},
|
||||
{
|
||||
"stdout": "[\n {\n \"timestamp\": \"<STAMP>\",\n \"slug\": \"src-app-tsx\"\n }\n]\n",
|
||||
"stdout": "[\n {\n \"target_identity\": \"file:<WS>/src-app-tsx\",\n \"timestamp\": \"<STAMP>\",\n \"slug\": \"src-app-tsx\",\n \"closed\": true\n }\n]\n",
|
||||
"stderr": "",
|
||||
"exit": 0,
|
||||
"signal": null
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"stdout": "",
|
||||
"stderr": "408 anti-patterns found.\n2 advisory notes (not counted).\n",
|
||||
"stderr": "412 anti-patterns found.\n2 advisory notes (not counted).\n",
|
||||
"exit": 2,
|
||||
"signal": null,
|
||||
"files": {}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"stdout": "[\n {\n \"antipattern\": \"overused-font\",\n \"name\": \"Overused font\",\n \"description\": \"Inter, Roboto, Fraunces, Geist, Plus Jakarta Sans, and Space Grotesk are used on so many sites they no longer feel distinctive. Each new wave of AI-generated UIs converges on the same handful of faces. Choose a face that gives your interface personality.\",\n \"severity\": \"warning\",\n \"category\": \"slop\",\n \"file\": \"<REPO>/tests/fixtures/antipatterns/overused-font.html\",\n \"line\": 0,\n \"snippet\": \"Primary font: inter\"\n },\n {\n \"antipattern\": \"overused-font\",\n \"name\": \"Overused font\",\n \"description\": \"Inter, Roboto, Fraunces, Geist, Plus Jakarta Sans, and Space Grotesk are used on so many sites they no longer feel distinctive. Each new wave of AI-generated UIs converges on the same handful of faces. Choose a face that gives your interface personality.\",\n \"severity\": \"warning\",\n \"category\": \"slop\",\n \"file\": \"<REPO>/tests/fixtures/antipatterns/overused-font.html\",\n \"line\": 0,\n \"snippet\": \"Primary font: geist\"\n },\n {\n \"antipattern\": \"overused-font\",\n \"name\": \"Overused font\",\n \"description\": \"Inter, Roboto, Fraunces, Geist, Plus Jakarta Sans, and Space Grotesk are used on so many sites they no longer feel distinctive. Each new wave of AI-generated UIs converges on the same handful of faces. Choose a face that gives your interface personality.\",\n \"severity\": \"warning\",\n \"category\": \"slop\",\n \"file\": \"<REPO>/tests/fixtures/antipatterns/overused-font.html\",\n \"line\": 0,\n \"snippet\": \"Primary font: montserrat\"\n },\n {\n \"antipattern\": \"overused-font\",\n \"name\": \"Overused font\",\n \"description\": \"Inter, Roboto, Fraunces, Geist, Plus Jakarta Sans, and Space Grotesk are used on so many sites they no longer feel distinctive. Each new wave of AI-generated UIs converges on the same handful of faces. Choose a face that gives your interface personality.\",\n \"severity\": \"warning\",\n \"category\": \"slop\",\n \"file\": \"<REPO>/tests/fixtures/antipatterns/overused-font.html\",\n \"line\": 0,\n \"snippet\": \"Primary font: lato\"\n }\n]\n",
|
||||
"stderr": "",
|
||||
"exit": 2,
|
||||
"signal": null,
|
||||
"files": {}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"stdout": "",
|
||||
"stderr": "\n<REPO>/tests/fixtures/antipatterns/overused-font.html\n [overused-font] Primary font: inter\n → Inter, Roboto, Fraunces, Geist, Plus Jakarta Sans, and Space Grotesk are used on so many sites they no longer feel distinctive. Each new wave of AI-generated UIs converges on the same handful of faces. Choose a face that gives your interface personality.\n [overused-font] Primary font: geist\n → Inter, Roboto, Fraunces, Geist, Plus Jakarta Sans, and Space Grotesk are used on so many sites they no longer feel distinctive. Each new wave of AI-generated UIs converges on the same handful of faces. Choose a face that gives your interface personality.\n [overused-font] Primary font: montserrat\n → Inter, Roboto, Fraunces, Geist, Plus Jakarta Sans, and Space Grotesk are used on so many sites they no longer feel distinctive. Each new wave of AI-generated UIs converges on the same handful of faces. Choose a face that gives your interface personality.\n [overused-font] Primary font: lato\n → Inter, Roboto, Fraunces, Geist, Plus Jakarta Sans, and Space Grotesk are used on so many sites they no longer feel distinctive. Each new wave of AI-generated UIs converges on the same handful of faces. Choose a face that gives your interface personality.\n\n4 anti-patterns found.\n",
|
||||
"exit": 2,
|
||||
"signal": null,
|
||||
"files": {}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user