@neonwatty/limner 0.1.2 → 0.1.4
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 +35 -0
- package/dist/cli.js +7 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/ledger.d.ts +43 -0
- package/dist/commands/ledger.js +102 -0
- package/dist/commands/ledger.js.map +1 -0
- package/dist/commands/loop-cli.d.ts +2 -0
- package/dist/commands/loop-cli.js +71 -0
- package/dist/commands/loop-cli.js.map +1 -0
- package/dist/commands/loop-comparison-adapters.d.ts +17 -0
- package/dist/commands/loop-comparison-adapters.js +85 -0
- package/dist/commands/loop-comparison-adapters.js.map +1 -0
- package/dist/commands/loop.d.ts +41 -0
- package/dist/commands/loop.js +151 -0
- package/dist/commands/loop.js.map +1 -0
- package/dist/core/agent-comparison-pack.d.ts +1 -1
- package/dist/core/agent-comparison-profiles.d.ts +1 -1
- package/dist/core/agent-comparison-profiles.js +11 -2
- package/dist/core/agent-comparison-profiles.js.map +1 -1
- package/dist/core/ledger-db.d.ts +6 -0
- package/dist/core/ledger-db.js +106 -0
- package/dist/core/ledger-db.js.map +1 -0
- package/dist/core/ledger-events.d.ts +3 -0
- package/dist/core/ledger-events.js +12 -0
- package/dist/core/ledger-events.js.map +1 -0
- package/dist/core/ledger-ids.d.ts +3 -0
- package/dist/core/ledger-ids.js +12 -0
- package/dist/core/ledger-ids.js.map +1 -0
- package/dist/core/ledger-paths.d.ts +9 -0
- package/dist/core/ledger-paths.js +14 -0
- package/dist/core/ledger-paths.js.map +1 -0
- package/dist/core/ledger-store.d.ts +64 -0
- package/dist/core/ledger-store.js +173 -0
- package/dist/core/ledger-store.js.map +1 -0
- package/dist/core/loop-instructions.d.ts +2 -0
- package/dist/core/loop-instructions.js +8 -0
- package/dist/core/loop-instructions.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/schemas/comparison.d.ts +1 -0
- package/dist/schemas/comparison.js +1 -1
- package/dist/schemas/comparison.js.map +1 -1
- package/dist/schemas/ledger.d.ts +25 -0
- package/dist/schemas/ledger.js +7 -0
- package/dist/schemas/ledger.js.map +1 -0
- package/docs/agent-workflow.md +18 -0
- package/docs/superpowers/plans/2026-06-12-global-loop-ledger.md +160 -0
- package/docs/superpowers/specs/2026-06-12-global-loop-ledger-design.md +254 -0
- package/package.json +3 -1
- package/skills/limner/SKILL.md +16 -0
package/README.md
CHANGED
|
@@ -54,9 +54,13 @@ npm run check
|
|
|
54
54
|
limner init ./ideal.png --target replay-boundaries
|
|
55
55
|
limner preview --target replay-boundaries
|
|
56
56
|
limner capture reference --target replay-boundaries
|
|
57
|
+
limner loop start --mode image-mockup --target replay-boundaries --name replay-boundaries-polish --max-iterations 5
|
|
58
|
+
limner loop compare --trajectory traj_...
|
|
59
|
+
limner loop status --trajectory traj_...
|
|
57
60
|
limner compare image-reference --target replay-boundaries
|
|
58
61
|
limner compare reference-implementation --target replay-boundaries --url http://localhost:3152/internal/optimization-lab/wedding-envelope#replay-boundaries --storage-state ./e2e/.auth/user.json
|
|
59
62
|
limner report --target replay-boundaries
|
|
63
|
+
limner ledger export traj_... --format markdown
|
|
60
64
|
limner runs list
|
|
61
65
|
```
|
|
62
66
|
|
|
@@ -81,6 +85,37 @@ limner-workspace/
|
|
|
81
85
|
|
|
82
86
|
## Modes
|
|
83
87
|
|
|
88
|
+
### Loop Ledger
|
|
89
|
+
|
|
90
|
+
Use `limner loop` for Ralph Loop-style polishing. Loop work is tracked in a global local-only SQLite ledger at `~/.limner/ledger.sqlite`; no telemetry is sent.
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
limner loop start --mode image-mockup --target replay-boundaries --name replay-boundaries-polish --max-iterations 5
|
|
94
|
+
limner loop compare --trajectory traj_...
|
|
95
|
+
limner loop status --trajectory traj_... --feedback "Prompt should mention button contrast."
|
|
96
|
+
limner loop next --trajectory traj_...
|
|
97
|
+
limner loop close --trajectory traj_...
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Loop modes:
|
|
101
|
+
|
|
102
|
+
- `image-mockup`: source image to editable HTML mockup.
|
|
103
|
+
- `mockup-implementation`: approved mockup to real implementation.
|
|
104
|
+
- `image-implementation`: source image directly to real implementation.
|
|
105
|
+
|
|
106
|
+
Every meaningful loop interaction writes a ledger event. `agentFeedback` is an optional 255-character field for short process-improvement notes; longer comments belong in notes or project artifacts.
|
|
107
|
+
|
|
108
|
+
Use `limner ledger` to query and export trajectories:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
limner ledger list --active
|
|
112
|
+
limner ledger status --trajectory traj_...
|
|
113
|
+
limner ledger show traj_...
|
|
114
|
+
limner ledger next --trajectory traj_...
|
|
115
|
+
limner ledger export traj_... --format json
|
|
116
|
+
limner ledger export traj_... --format markdown
|
|
117
|
+
```
|
|
118
|
+
|
|
84
119
|
### Image To Reference
|
|
85
120
|
|
|
86
121
|
Use this while recreating the ideal image as a standalone HTML/CSS mockup. This mode uses the `ideal-to-mockup` agent comparison profile.
|
package/dist/cli.js
CHANGED
|
@@ -1,21 +1,27 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
2
3
|
import { Command } from 'commander';
|
|
3
4
|
import { registerCaptureCommand } from './commands/capture.js';
|
|
4
5
|
import { registerCompareCommand } from './commands/compare.js';
|
|
5
6
|
import { registerInitCommand } from './commands/init.js';
|
|
7
|
+
import { registerLedgerCommand } from './commands/ledger.js';
|
|
8
|
+
import { registerLoopCommand } from './commands/loop-cli.js';
|
|
6
9
|
import { registerPreviewCommand } from './commands/preview.js';
|
|
7
10
|
import { registerReportCommand } from './commands/report.js';
|
|
8
11
|
import { registerRunsCommand } from './commands/runs.js';
|
|
12
|
+
const packageJson = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
|
|
9
13
|
const program = new Command();
|
|
10
14
|
program
|
|
11
15
|
.name('limner')
|
|
12
16
|
.description('Agent-guided visual fidelity workbench')
|
|
13
|
-
.version(
|
|
17
|
+
.version(packageJson.version)
|
|
14
18
|
.option('-w, --workspace <path>', 'Limner workspace root', process.cwd());
|
|
15
19
|
registerInitCommand(program);
|
|
16
20
|
registerPreviewCommand(program);
|
|
17
21
|
registerCaptureCommand(program);
|
|
18
22
|
registerCompareCommand(program);
|
|
23
|
+
registerLoopCommand(program);
|
|
24
|
+
registerLedgerCommand(program);
|
|
19
25
|
registerReportCommand(program);
|
|
20
26
|
registerRunsCommand(program);
|
|
21
27
|
program.parseAsync(process.argv).catch((error) => {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CAAC,wCAAwC,CAAC;KACrD,OAAO,CAAC,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAC5B,YAAY,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAC3C,CAAC;AAEzB,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CAAC,wCAAwC,CAAC;KACrD,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC;KAC5B,MAAM,CAAC,wBAAwB,EAAE,uBAAuB,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;AAE5E,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAChC,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAChC,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAChC,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAE7B,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IACxD,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,OAAO,CAAC,KAAK,CAAC,WAAW,OAAO,EAAE,CAAC,CAAC;IACpC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import type { LedgerMode } from '../schemas/ledger.js';
|
|
3
|
+
type LedgerEnv = Partial<Pick<NodeJS.ProcessEnv, 'LIMNER_LEDGER_HOME'>>;
|
|
4
|
+
export declare function listLedger(input: {
|
|
5
|
+
ledgerEnv?: LedgerEnv;
|
|
6
|
+
active?: boolean;
|
|
7
|
+
projectRoot?: string;
|
|
8
|
+
mode?: LedgerMode;
|
|
9
|
+
}): {
|
|
10
|
+
lines: string[];
|
|
11
|
+
};
|
|
12
|
+
export declare function getLedgerStatus(input: {
|
|
13
|
+
ledgerEnv?: LedgerEnv;
|
|
14
|
+
trajectoryId: string;
|
|
15
|
+
}): {
|
|
16
|
+
lines: string[];
|
|
17
|
+
};
|
|
18
|
+
export declare function showLedger(input: {
|
|
19
|
+
ledgerEnv?: LedgerEnv;
|
|
20
|
+
trajectoryId: string;
|
|
21
|
+
}): {
|
|
22
|
+
json: {
|
|
23
|
+
trajectory: import("../core/ledger-store.js").TrajectorySummary;
|
|
24
|
+
iterations: unknown[];
|
|
25
|
+
events: unknown[];
|
|
26
|
+
instructionVersions: unknown[];
|
|
27
|
+
notes: unknown[];
|
|
28
|
+
artifacts: unknown[];
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
export declare function getLedgerNext(input: {
|
|
32
|
+
ledgerEnv?: LedgerEnv;
|
|
33
|
+
trajectoryId: string;
|
|
34
|
+
}): {
|
|
35
|
+
line: string;
|
|
36
|
+
};
|
|
37
|
+
export declare function exportLedger(input: {
|
|
38
|
+
ledgerEnv?: LedgerEnv;
|
|
39
|
+
trajectoryId: string;
|
|
40
|
+
format: 'json' | 'markdown';
|
|
41
|
+
}): string;
|
|
42
|
+
export declare function registerLedgerCommand(program: Command): void;
|
|
43
|
+
export {};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { openLedgerDatabase } from '../core/ledger-db.js';
|
|
2
|
+
import { resolveLedgerPaths } from '../core/ledger-paths.js';
|
|
3
|
+
import { createLedgerStore } from '../core/ledger-store.js';
|
|
4
|
+
export function listLedger(input) {
|
|
5
|
+
return withDb(input.ledgerEnv, (db) => {
|
|
6
|
+
const conditions = [];
|
|
7
|
+
const params = [];
|
|
8
|
+
if (input.active) {
|
|
9
|
+
conditions.push("status = 'active'");
|
|
10
|
+
}
|
|
11
|
+
if (input.projectRoot) {
|
|
12
|
+
conditions.push('project_root = ?');
|
|
13
|
+
params.push(input.projectRoot);
|
|
14
|
+
}
|
|
15
|
+
if (input.mode) {
|
|
16
|
+
conditions.push('mode = ?');
|
|
17
|
+
params.push(input.mode);
|
|
18
|
+
}
|
|
19
|
+
const where = conditions.length > 0 ? `where ${conditions.join(' and ')}` : '';
|
|
20
|
+
const rows = db.prepare(`select trajectory_id as trajectoryId, human_id as humanId, mode, target, status from trajectories ${where} order by updated_at desc`).all(...params);
|
|
21
|
+
return { lines: rows.map(formatRow) };
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
export function getLedgerStatus(input) {
|
|
25
|
+
return withStore(input.ledgerEnv, (store) => {
|
|
26
|
+
const trajectory = store.resolveTrajectory({ trajectoryId: input.trajectoryId });
|
|
27
|
+
store.appendEvent({ trajectoryId: trajectory.trajectoryId, eventType: 'ledger.status.viewed', actor: 'cli', command: 'ledger status', resultStatus: 'ok' });
|
|
28
|
+
const exported = store.exportTrajectoryJson(trajectory.trajectoryId);
|
|
29
|
+
return {
|
|
30
|
+
lines: [
|
|
31
|
+
`Trajectory: ${trajectory.trajectoryId}`,
|
|
32
|
+
`Name: ${trajectory.humanId}`,
|
|
33
|
+
`Mode: ${trajectory.mode}`,
|
|
34
|
+
`Target: ${trajectory.target}`,
|
|
35
|
+
`Status: ${trajectory.status}`,
|
|
36
|
+
`Iterations: ${exported.iterations.length}`,
|
|
37
|
+
`Events: ${exported.events.length}`,
|
|
38
|
+
],
|
|
39
|
+
};
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
export function showLedger(input) {
|
|
43
|
+
return withStore(input.ledgerEnv, (store) => {
|
|
44
|
+
store.appendEvent({ trajectoryId: input.trajectoryId, eventType: 'ledger.show.viewed', actor: 'cli', command: 'ledger show', resultStatus: 'ok' });
|
|
45
|
+
return { json: store.exportTrajectoryJson(input.trajectoryId) };
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
export function getLedgerNext(input) {
|
|
49
|
+
return withStore(input.ledgerEnv, (store) => {
|
|
50
|
+
const trajectory = store.resolveTrajectory({ trajectoryId: input.trajectoryId });
|
|
51
|
+
store.appendEvent({ trajectoryId: trajectory.trajectoryId, eventType: 'ledger.next.viewed', actor: 'cli', command: 'ledger next', resultStatus: 'ok' });
|
|
52
|
+
return { line: `Next: run limner loop compare --trajectory ${trajectory.trajectoryId}` };
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
export function exportLedger(input) {
|
|
56
|
+
return withStore(input.ledgerEnv, (store) => {
|
|
57
|
+
store.appendEvent({ trajectoryId: input.trajectoryId, eventType: 'ledger.exported', actor: 'cli', command: 'ledger export', resultStatus: 'ok' });
|
|
58
|
+
const exported = store.exportTrajectoryJson(input.trajectoryId);
|
|
59
|
+
if (input.format === 'json')
|
|
60
|
+
return JSON.stringify(exported, null, 2) + '\n';
|
|
61
|
+
return [
|
|
62
|
+
'# Limner Trajectory',
|
|
63
|
+
'',
|
|
64
|
+
`Trajectory: ${exported.trajectory.trajectoryId}`,
|
|
65
|
+
`Name: ${exported.trajectory.humanId}`,
|
|
66
|
+
`Mode: ${exported.trajectory.mode}`,
|
|
67
|
+
`Status: ${exported.trajectory.status}`,
|
|
68
|
+
`Iterations: ${exported.iterations.length}`,
|
|
69
|
+
`Events: ${exported.events.length}`,
|
|
70
|
+
'',
|
|
71
|
+
].join('\n');
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
export function registerLedgerCommand(program) {
|
|
75
|
+
const ledger = program.command('ledger').description('Query the global Limner loop ledger');
|
|
76
|
+
ledger.command('list').option('--active', 'only active trajectories').option('--project <path>', 'project root').option('--mode <mode>', 'loop mode')
|
|
77
|
+
.action((options) => console.log(listLedger({ active: options.active, projectRoot: options.project, mode: options.mode }).lines.join('\n')));
|
|
78
|
+
ledger.command('status').requiredOption('--trajectory <id>', 'trajectory id')
|
|
79
|
+
.action((options) => console.log(getLedgerStatus({ trajectoryId: options.trajectory }).lines.join('\n')));
|
|
80
|
+
ledger.command('show').argument('<id>', 'trajectory id')
|
|
81
|
+
.action((id) => console.log(JSON.stringify(showLedger({ trajectoryId: id }).json, null, 2)));
|
|
82
|
+
ledger.command('next').requiredOption('--trajectory <id>', 'trajectory id')
|
|
83
|
+
.action((options) => console.log(getLedgerNext({ trajectoryId: options.trajectory }).line));
|
|
84
|
+
ledger.command('export').argument('<id>', 'trajectory id').option('--format <format>', 'json or markdown', 'json')
|
|
85
|
+
.action((id, options) => console.log(exportLedger({ trajectoryId: id, format: options.format })));
|
|
86
|
+
}
|
|
87
|
+
function withStore(env, callback) {
|
|
88
|
+
return withDb(env, (db) => callback(createLedgerStore(db)));
|
|
89
|
+
}
|
|
90
|
+
function withDb(env, callback) {
|
|
91
|
+
const db = openLedgerDatabase({ databasePath: resolveLedgerPaths(env).databasePath });
|
|
92
|
+
try {
|
|
93
|
+
return callback(db);
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
db.close();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function formatRow(row) {
|
|
100
|
+
return `${row.trajectoryId} ${row.mode} ${row.target} ${row.status} ${row.humanId}`;
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=ledger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ledger.js","sourceRoot":"","sources":["../../src/commands/ledger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { advanceLoop, closeLoop, compareLoop, getLoopStatus, startLoop } from './loop.js';
|
|
2
|
+
export function registerLoopCommand(program) {
|
|
3
|
+
const loop = program.command('loop').description('Manage Limner comparison loops');
|
|
4
|
+
loop
|
|
5
|
+
.command('start')
|
|
6
|
+
.requiredOption('--mode <mode>', 'loop mode')
|
|
7
|
+
.requiredOption('-t, --target <name>', 'target name')
|
|
8
|
+
.option('--name <name>', 'human-readable trajectory name')
|
|
9
|
+
.option('--max-iterations <count>', 'maximum planned iterations')
|
|
10
|
+
.option('-u, --url <url>', 'implementation URL for implementation modes')
|
|
11
|
+
.option('--storage-state <path>', 'Playwright storageState JSON')
|
|
12
|
+
.option('--full-page', 'capture the full scrollable page')
|
|
13
|
+
.action((options, command) => {
|
|
14
|
+
const globals = command.optsWithGlobals();
|
|
15
|
+
const result = startLoop({
|
|
16
|
+
workspaceRoot: globals.workspace,
|
|
17
|
+
target: options.target,
|
|
18
|
+
mode: options.mode,
|
|
19
|
+
name: options.name,
|
|
20
|
+
maxIterations: options.maxIterations ? Number(options.maxIterations) : undefined,
|
|
21
|
+
url: options.url,
|
|
22
|
+
storageState: options.storageState,
|
|
23
|
+
fullPage: options.fullPage,
|
|
24
|
+
});
|
|
25
|
+
console.log(`Trajectory: ${result.trajectoryId}`);
|
|
26
|
+
console.log(`Active iteration: ${result.iterationId}`);
|
|
27
|
+
});
|
|
28
|
+
loop
|
|
29
|
+
.command('status')
|
|
30
|
+
.option('--trajectory <id>', 'trajectory id')
|
|
31
|
+
.option('-t, --target <name>', 'target name')
|
|
32
|
+
.option('--mode <mode>', 'loop mode')
|
|
33
|
+
.option('--feedback <text>', 'short agent feedback, max 255 characters')
|
|
34
|
+
.action((options) => {
|
|
35
|
+
console.log(getLoopStatus({ trajectoryId: options.trajectory, target: options.target, mode: options.mode, feedback: options.feedback }).lines.join('\n'));
|
|
36
|
+
});
|
|
37
|
+
loop.command('next').option('--trajectory <id>', 'trajectory id').action((options) => {
|
|
38
|
+
console.log(`Active iteration: ${advanceLoop({ trajectoryId: options.trajectory }).iterationId}`);
|
|
39
|
+
});
|
|
40
|
+
loop.command('close').option('--trajectory <id>', 'trajectory id').action((options) => {
|
|
41
|
+
console.log(`Status: ${closeLoop({ trajectoryId: options.trajectory }).status}`);
|
|
42
|
+
});
|
|
43
|
+
loop
|
|
44
|
+
.command('compare')
|
|
45
|
+
.option('--trajectory <id>', 'trajectory id')
|
|
46
|
+
.option('-t, --target <name>', 'target name')
|
|
47
|
+
.option('--mode <mode>', 'loop mode')
|
|
48
|
+
.option('-u, --url <url>', 'implementation URL')
|
|
49
|
+
.option('--storage-state <path>', 'Playwright storageState JSON')
|
|
50
|
+
.option('--headed', 'show browser while capturing')
|
|
51
|
+
.option('--full-page', 'capture the full scrollable page')
|
|
52
|
+
.action(async (options, command) => {
|
|
53
|
+
const globals = command.optsWithGlobals();
|
|
54
|
+
const result = await compareLoop({
|
|
55
|
+
workspaceRoot: globals.workspace,
|
|
56
|
+
trajectoryId: options.trajectory,
|
|
57
|
+
target: options.target,
|
|
58
|
+
mode: options.mode,
|
|
59
|
+
url: options.url,
|
|
60
|
+
storageState: options.storageState,
|
|
61
|
+
headed: options.headed,
|
|
62
|
+
fullPage: options.fullPage,
|
|
63
|
+
});
|
|
64
|
+
console.log(`Side-by-side: ${result.sideBySidePath}`);
|
|
65
|
+
if (result.reportPath)
|
|
66
|
+
console.log(`Report: ${result.reportPath}`);
|
|
67
|
+
if (result.agentComparison)
|
|
68
|
+
console.log(`Agent comparison status: ${result.agentComparison.status}`);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=loop-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loop-cli.js","sourceRoot":"","sources":["../../src/commands/loop-cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type AgentComparisonPackResult } from '../core/agent-comparison-pack.js';
|
|
2
|
+
import type { LedgerMode } from '../schemas/ledger.js';
|
|
3
|
+
export type LoopCompareInput = {
|
|
4
|
+
workspaceRoot: string;
|
|
5
|
+
target: string;
|
|
6
|
+
mode: LedgerMode;
|
|
7
|
+
url?: string;
|
|
8
|
+
storageState?: string;
|
|
9
|
+
headed?: boolean;
|
|
10
|
+
fullPage?: boolean;
|
|
11
|
+
};
|
|
12
|
+
export type LoopCompareResult = {
|
|
13
|
+
sideBySidePath: string;
|
|
14
|
+
reportPath?: string;
|
|
15
|
+
agentComparison?: AgentComparisonPackResult;
|
|
16
|
+
};
|
|
17
|
+
export declare function runLoopComparison(input: LoopCompareInput): Promise<LoopCompareResult>;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { writeAgentComparisonPack } from '../core/agent-comparison-pack.js';
|
|
4
|
+
import { loadRegionContract } from '../core/dom-metrics.js';
|
|
5
|
+
import { capturePage } from '../core/playwright-capture.js';
|
|
6
|
+
import { createRunLogger } from '../core/run-logger.js';
|
|
7
|
+
import { createSideBySideImage } from '../core/side-by-side.js';
|
|
8
|
+
import { resolveTargetWithSource, resolveWorkspace } from '../core/workspace.js';
|
|
9
|
+
import { compareImageReference, compareReferenceImplementation } from './compare.js';
|
|
10
|
+
export async function runLoopComparison(input) {
|
|
11
|
+
if (input.mode === 'image-mockup') {
|
|
12
|
+
return compareImageReference({ workspaceRoot: input.workspaceRoot, target: input.target, headed: input.headed, fullPage: input.fullPage });
|
|
13
|
+
}
|
|
14
|
+
if (input.mode === 'mockup-implementation') {
|
|
15
|
+
if (!input.url)
|
|
16
|
+
throw new Error('mockup-implementation requires an implementation URL.');
|
|
17
|
+
return compareReferenceImplementation({
|
|
18
|
+
workspaceRoot: input.workspaceRoot,
|
|
19
|
+
target: input.target,
|
|
20
|
+
url: input.url,
|
|
21
|
+
headed: input.headed,
|
|
22
|
+
storageState: input.storageState,
|
|
23
|
+
fullPage: input.fullPage,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
return compareImageImplementation(input);
|
|
27
|
+
}
|
|
28
|
+
async function compareImageImplementation(input) {
|
|
29
|
+
if (!input.url)
|
|
30
|
+
throw new Error('image-implementation requires an implementation URL.');
|
|
31
|
+
const workspace = resolveWorkspace(input.workspaceRoot);
|
|
32
|
+
const target = await resolveTargetWithSource(input.workspaceRoot, input.target);
|
|
33
|
+
const logger = await createRunLogger(workspace, { command: 'loop compare', target: input.target, mode: 'image-implementation' });
|
|
34
|
+
const captureDir = path.join(target.capturesDir, 'image-implementation');
|
|
35
|
+
const implementationPath = path.join(captureDir, 'implementation.png');
|
|
36
|
+
const sideBySidePath = path.join(captureDir, 'side-by-side.png');
|
|
37
|
+
const reportPath = path.join(target.reportsDir, 'image-implementation.md');
|
|
38
|
+
try {
|
|
39
|
+
await logger.event({ type: 'command.started' });
|
|
40
|
+
await mkdir(captureDir, { recursive: true });
|
|
41
|
+
const contract = await loadRegionContract(target.regionsPath);
|
|
42
|
+
await capturePage({
|
|
43
|
+
url: input.url,
|
|
44
|
+
outputPath: implementationPath,
|
|
45
|
+
contract,
|
|
46
|
+
side: 'app',
|
|
47
|
+
headed: input.headed,
|
|
48
|
+
storageState: input.storageState,
|
|
49
|
+
fullPage: input.fullPage,
|
|
50
|
+
});
|
|
51
|
+
await createSideBySideImage({ leftPath: target.sourceImagePath, rightPath: implementationPath, outputPath: sideBySidePath });
|
|
52
|
+
const agentComparison = await writeAgentComparisonPack({
|
|
53
|
+
workspaceRoot: input.workspaceRoot,
|
|
54
|
+
captureDir,
|
|
55
|
+
mode: 'image-implementation',
|
|
56
|
+
profile: 'ideal-to-implementation',
|
|
57
|
+
imageInputs: {
|
|
58
|
+
expectedImagePath: target.sourceImagePath,
|
|
59
|
+
actualImagePath: implementationPath,
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
await writeFile(reportPath, [
|
|
63
|
+
'# Image To Implementation Comparison',
|
|
64
|
+
'',
|
|
65
|
+
`Source image: ${target.sourceImagePath}`,
|
|
66
|
+
`Implementation: ${implementationPath}`,
|
|
67
|
+
`Side-by-side: ${sideBySidePath}`,
|
|
68
|
+
`Agent comparison: ${agentComparison.responsePath}`,
|
|
69
|
+
'',
|
|
70
|
+
].join('\n'));
|
|
71
|
+
await logger.artifact(implementationPath, 'screenshot');
|
|
72
|
+
await logger.artifact(sideBySidePath, 'side-by-side');
|
|
73
|
+
await logger.artifact(agentComparison.promptPath, 'agent-comparison-prompt');
|
|
74
|
+
await logger.artifact(agentComparison.schemaPath, 'agent-comparison-schema');
|
|
75
|
+
await logger.artifact(reportPath, 'report');
|
|
76
|
+
await logger.complete('ok');
|
|
77
|
+
return { sideBySidePath, reportPath, agentComparison };
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
await logger.event({ type: 'command.failed', status: 'failed', message: error instanceof Error ? error.message : String(error) });
|
|
81
|
+
await logger.complete('failed');
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=loop-comparison-adapters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loop-comparison-adapters.js","sourceRoot":"","sources":["../../src/commands/loop-comparison-adapters.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type LedgerMode } from '../schemas/ledger.js';
|
|
2
|
+
type LedgerEnv = Partial<Pick<NodeJS.ProcessEnv, 'LIMNER_LEDGER_HOME'>>;
|
|
3
|
+
export type StartLoopInput = {
|
|
4
|
+
ledgerEnv?: LedgerEnv;
|
|
5
|
+
workspaceRoot: string;
|
|
6
|
+
target: string;
|
|
7
|
+
mode: LedgerMode;
|
|
8
|
+
name?: string;
|
|
9
|
+
maxIterations?: number;
|
|
10
|
+
url?: string;
|
|
11
|
+
storageState?: string;
|
|
12
|
+
fullPage?: boolean;
|
|
13
|
+
};
|
|
14
|
+
export type TrajectorySelector = {
|
|
15
|
+
ledgerEnv?: LedgerEnv;
|
|
16
|
+
trajectoryId?: string;
|
|
17
|
+
target?: string;
|
|
18
|
+
mode?: LedgerMode;
|
|
19
|
+
feedback?: string;
|
|
20
|
+
};
|
|
21
|
+
export type CompareLoopInput = TrajectorySelector & {
|
|
22
|
+
workspaceRoot: string;
|
|
23
|
+
url?: string;
|
|
24
|
+
storageState?: string;
|
|
25
|
+
headed?: boolean;
|
|
26
|
+
fullPage?: boolean;
|
|
27
|
+
};
|
|
28
|
+
export declare function startLoop(input: StartLoopInput): {
|
|
29
|
+
trajectoryId: string;
|
|
30
|
+
iterationId: string | null;
|
|
31
|
+
};
|
|
32
|
+
export declare function getLoopStatus(input: TrajectorySelector): {
|
|
33
|
+
trajectory: import("../core/ledger-store.js").TrajectorySummary;
|
|
34
|
+
lines: string[];
|
|
35
|
+
};
|
|
36
|
+
export declare function advanceLoop(input: TrajectorySelector): {
|
|
37
|
+
iterationId: string;
|
|
38
|
+
};
|
|
39
|
+
export declare function closeLoop(input: TrajectorySelector): import("../core/ledger-store.js").TrajectorySummary;
|
|
40
|
+
export declare function compareLoop(input: CompareLoopInput): Promise<import("./loop-comparison-adapters.js").LoopCompareResult>;
|
|
41
|
+
export {};
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { ledgerModeSchema } from '../schemas/ledger.js';
|
|
2
|
+
import { openLedgerDatabase } from '../core/ledger-db.js';
|
|
3
|
+
import { defaultLoopInstructions } from '../core/loop-instructions.js';
|
|
4
|
+
import { resolveLedgerPaths } from '../core/ledger-paths.js';
|
|
5
|
+
import { createLedgerStore } from '../core/ledger-store.js';
|
|
6
|
+
import { runLoopComparison } from './loop-comparison-adapters.js';
|
|
7
|
+
export function startLoop(input) {
|
|
8
|
+
return withStore(input.ledgerEnv, (store) => {
|
|
9
|
+
const mode = ledgerModeSchema.parse(input.mode);
|
|
10
|
+
const trajectory = store.startTrajectory({
|
|
11
|
+
mode,
|
|
12
|
+
target: input.target,
|
|
13
|
+
name: input.name ?? input.target,
|
|
14
|
+
projectRoot: input.workspaceRoot,
|
|
15
|
+
workspaceRoot: input.workspaceRoot,
|
|
16
|
+
maxIterations: input.maxIterations,
|
|
17
|
+
context: {
|
|
18
|
+
url: input.url,
|
|
19
|
+
storageState: input.storageState,
|
|
20
|
+
fullPage: input.fullPage,
|
|
21
|
+
},
|
|
22
|
+
instructions: defaultLoopInstructions(mode),
|
|
23
|
+
});
|
|
24
|
+
return { trajectoryId: trajectory.trajectoryId, iterationId: trajectory.activeIterationId };
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
export function getLoopStatus(input) {
|
|
28
|
+
return withStore(input.ledgerEnv, (store) => {
|
|
29
|
+
const trajectory = store.resolveTrajectory(selector(input));
|
|
30
|
+
if (input.feedback) {
|
|
31
|
+
store.appendEvent({
|
|
32
|
+
trajectoryId: trajectory.trajectoryId,
|
|
33
|
+
iterationId: trajectory.activeIterationId ?? undefined,
|
|
34
|
+
eventType: 'loop.status.viewed',
|
|
35
|
+
actor: 'agent',
|
|
36
|
+
command: 'loop status',
|
|
37
|
+
resultStatus: 'ok',
|
|
38
|
+
agentFeedback: input.feedback,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
store.appendEvent({
|
|
43
|
+
trajectoryId: trajectory.trajectoryId,
|
|
44
|
+
iterationId: trajectory.activeIterationId ?? undefined,
|
|
45
|
+
eventType: 'loop.status.viewed',
|
|
46
|
+
actor: 'cli',
|
|
47
|
+
command: 'loop status',
|
|
48
|
+
resultStatus: 'ok',
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
const exported = store.exportTrajectoryJson(trajectory.trajectoryId);
|
|
52
|
+
return {
|
|
53
|
+
trajectory,
|
|
54
|
+
lines: [
|
|
55
|
+
`Trajectory: ${trajectory.trajectoryId}`,
|
|
56
|
+
`Name: ${trajectory.humanId}`,
|
|
57
|
+
`Mode: ${trajectory.mode}`,
|
|
58
|
+
`Target: ${trajectory.target}`,
|
|
59
|
+
`Status: ${trajectory.status}`,
|
|
60
|
+
`Active iteration: ${trajectory.activeIterationId ?? 'none'}`,
|
|
61
|
+
`Iterations: ${exported.iterations.length}`,
|
|
62
|
+
`Max iterations: ${trajectory.maxIterations ?? 'none'}`,
|
|
63
|
+
],
|
|
64
|
+
};
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
export function advanceLoop(input) {
|
|
68
|
+
return withStore(input.ledgerEnv, (store) => {
|
|
69
|
+
const trajectory = store.resolveTrajectory(selector(input));
|
|
70
|
+
return store.advanceIteration(trajectory.trajectoryId);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
export function closeLoop(input) {
|
|
74
|
+
return withStore(input.ledgerEnv, (store) => {
|
|
75
|
+
const trajectory = store.resolveTrajectory(selector(input));
|
|
76
|
+
return store.closeTrajectory(trajectory.trajectoryId);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
export async function compareLoop(input) {
|
|
80
|
+
return withStoreAsync(input.ledgerEnv, async (store) => {
|
|
81
|
+
const trajectory = store.resolveTrajectory(selector(input));
|
|
82
|
+
store.appendEvent({
|
|
83
|
+
trajectoryId: trajectory.trajectoryId,
|
|
84
|
+
iterationId: trajectory.activeIterationId ?? undefined,
|
|
85
|
+
eventType: 'loop.compare.started',
|
|
86
|
+
actor: 'cli',
|
|
87
|
+
command: 'loop compare',
|
|
88
|
+
resultStatus: 'running',
|
|
89
|
+
});
|
|
90
|
+
try {
|
|
91
|
+
const result = await runLoopComparison({
|
|
92
|
+
workspaceRoot: input.workspaceRoot,
|
|
93
|
+
target: trajectory.target,
|
|
94
|
+
mode: trajectory.mode,
|
|
95
|
+
url: input.url,
|
|
96
|
+
storageState: input.storageState,
|
|
97
|
+
headed: input.headed,
|
|
98
|
+
fullPage: input.fullPage,
|
|
99
|
+
});
|
|
100
|
+
const eventType = result.agentComparison?.status === 'validated' ? 'loop.compare.validated' : 'loop.compare.awaiting_agent';
|
|
101
|
+
store.appendEvent({
|
|
102
|
+
trajectoryId: trajectory.trajectoryId,
|
|
103
|
+
iterationId: trajectory.activeIterationId ?? undefined,
|
|
104
|
+
eventType,
|
|
105
|
+
actor: 'cli',
|
|
106
|
+
command: 'loop compare',
|
|
107
|
+
resultStatus: result.agentComparison?.status ?? 'ok',
|
|
108
|
+
artifactRefs: [result.sideBySidePath, result.reportPath, result.agentComparison?.responsePath].filter(Boolean),
|
|
109
|
+
});
|
|
110
|
+
return result;
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
store.appendEvent({
|
|
114
|
+
trajectoryId: trajectory.trajectoryId,
|
|
115
|
+
iterationId: trajectory.activeIterationId ?? undefined,
|
|
116
|
+
eventType: 'loop.compare.failed',
|
|
117
|
+
actor: 'cli',
|
|
118
|
+
command: 'loop compare',
|
|
119
|
+
resultStatus: 'failed',
|
|
120
|
+
notes: error instanceof Error ? error.message : String(error),
|
|
121
|
+
});
|
|
122
|
+
throw error;
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
function withStore(env, callback) {
|
|
127
|
+
const db = openLedgerDatabase({ databasePath: resolveLedgerPaths(env).databasePath });
|
|
128
|
+
try {
|
|
129
|
+
return callback(createLedgerStore(db));
|
|
130
|
+
}
|
|
131
|
+
finally {
|
|
132
|
+
db.close();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
async function withStoreAsync(env, callback) {
|
|
136
|
+
const db = openLedgerDatabase({ databasePath: resolveLedgerPaths(env).databasePath });
|
|
137
|
+
try {
|
|
138
|
+
return await callback(createLedgerStore(db));
|
|
139
|
+
}
|
|
140
|
+
finally {
|
|
141
|
+
db.close();
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
function selector(input) {
|
|
145
|
+
return {
|
|
146
|
+
trajectoryId: input.trajectoryId,
|
|
147
|
+
target: input.target,
|
|
148
|
+
mode: input.mode,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=loop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loop.js","sourceRoot":"","sources":["../../src/commands/loop.ts"],"names":[],"mappings":"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"}
|