@neonwatty/limner 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -39
- package/dist/cli.js +3 -3
- package/dist/cli.js.map +1 -1
- package/dist/commands/compare-image-reference.d.ts +3 -0
- package/dist/commands/compare-image-reference.js +26 -3
- package/dist/commands/compare-image-reference.js.map +1 -1
- package/dist/commands/compare.d.ts +4 -1
- package/dist/commands/compare.js +72 -45
- package/dist/commands/compare.js.map +1 -1
- package/dist/core/agent-comparison-fingerprint.d.ts +12 -0
- package/dist/core/agent-comparison-fingerprint.js +27 -0
- package/dist/core/agent-comparison-fingerprint.js.map +1 -0
- package/dist/core/agent-comparison-pack.d.ts +30 -0
- package/dist/core/agent-comparison-pack.js +148 -0
- package/dist/core/agent-comparison-pack.js.map +1 -0
- package/dist/core/agent-comparison-profiles.d.ts +9 -0
- package/dist/core/agent-comparison-profiles.js +19 -0
- package/dist/core/agent-comparison-profiles.js.map +1 -0
- package/dist/core/agent-comparison-prompts.d.ts +22 -0
- package/dist/core/agent-comparison-prompts.js +84 -0
- package/dist/core/agent-comparison-prompts.js.map +1 -0
- package/dist/core/agent-comparison-report.d.ts +3 -0
- package/dist/core/agent-comparison-report.js +56 -0
- package/dist/core/agent-comparison-report.js.map +1 -0
- package/dist/core/agent-comparison-validation.d.ts +2 -0
- package/dist/core/agent-comparison-validation.js +8 -0
- package/dist/core/agent-comparison-validation.js.map +1 -0
- package/dist/core/playwright-capture.js +1 -1
- package/dist/core/playwright-capture.js.map +1 -1
- package/dist/core/report-writer.d.ts +7 -11
- package/dist/core/report-writer.js +21 -43
- package/dist/core/report-writer.js.map +1 -1
- package/dist/core/visual-spec-prompts.js +2 -2
- package/dist/core/visual-spec-prompts.js.map +1 -1
- package/dist/core/workspace.d.ts +1 -0
- package/dist/core/workspace.js +13 -2
- package/dist/core/workspace.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/schemas/comparison.d.ts +349 -0
- package/dist/schemas/comparison.js +211 -0
- package/dist/schemas/comparison.js.map +1 -0
- package/dist/schemas/visual-spec.d.ts +8 -8
- package/dist/schemas/visual-spec.js +2 -2
- package/dist/schemas/visual-spec.js.map +1 -1
- package/docs/agent-workflow.md +20 -33
- package/docs/superpowers/plans/2026-06-12-agent-comparison-scores.md +209 -0
- package/package.json +2 -2
- package/skills/limner/SKILL.md +18 -21
- package/templates/target/AGENT_GUIDE.md +13 -9
- package/dist/commands/compare-image-app.d.ts +0 -12
- package/dist/commands/compare-image-app.js +0 -45
- package/dist/commands/compare-image-app.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neonwatty/limner",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Agent-guided visual fidelity workbench for turning images into HTML references and comparing references to real apps.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
|
-
"
|
|
7
|
+
"limner": "dist/cli.js"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"dist",
|
package/skills/limner/SKILL.md
CHANGED
|
@@ -1,25 +1,29 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: limner
|
|
3
|
-
description: Use when turning an image into
|
|
3
|
+
description: Use when turning an image into an HTML mockup or comparing an approved mockup against an implementation.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Limner
|
|
7
7
|
|
|
8
8
|
Use Limner for structured visual fidelity loops.
|
|
9
9
|
|
|
10
|
+
Prompt profiles: `ideal-to-mockup` for Image To Reference, and `mockup-to-implementation` for Reference To Implementation.
|
|
11
|
+
|
|
10
12
|
## Image To Reference
|
|
11
13
|
|
|
12
|
-
1. Run `
|
|
14
|
+
1. Run `limner init <image> --target <name>` if the target does not exist.
|
|
13
15
|
2. Inspect `source/ideal.png`.
|
|
14
16
|
3. Fill `contract/regions.json`, `contract/tokens.json`, and `contract/acceptance.md`.
|
|
15
17
|
4. Edit `reference/index.html` and `reference/styles.css`.
|
|
16
|
-
5. Run `
|
|
17
|
-
6.
|
|
18
|
-
7.
|
|
18
|
+
5. Run `limner compare image-reference --target <name>`.
|
|
19
|
+
6. Read `captures/image-reference/agent-comparison/agent-prompt.codex.md`.
|
|
20
|
+
7. Write `captures/image-reference/agent-comparison/agent-response.json`.
|
|
21
|
+
8. Rerun `limner compare image-reference --target <name>` so Limner validates `image-comparison.json` and `comparison-summary.json`.
|
|
22
|
+
9. Use the validated next-iteration guidance for one scoped mockup fix.
|
|
19
23
|
|
|
20
24
|
Optional structured spec layer:
|
|
21
25
|
|
|
22
|
-
- Run `
|
|
26
|
+
- Run `limner compare image-reference --target <name> --spec`.
|
|
23
27
|
- Edit `contract/visual-spec-instructions.md` to customize the agent prompt for this target, or pass `--spec-instructions <path>` for a shared policy file.
|
|
24
28
|
- Use `captures/image-reference/spec/agent-prompt.codex.md` for Codex or `captures/image-reference/spec/agent-prompt.claude.md` for Claude.
|
|
25
29
|
- Use the generated `captures/image-reference/spec/agent-response.schema.json` for strict structured output when the agent supports it.
|
|
@@ -27,25 +31,18 @@ Optional structured spec layer:
|
|
|
27
31
|
- Have the agent write `captures/image-reference/spec/agent-response.json`.
|
|
28
32
|
- Rerun the same command so Limner can validate the response and emit the spec and diff JSON artifacts.
|
|
29
33
|
|
|
30
|
-
## Reference To
|
|
34
|
+
## Reference To Implementation
|
|
31
35
|
|
|
32
36
|
1. Confirm the reference HTML is approved.
|
|
33
|
-
2. Ensure every important region has both `referenceSelector` and `appSelector`.
|
|
34
|
-
3. Run `
|
|
35
|
-
4.
|
|
36
|
-
5.
|
|
37
|
-
6. Rerun
|
|
38
|
-
|
|
39
|
-
## Image To App Grounding
|
|
40
|
-
|
|
41
|
-
Use `limn compare image-app --target <name> --url <app-url>` to compare the source image directly to an app screenshot.
|
|
42
|
-
|
|
43
|
-
Add `--storage-state <path>` for authenticated pages and `--full-page` only when a full-page screenshot is intended. The default is viewport-only.
|
|
44
|
-
|
|
45
|
-
For generated-image reconstruction work, do not skip Image To Reference. Build the HTML facsimile first, then compare the approved reference to the app.
|
|
37
|
+
2. Ensure every important region has both `referenceSelector` and an implementation selector in `appSelector`.
|
|
38
|
+
3. Run `limner compare reference-implementation --target <name> --url <implementation-url>`.
|
|
39
|
+
4. Read `captures/reference-implementation/agent-comparison/agent-prompt.codex.md`.
|
|
40
|
+
5. Write `captures/reference-implementation/agent-comparison/agent-response.json`.
|
|
41
|
+
6. Rerun the same command so Limner validates image, structure, and summary comparison artifacts.
|
|
42
|
+
7. Use the validated next-iteration guidance for one scoped implementation fix.
|
|
46
43
|
|
|
47
44
|
## Constraints
|
|
48
45
|
|
|
49
|
-
- Limner does not call an AI vision model itself.
|
|
46
|
+
- Limner does not call an AI vision model itself. Agent comparison and the `--spec` workflow require an external agent.
|
|
50
47
|
- Limner does not make final pass/fail judgments.
|
|
51
48
|
- Limner logs only local JSONL events under `.limner/runs/`.
|
|
@@ -2,23 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
Use this target folder as a structured workbench for visual fidelity.
|
|
4
4
|
|
|
5
|
+
Prompt profiles: `ideal-to-mockup` for Loop 1, and `mockup-to-implementation` for Loop 2.
|
|
6
|
+
|
|
5
7
|
## Loop 1: Image To Reference
|
|
6
8
|
|
|
7
9
|
1. Inspect `source/ideal.png`.
|
|
8
10
|
2. Fill out `contract/regions.json`, `contract/tokens.json`, and `contract/acceptance.md`.
|
|
9
11
|
3. Edit `reference/index.html` and `reference/styles.css` until the reference is a faithful HTML facsimile.
|
|
10
|
-
4. Run `
|
|
11
|
-
5.
|
|
12
|
-
6.
|
|
12
|
+
4. Run `limner compare image-reference --target <target>`.
|
|
13
|
+
5. Read `captures/image-reference/agent-comparison/agent-prompt.codex.md`.
|
|
14
|
+
6. Write `captures/image-reference/agent-comparison/agent-response.json`.
|
|
15
|
+
7. Rerun the comparison and use the validated next-iteration guidance for one scoped mockup fix.
|
|
13
16
|
|
|
14
|
-
## Loop 2: Reference To
|
|
17
|
+
## Loop 2: Reference To Implementation
|
|
15
18
|
|
|
16
19
|
1. Treat the reference HTML as the approved design.
|
|
17
|
-
2. Add
|
|
18
|
-
3. Run `
|
|
19
|
-
4.
|
|
20
|
-
5.
|
|
20
|
+
2. Add implementation selectors to `contract/regions.json` using `appSelector`.
|
|
21
|
+
3. Run `limner compare reference-implementation --target <target> --url <implementation-url>`.
|
|
22
|
+
4. Read `captures/reference-implementation/agent-comparison/agent-prompt.codex.md`.
|
|
23
|
+
5. Write `captures/reference-implementation/agent-comparison/agent-response.json`.
|
|
24
|
+
6. Rerun the comparison and use the validated next-iteration guidance for one scoped implementation fix.
|
|
21
25
|
|
|
22
26
|
## Rule
|
|
23
27
|
|
|
24
|
-
Limner does not decide visual success automatically. It produces evidence
|
|
28
|
+
Limner does not decide visual success automatically. It produces evidence and validates agent-authored UX comparisons so the next implementation iteration is focused.
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export declare function compareImageApp(options: {
|
|
2
|
-
workspaceRoot: string;
|
|
3
|
-
target: string;
|
|
4
|
-
url: string;
|
|
5
|
-
headed?: boolean;
|
|
6
|
-
storageState?: string;
|
|
7
|
-
fullPage?: boolean;
|
|
8
|
-
}): Promise<{
|
|
9
|
-
sideBySidePath: string;
|
|
10
|
-
reportPath: string;
|
|
11
|
-
appPath: string;
|
|
12
|
-
}>;
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { mkdir } from 'node:fs/promises';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import { capturePage } from '../core/playwright-capture.js';
|
|
4
|
-
import { writeImageAppReport } from '../core/report-writer.js';
|
|
5
|
-
import { createRunLogger } from '../core/run-logger.js';
|
|
6
|
-
import { createSideBySideImage } from '../core/side-by-side.js';
|
|
7
|
-
import { resolveTarget, resolveWorkspace } from '../core/workspace.js';
|
|
8
|
-
export async function compareImageApp(options) {
|
|
9
|
-
const workspace = resolveWorkspace(options.workspaceRoot);
|
|
10
|
-
const target = resolveTarget(options.workspaceRoot, options.target);
|
|
11
|
-
const logger = await createRunLogger(workspace, { command: 'compare', target: options.target, mode: 'image-app' });
|
|
12
|
-
const captureDir = path.join(target.capturesDir, 'image-app');
|
|
13
|
-
const appPath = path.join(captureDir, 'app.png');
|
|
14
|
-
const sideBySidePath = path.join(captureDir, 'side-by-side.png');
|
|
15
|
-
try {
|
|
16
|
-
await logger.event({ type: 'command.started' });
|
|
17
|
-
await mkdir(captureDir, { recursive: true });
|
|
18
|
-
await capturePage({
|
|
19
|
-
url: options.url,
|
|
20
|
-
outputPath: appPath,
|
|
21
|
-
headed: options.headed,
|
|
22
|
-
storageState: options.storageState,
|
|
23
|
-
fullPage: options.fullPage,
|
|
24
|
-
});
|
|
25
|
-
await createSideBySideImage({ leftPath: target.sourceImagePath, rightPath: appPath, outputPath: sideBySidePath });
|
|
26
|
-
const reportPath = await writeImageAppReport({
|
|
27
|
-
target,
|
|
28
|
-
idealPath: target.sourceImagePath,
|
|
29
|
-
appPath,
|
|
30
|
-
sideBySidePath,
|
|
31
|
-
appUrl: options.url,
|
|
32
|
-
});
|
|
33
|
-
await logger.artifact(appPath, 'screenshot');
|
|
34
|
-
await logger.artifact(sideBySidePath, 'side-by-side');
|
|
35
|
-
await logger.artifact(reportPath, 'report');
|
|
36
|
-
await logger.complete('ok');
|
|
37
|
-
return { sideBySidePath, reportPath, appPath };
|
|
38
|
-
}
|
|
39
|
-
catch (error) {
|
|
40
|
-
await logger.event({ type: 'command.failed', status: 'failed', message: error instanceof Error ? error.message : String(error) });
|
|
41
|
-
await logger.complete('failed');
|
|
42
|
-
throw error;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
//# sourceMappingURL=compare-image-app.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"compare-image-app.js","sourceRoot":"","sources":["../../src/commands/compare-image-app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAEvE,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAOrC;IACC,MAAM,SAAS,GAAG,gBAAgB,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IAC1D,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACpE,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;IACnH,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IAC9D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IACjD,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;IAEjE,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,CAAC;QAChD,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7C,MAAM,WAAW,CAAC;YAChB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,UAAU,EAAE,OAAO;YACnB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,QAAQ,EAAE,OAAO,CAAC,QAAQ;SAC3B,CAAC,CAAC;QACH,MAAM,qBAAqB,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,eAAe,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,CAAC,CAAC;QAClH,MAAM,UAAU,GAAG,MAAM,mBAAmB,CAAC;YAC3C,MAAM;YACN,SAAS,EAAE,MAAM,CAAC,eAAe;YACjC,OAAO;YACP,cAAc;YACd,MAAM,EAAE,OAAO,CAAC,GAAG;SACpB,CAAC,CAAC;QACH,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QAC7C,MAAM,MAAM,CAAC,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;QACtD,MAAM,MAAM,CAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAC5C,MAAM,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC5B,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;IACjD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,MAAM,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClI,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAChC,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
|