looply-cli 0.5.11 → 0.5.13
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/dist/.src-hash +1 -1
- package/dist/bin.d.ts.map +1 -1
- package/dist/bin.js +16 -0
- package/dist/bin.js.map +1 -1
- package/dist/branch-delivery-wiring.d.ts +7 -2
- package/dist/branch-delivery-wiring.d.ts.map +1 -1
- package/dist/branch-delivery-wiring.js +79 -12
- package/dist/branch-delivery-wiring.js.map +1 -1
- package/dist/branch-delivery.d.ts +23 -3
- package/dist/branch-delivery.d.ts.map +1 -1
- package/dist/branch-delivery.js +40 -2
- package/dist/branch-delivery.js.map +1 -1
- package/dist/coordinator-state.d.ts.map +1 -1
- package/dist/coordinator-state.js +2 -0
- package/dist/coordinator-state.js.map +1 -1
- package/dist/daemon-cmd.d.ts.map +1 -1
- package/dist/daemon-cmd.js +23 -1
- package/dist/daemon-cmd.js.map +1 -1
- package/dist/delivery-rules.d.ts +11 -0
- package/dist/delivery-rules.d.ts.map +1 -1
- package/dist/delivery-rules.js +34 -1
- package/dist/delivery-rules.js.map +1 -1
- package/dist/github-api.d.ts +2 -0
- package/dist/github-api.d.ts.map +1 -1
- package/dist/github-api.js +3 -0
- package/dist/github-api.js.map +1 -1
- package/dist/goal-gap.d.ts +9 -0
- package/dist/goal-gap.d.ts.map +1 -1
- package/dist/goal-gap.js +9 -0
- package/dist/goal-gap.js.map +1 -1
- package/dist/machine-run-slots.d.ts +10 -2
- package/dist/machine-run-slots.d.ts.map +1 -1
- package/dist/machine-run-slots.js +15 -4
- package/dist/machine-run-slots.js.map +1 -1
- package/dist/maintenance-cmd.d.ts +44 -0
- package/dist/maintenance-cmd.d.ts.map +1 -0
- package/dist/maintenance-cmd.js +132 -0
- package/dist/maintenance-cmd.js.map +1 -0
- package/dist/maintenance-facts.d.ts +52 -0
- package/dist/maintenance-facts.d.ts.map +1 -0
- package/dist/maintenance-facts.js +256 -0
- package/dist/maintenance-facts.js.map +1 -0
- package/dist/maintenance-tick.d.ts +51 -0
- package/dist/maintenance-tick.d.ts.map +1 -0
- package/dist/maintenance-tick.js +156 -0
- package/dist/maintenance-tick.js.map +1 -0
- package/dist/mcp-main.js +3 -0
- package/dist/mcp-main.js.map +1 -1
- package/dist/mcp-server.d.ts +5 -0
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +14 -1
- package/dist/mcp-server.js.map +1 -1
- package/dist/model-transport.d.ts.map +1 -1
- package/dist/model-transport.js +4 -0
- package/dist/model-transport.js.map +1 -1
- package/dist/run-cmd.d.ts.map +1 -1
- package/dist/run-cmd.js +18 -1
- package/dist/run-cmd.js.map +1 -1
- package/dist/run-launcher.d.ts +3 -0
- package/dist/run-launcher.d.ts.map +1 -1
- package/dist/run-launcher.js +3 -2
- package/dist/run-launcher.js.map +1 -1
- package/dist/screenshot-tool.d.ts +45 -0
- package/dist/screenshot-tool.d.ts.map +1 -0
- package/dist/screenshot-tool.js +49 -0
- package/dist/screenshot-tool.js.map +1 -0
- package/dist/server-client.d.ts +39 -0
- package/dist/server-client.d.ts.map +1 -1
- package/dist/server-client.js +21 -0
- package/dist/server-client.js.map +1 -1
- package/dist/visual-proof-browser.d.ts +184 -0
- package/dist/visual-proof-browser.d.ts.map +1 -0
- package/dist/visual-proof-browser.js +267 -0
- package/dist/visual-proof-browser.js.map +1 -0
- package/dist/visual-proof-cmd.d.ts +24 -0
- package/dist/visual-proof-cmd.d.ts.map +1 -0
- package/dist/visual-proof-cmd.js +144 -0
- package/dist/visual-proof-cmd.js.map +1 -0
- package/dist/visual-proof-config.d.ts +151 -0
- package/dist/visual-proof-config.d.ts.map +1 -0
- package/dist/visual-proof-config.js +381 -0
- package/dist/visual-proof-config.js.map +1 -0
- package/dist/visual-proof-publish.d.ts +77 -0
- package/dist/visual-proof-publish.d.ts.map +1 -0
- package/dist/visual-proof-publish.js +211 -0
- package/dist/visual-proof-publish.js.map +1 -0
- package/dist/visual-proof-run.d.ts +73 -0
- package/dist/visual-proof-run.d.ts.map +1 -0
- package/dist/visual-proof-run.js +153 -0
- package/dist/visual-proof-run.js.map +1 -0
- package/dist/visual-proof-scope.d.ts +41 -0
- package/dist/visual-proof-scope.d.ts.map +1 -0
- package/dist/visual-proof-scope.js +205 -0
- package/dist/visual-proof-scope.js.map +1 -0
- package/dist/visual-proof-serve.d.ts +11 -0
- package/dist/visual-proof-serve.d.ts.map +1 -0
- package/dist/visual-proof-serve.js +100 -0
- package/dist/visual-proof-serve.js.map +1 -0
- package/dist/visual-proof-store.d.ts +76 -0
- package/dist/visual-proof-store.d.ts.map +1 -0
- package/dist/visual-proof-store.js +117 -0
- package/dist/visual-proof-store.js.map +1 -0
- package/dist/visual-proof.d.ts +87 -0
- package/dist/visual-proof.d.ts.map +1 -0
- package/dist/visual-proof.js +343 -0
- package/dist/visual-proof.js.map +1 -0
- package/package.json +5 -2
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PUBLISHED = void 0;
|
|
4
|
+
exports.sheetsToSend = sheetsToSend;
|
|
5
|
+
exports.proofComment = proofComment;
|
|
6
|
+
exports.publishVisualProof = publishVisualProof;
|
|
7
|
+
exports.nodeGitEnv = nodeGitEnv;
|
|
8
|
+
const node_child_process_1 = require("node:child_process");
|
|
9
|
+
const node_fs_1 = require("node:fs");
|
|
10
|
+
const node_path_1 = require("node:path");
|
|
11
|
+
const core_1 = require("@looply/core");
|
|
12
|
+
const delivery_rules_1 = require("./delivery-rules");
|
|
13
|
+
const trusted_git_1 = require("./trusted-git");
|
|
14
|
+
/**
|
|
15
|
+
* WHERE A PERSON SEES THE SCREENSHOTS: THE TICKET AND THE PULL REQUEST.
|
|
16
|
+
*
|
|
17
|
+
* 1. the contact sheets are uploaded to the goal on the Looply server, where
|
|
18
|
+
* AutoRyn lists them from the goal's evidence and attaches them to the ticket;
|
|
19
|
+
* 2. they are committed — images only, never code — to their own branch
|
|
20
|
+
* `looply-proof/<goal>/<head sha>` on origin, built with git's plumbing so the
|
|
21
|
+
* checkout's files, index and HEAD are never touched, and pushed under
|
|
22
|
+
* `unsafeProofPushArgv` (origin only, that branch shape only, never forced);
|
|
23
|
+
* 3. one comment on the pull request shows them, linked from that branch, so
|
|
24
|
+
* they are visible exactly to whoever can see the repository.
|
|
25
|
+
*
|
|
26
|
+
* Each step is recorded in the capture's `published.json` and is not repeated.
|
|
27
|
+
* Nothing here throws: a step that cannot happen says why, and delivery carries on.
|
|
28
|
+
*/
|
|
29
|
+
exports.PUBLISHED = 'published.json';
|
|
30
|
+
function readRecord(dir) {
|
|
31
|
+
try {
|
|
32
|
+
return JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(dir, exports.PUBLISHED), 'utf8'));
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return {};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function writeRecord(dir, r) {
|
|
39
|
+
(0, node_fs_1.writeFileSync)((0, node_path_1.join)(dir, exports.PUBLISHED), `${JSON.stringify(r, null, 2)}\n`, 'utf8');
|
|
40
|
+
}
|
|
41
|
+
/** The sheets that fit the upload rule, largest set first in the manifest's order. */
|
|
42
|
+
function sheetsToSend(capture) {
|
|
43
|
+
const out = [];
|
|
44
|
+
let total = 0;
|
|
45
|
+
for (const s of capture.manifest.sheets) {
|
|
46
|
+
const file = (0, node_path_1.join)(capture.dir, s.file);
|
|
47
|
+
if (!(0, node_fs_1.existsSync)(file))
|
|
48
|
+
continue;
|
|
49
|
+
const bytes = (0, node_fs_1.statSync)(file).size;
|
|
50
|
+
if (bytes > core_1.MAX_PROOF_IMAGE_BYTES || total + bytes > core_1.MAX_PROOF_TOTAL_BYTES || out.length >= core_1.MAX_PROOF_IMAGES)
|
|
51
|
+
continue;
|
|
52
|
+
total += bytes;
|
|
53
|
+
out.push({ name: s.file.split('/').pop(), label: s.label, file, bytes });
|
|
54
|
+
}
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
/** The pull request comment: every sheet, inline, from the screenshots branch. */
|
|
58
|
+
function proofComment(input) {
|
|
59
|
+
const m = input.manifest;
|
|
60
|
+
const rtl = m.shots.some((s) => s.dir === 'rtl');
|
|
61
|
+
const lines = [
|
|
62
|
+
'### What this change looks like',
|
|
63
|
+
'',
|
|
64
|
+
`Before (\`${m.baseSha.slice(0, 8)}\`) and after (\`${m.headSha.slice(0, 8)}\`): light and dark${rtl ? ', right-to-left' : ''}, at every width. Built and captured by Looply in its sandbox, offline, signed in with the project's own test data.`,
|
|
65
|
+
'',
|
|
66
|
+
];
|
|
67
|
+
for (const a of m.apps) {
|
|
68
|
+
lines.push(`**${a.name}**: ${a.routes.map((r) => `\`/${r.path}\``).join(', ')}. Why these screens: ${a.why.join('; ')}.`, '');
|
|
69
|
+
}
|
|
70
|
+
for (const img of input.images)
|
|
71
|
+
lines.push(`#### ${img.label}`, '', ``, '');
|
|
72
|
+
if (m.notes.length > 0)
|
|
73
|
+
lines.push('**Notes**', '', ...m.notes.map((n) => `- ${n}`), '');
|
|
74
|
+
lines.push(`<sub>The images live on the branch \`${input.branch}\`, apart from the code. Nothing in it is merged.</sub>`);
|
|
75
|
+
return lines.join('\n');
|
|
76
|
+
}
|
|
77
|
+
async function publishVisualProof(input, deps) {
|
|
78
|
+
const notes = [];
|
|
79
|
+
const rec = readRecord(input.capture.dir);
|
|
80
|
+
const sheets = sheetsToSend(input.capture);
|
|
81
|
+
if (sheets.length === 0)
|
|
82
|
+
return { uploaded: false, branch: null, commented: false, notes: ['there are no before/after sheets to show'] };
|
|
83
|
+
const m = input.capture.manifest;
|
|
84
|
+
// 1. the server, for the ticket
|
|
85
|
+
let uploaded = rec.uploadedAt !== undefined;
|
|
86
|
+
if (!uploaded && deps.upload !== null) {
|
|
87
|
+
try {
|
|
88
|
+
await deps.upload(input.goalId, {
|
|
89
|
+
baseSha: m.baseSha,
|
|
90
|
+
headSha: m.headSha,
|
|
91
|
+
notes: m.notes.slice(0, 20).map((n) => n.slice(0, 600)),
|
|
92
|
+
images: sheets.map((s) => ({ name: s.name, label: s.label.slice(0, 200), mime: 'image/jpeg', data: (0, node_fs_1.readFileSync)(s.file).toString('base64') })),
|
|
93
|
+
...(input.pull === null ? {} : { pullRequestUrl: input.pull.url }),
|
|
94
|
+
});
|
|
95
|
+
uploaded = true;
|
|
96
|
+
rec.uploadedAt = new Date(deps.now()).toISOString();
|
|
97
|
+
writeRecord(input.capture.dir, rec);
|
|
98
|
+
deps.log(`visual : ${sheets.length} before/after sheet(s) sent to goal ${input.goalId}`);
|
|
99
|
+
}
|
|
100
|
+
catch (e) {
|
|
101
|
+
notes.push(`the screenshots could not be sent to the server: ${e.message}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// 2 and 3. the pull request
|
|
105
|
+
if (input.pull === null || input.github === null)
|
|
106
|
+
return { uploaded, branch: rec.branch ?? null, commented: false, notes };
|
|
107
|
+
if ((rec.commentedOn ?? []).includes(input.pull.number))
|
|
108
|
+
return { uploaded, branch: rec.branch ?? null, commented: true, notes };
|
|
109
|
+
const branch = (0, delivery_rules_1.proofBranch)(input.goalId, m.headSha);
|
|
110
|
+
if (branch === null)
|
|
111
|
+
return { uploaded, branch: null, commented: false, notes: [...notes, 'the goal id or head cannot name a screenshots branch'] };
|
|
112
|
+
let commit = rec.branch === branch ? (rec.commit ?? null) : null;
|
|
113
|
+
if (commit === null) {
|
|
114
|
+
const made = await commitImages(deps, sheets, `Looply: before/after screenshots for ${input.goalId} at ${m.headSha.slice(0, 12)}`);
|
|
115
|
+
if (!made.ok)
|
|
116
|
+
return { uploaded, branch: null, commented: false, notes: [...notes, made.because] };
|
|
117
|
+
const remote = await deps.git(['-c', 'credential.interactive=never', 'ls-remote', '--heads', delivery_rules_1.DELIVERY_REMOTE, `refs/heads/${branch}`]);
|
|
118
|
+
const existing = remote.code === 0 ? (remote.stdout.trim().split(/\s+/)[0] ?? '') : '';
|
|
119
|
+
if (/^[0-9a-f]{40}$/.test(existing)) {
|
|
120
|
+
// Already there (an earlier delivery of this head): use it as it is, never replace it.
|
|
121
|
+
commit = existing;
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
const argv = (0, delivery_rules_1.proofPushArgv)(branch, made.sha);
|
|
125
|
+
const unsafe = (0, delivery_rules_1.unsafeProofPushArgv)(argv);
|
|
126
|
+
if (unsafe !== null)
|
|
127
|
+
return { uploaded, branch: null, commented: false, notes: [...notes, `refused before git ran: ${unsafe}`] };
|
|
128
|
+
const pushed = await deps.git(['-c', 'credential.interactive=never', ...argv]);
|
|
129
|
+
if (pushed.code !== 0) {
|
|
130
|
+
return { uploaded, branch: null, commented: false, notes: [...notes, `the screenshots branch could not be pushed: ${(0, delivery_rules_1.redactUrl)(`${pushed.stderr}\n${pushed.stdout}`.trim()).slice(0, 300)}`] };
|
|
131
|
+
}
|
|
132
|
+
commit = made.sha;
|
|
133
|
+
deps.log(`visual : pushed ${branch} (${made.sha.slice(0, 12)}) with ${sheets.length} image(s)`);
|
|
134
|
+
}
|
|
135
|
+
rec.branch = branch;
|
|
136
|
+
rec.commit = commit;
|
|
137
|
+
writeRecord(input.capture.dir, rec);
|
|
138
|
+
}
|
|
139
|
+
const { owner, repo, api } = input.github;
|
|
140
|
+
if (api.commentOnPull === undefined)
|
|
141
|
+
return { uploaded, branch, commented: false, notes: [...notes, 'this GitHub client cannot comment on a pull request'] };
|
|
142
|
+
const images = sheets.map((s) => ({ label: s.label, url: `https://github.com/${owner}/${repo}/blob/${commit}/${encodeURIComponent(s.name)}?raw=true` }));
|
|
143
|
+
try {
|
|
144
|
+
await api.commentOnPull(input.pull.number, proofComment({ manifest: m, images, branch }));
|
|
145
|
+
rec.commentedOn = [...(rec.commentedOn ?? []), input.pull.number];
|
|
146
|
+
writeRecord(input.capture.dir, rec);
|
|
147
|
+
deps.log(`visual : screenshots shown on ${input.pull.url}`);
|
|
148
|
+
return { uploaded, branch, commented: true, notes };
|
|
149
|
+
}
|
|
150
|
+
catch (e) {
|
|
151
|
+
return { uploaded, branch, commented: false, notes: [...notes, `GitHub refused the screenshots comment: ${e.message}`] };
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* A commit holding only the given images, made without touching the checkout:
|
|
156
|
+
* `hash-object -w` each file, add it to a PRIVATE index file, `write-tree`, `commit-tree`.
|
|
157
|
+
*/
|
|
158
|
+
async function commitImages(deps, files, message) {
|
|
159
|
+
const index = (0, node_path_1.join)(files[0].file, '..', `.looply-proof-index-${process.pid}`);
|
|
160
|
+
const env = {
|
|
161
|
+
GIT_INDEX_FILE: index,
|
|
162
|
+
GIT_AUTHOR_NAME: 'Looply',
|
|
163
|
+
GIT_AUTHOR_EMAIL: 'looply@users.noreply.github.com',
|
|
164
|
+
GIT_COMMITTER_NAME: 'Looply',
|
|
165
|
+
GIT_COMMITTER_EMAIL: 'looply@users.noreply.github.com',
|
|
166
|
+
};
|
|
167
|
+
try {
|
|
168
|
+
for (const f of files) {
|
|
169
|
+
const blob = await deps.gitEnv(['hash-object', '-w', '--no-filters', '--', f.file], env);
|
|
170
|
+
if (blob.code !== 0)
|
|
171
|
+
return { ok: false, because: `git could not store ${f.name}: ${blob.stderr.trim().slice(0, 200)}` };
|
|
172
|
+
const added = await deps.gitEnv(['update-index', '--add', '--cacheinfo', `100644,${blob.stdout.trim()},${f.name}`], env);
|
|
173
|
+
if (added.code !== 0)
|
|
174
|
+
return { ok: false, because: `git could not stage ${f.name}: ${added.stderr.trim().slice(0, 200)}` };
|
|
175
|
+
}
|
|
176
|
+
const tree = await deps.gitEnv(['write-tree'], env);
|
|
177
|
+
if (tree.code !== 0)
|
|
178
|
+
return { ok: false, because: `git write-tree failed: ${tree.stderr.trim().slice(0, 200)}` };
|
|
179
|
+
const commit = await deps.gitEnv(['commit-tree', tree.stdout.trim(), '-m', message], env);
|
|
180
|
+
if (commit.code !== 0 || !/^[0-9a-f]{40}$/.test(commit.stdout.trim()))
|
|
181
|
+
return { ok: false, because: `git commit-tree failed: ${commit.stderr.trim().slice(0, 200)}` };
|
|
182
|
+
return { ok: true, sha: commit.stdout.trim() };
|
|
183
|
+
}
|
|
184
|
+
finally {
|
|
185
|
+
(0, node_fs_1.rmSync)(index, { force: true });
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/** git in `cwd` with extra environment, hidden, never prompting — never by bare name. */
|
|
189
|
+
function nodeGitEnv(cwd) {
|
|
190
|
+
return (args, env) => new Promise((resolve) => {
|
|
191
|
+
let child;
|
|
192
|
+
try {
|
|
193
|
+
// The same git, flags and pinned environment as every other git call (trusted-git.ts), plus the extras.
|
|
194
|
+
const bin = (0, trusted_git_1.gitBinary)();
|
|
195
|
+
if (bin === null)
|
|
196
|
+
throw new Error('git was not found on PATH');
|
|
197
|
+
child = (0, node_child_process_1.spawn)(bin, [...(0, trusted_git_1.trustedGitArgs)(), ...args], { cwd, env: { ...(0, trusted_git_1.trustedGitEnv)(process.env, cwd), ...env, GIT_TERMINAL_PROMPT: '0' }, stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true });
|
|
198
|
+
}
|
|
199
|
+
catch (e) {
|
|
200
|
+
resolve({ code: -1, stdout: '', stderr: e.message });
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
let stdout = '';
|
|
204
|
+
let stderr = '';
|
|
205
|
+
child.stdout?.on('data', (d) => (stdout += d.toString('utf8')));
|
|
206
|
+
child.stderr?.on('data', (d) => (stderr += d.toString('utf8')));
|
|
207
|
+
child.on('error', (e) => resolve({ code: -1, stdout, stderr: e.message }));
|
|
208
|
+
child.on('close', (code) => resolve({ code: code ?? -1, stdout, stderr }));
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=visual-proof-publish.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"visual-proof-publish.js","sourceRoot":"","sources":["../src/visual-proof-publish.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { type ProofDeps } from './visual-proof';
|
|
2
|
+
import { type ProofManifest } from './visual-proof-store';
|
|
3
|
+
/**
|
|
4
|
+
* VISUAL PROOF IN A GOAL'S LIFE: once before it is judged, and again at delivery
|
|
5
|
+
* only if nothing was captured for the delivered commit.
|
|
6
|
+
*
|
|
7
|
+
* `ensureCapture` reuses a capture of the same goal at the same head; a capture
|
|
8
|
+
* that cannot be made logs why and returns null — it never fails anything.
|
|
9
|
+
* `writeJudgePointer` lists the images the judge may look at in the project's
|
|
10
|
+
* PROTECTED state folder (the model's container cannot write there), and the
|
|
11
|
+
* judge's `view_screenshot` tool serves only what that list names.
|
|
12
|
+
*/
|
|
13
|
+
export declare const JUDGE_POINTER = "visual-proof.json";
|
|
14
|
+
export interface Capture {
|
|
15
|
+
readonly dir: string;
|
|
16
|
+
readonly manifest: ProofManifest;
|
|
17
|
+
}
|
|
18
|
+
export interface EnsureCaptureInput {
|
|
19
|
+
/** Where git runs: the run's checkout, or the daemon's project folder. */
|
|
20
|
+
readonly cwd: string;
|
|
21
|
+
readonly projectName: string;
|
|
22
|
+
readonly goalId: string;
|
|
23
|
+
readonly goalText: string;
|
|
24
|
+
/** The commit to show; HEAD when absent. */
|
|
25
|
+
readonly headSha?: string;
|
|
26
|
+
readonly configuredBase?: string;
|
|
27
|
+
log(line: string): void;
|
|
28
|
+
/** Tests. */
|
|
29
|
+
readonly deps?: Partial<ProofDeps> & {
|
|
30
|
+
storeBase?: string;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export declare function ensureCapture(input: EnsureCaptureInput): Promise<Capture | null>;
|
|
34
|
+
export interface JudgePointer {
|
|
35
|
+
readonly goalId: string;
|
|
36
|
+
readonly headSha: string;
|
|
37
|
+
readonly images: ReadonlyArray<{
|
|
38
|
+
readonly name: string;
|
|
39
|
+
readonly label: string;
|
|
40
|
+
readonly file: string;
|
|
41
|
+
}>;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The images the judge may look at: every before/after sheet, then each AFTER frame.
|
|
45
|
+
* Names are plain and unique; files are absolute.
|
|
46
|
+
*/
|
|
47
|
+
export declare function judgeImages(capture: Capture): JudgePointer['images'];
|
|
48
|
+
export declare function writeJudgePointer(stateDir: string, goalId: string, capture: Capture): JudgePointer;
|
|
49
|
+
export declare function readJudgePointer(stateDir: string): JudgePointer | null;
|
|
50
|
+
/** One image by the name the pointer lists, as MCP image content; a refusal in words otherwise. */
|
|
51
|
+
export declare function judgeImage(stateDir: string, name: unknown): {
|
|
52
|
+
ok: true;
|
|
53
|
+
mime: 'image/jpeg' | 'image/png';
|
|
54
|
+
data: string;
|
|
55
|
+
} | {
|
|
56
|
+
ok: false;
|
|
57
|
+
because: string;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Before a goal is judged: capture (or reuse) the screenshots of this checkout's HEAD and list
|
|
61
|
+
* them for the judge in the checkout's protected state folder. Any stale list is removed first,
|
|
62
|
+
* so a judge never sees another commit's pictures. Never throws; [] when there are none.
|
|
63
|
+
*/
|
|
64
|
+
export declare function screenshotsForJudge(input: Omit<EnsureCaptureInput, 'headSha'>): Promise<Array<{
|
|
65
|
+
name: string;
|
|
66
|
+
label: string;
|
|
67
|
+
}>>;
|
|
68
|
+
/** For the judge's prompt: the names it can ask for, one line each. */
|
|
69
|
+
export declare function judgeScreenshotList(pointer: JudgePointer | null): Array<{
|
|
70
|
+
name: string;
|
|
71
|
+
label: string;
|
|
72
|
+
}>;
|
|
73
|
+
//# sourceMappingURL=visual-proof-run.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"visual-proof-run.d.ts","sourceRoot":"","sources":["../src/visual-proof-run.ts"],"names":[],"mappings":"AAKA,OAAO,EAA+B,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAG7E,OAAO,EAAe,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGvE;;;;;;;;;GASG;AAEH,eAAO,MAAM,aAAa,sBAAsB,CAAC;AAEjD,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;CAClC;AAED,MAAM,WAAW,kBAAkB;IACjC,0EAA0E;IAC1E,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,4CAA4C;IAC5C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,aAAa;IACb,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7D;AAED,wBAAsB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAgDtF;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC1G;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY,CAAC,QAAQ,CAAC,CAWpE;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,YAAY,CAQlG;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAOtE;AAED,mGAAmG;AACnG,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,YAAY,GAAG,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAOzJ;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,IAAI,CAAC,kBAAkB,EAAE,SAAS,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAWrI;AAED,uEAAuE;AACvE,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAExG"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.JUDGE_POINTER = void 0;
|
|
4
|
+
exports.ensureCapture = ensureCapture;
|
|
5
|
+
exports.judgeImages = judgeImages;
|
|
6
|
+
exports.writeJudgePointer = writeJudgePointer;
|
|
7
|
+
exports.readJudgePointer = readJudgePointer;
|
|
8
|
+
exports.judgeImage = judgeImage;
|
|
9
|
+
exports.screenshotsForJudge = screenshotsForJudge;
|
|
10
|
+
exports.judgeScreenshotList = judgeScreenshotList;
|
|
11
|
+
const node_fs_1 = require("node:fs");
|
|
12
|
+
const node_path_1 = require("node:path");
|
|
13
|
+
const git_driver_1 = require("./git-driver");
|
|
14
|
+
const run_base_1 = require("./run-base");
|
|
15
|
+
const untrusted_gate_1 = require("./untrusted-gate");
|
|
16
|
+
const visual_proof_1 = require("./visual-proof");
|
|
17
|
+
const visual_proof_cmd_1 = require("./visual-proof-cmd");
|
|
18
|
+
const visual_proof_config_1 = require("./visual-proof-config");
|
|
19
|
+
const visual_proof_store_1 = require("./visual-proof-store");
|
|
20
|
+
const workspace_1 = require("./workspace");
|
|
21
|
+
/**
|
|
22
|
+
* VISUAL PROOF IN A GOAL'S LIFE: once before it is judged, and again at delivery
|
|
23
|
+
* only if nothing was captured for the delivered commit.
|
|
24
|
+
*
|
|
25
|
+
* `ensureCapture` reuses a capture of the same goal at the same head; a capture
|
|
26
|
+
* that cannot be made logs why and returns null — it never fails anything.
|
|
27
|
+
* `writeJudgePointer` lists the images the judge may look at in the project's
|
|
28
|
+
* PROTECTED state folder (the model's container cannot write there), and the
|
|
29
|
+
* judge's `view_screenshot` tool serves only what that list names.
|
|
30
|
+
*/
|
|
31
|
+
exports.JUDGE_POINTER = 'visual-proof.json';
|
|
32
|
+
async function ensureCapture(input) {
|
|
33
|
+
let config;
|
|
34
|
+
try {
|
|
35
|
+
config = (0, visual_proof_config_1.readVisualProofConfig)(input.cwd);
|
|
36
|
+
}
|
|
37
|
+
catch (e) {
|
|
38
|
+
input.log(`visual : ${e.message}`);
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
if (!config.enabled)
|
|
42
|
+
return null;
|
|
43
|
+
const exec = input.deps?.git ?? (0, git_driver_1.nodeGitExec)(input.cwd);
|
|
44
|
+
const storeBase = input.deps?.storeBase ?? (0, workspace_1.workspacesBase)();
|
|
45
|
+
const head = input.headSha ?? (await exec(['rev-parse', 'HEAD'])).stdout.trim();
|
|
46
|
+
if (!/^[0-9a-f]{40}$/.test(head))
|
|
47
|
+
return null;
|
|
48
|
+
const existing = (0, visual_proof_store_1.findCapture)(storeBase, await (0, visual_proof_1.repoKey)(exec, input.cwd), input.goalId, head);
|
|
49
|
+
if (existing !== null)
|
|
50
|
+
return existing;
|
|
51
|
+
const base = (await (0, run_base_1.resolveBaseBranch)(new git_driver_1.GitDriver(exec), input.configuredBase).catch(() => null))?.ref ?? null;
|
|
52
|
+
if (base === null) {
|
|
53
|
+
input.log('visual : no screenshots: the base branch could not be found');
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
// A machine-made checkout carries config.yaml but not the rest of `.looply/` (where a project may keep its
|
|
57
|
+
// sign-in fixtures): those are also looked for in the repository's main folder.
|
|
58
|
+
const common = await exec(['rev-parse', '--path-format=absolute', '--git-common-dir']);
|
|
59
|
+
const mainDir = common.code === 0 && (0, node_path_1.basename)(common.stdout.trim()) === '.git' ? (0, node_path_1.dirname)(common.stdout.trim()) : input.cwd;
|
|
60
|
+
const outcome = await (0, visual_proof_1.captureVisualProof)({
|
|
61
|
+
checkout: input.cwd,
|
|
62
|
+
projectDir: mainDir,
|
|
63
|
+
projectName: input.projectName,
|
|
64
|
+
goalId: input.goalId,
|
|
65
|
+
goalText: input.goalText,
|
|
66
|
+
base,
|
|
67
|
+
head,
|
|
68
|
+
config,
|
|
69
|
+
carry: (0, visual_proof_cmd_1.carryOf)(input.cwd),
|
|
70
|
+
storeBase,
|
|
71
|
+
}, {
|
|
72
|
+
git: exec,
|
|
73
|
+
buildRunner: input.deps?.buildRunner ?? ((tree) => (0, untrusted_gate_1.makeUntrustedGateRunner)(tree)),
|
|
74
|
+
...(input.deps?.engine === undefined ? {} : { engine: input.deps.engine }),
|
|
75
|
+
now: input.deps?.now ?? (() => Date.now()),
|
|
76
|
+
log: input.log,
|
|
77
|
+
});
|
|
78
|
+
if (outcome.kind === 'captured')
|
|
79
|
+
return { dir: outcome.dir, manifest: outcome.manifest };
|
|
80
|
+
input.log(`visual : no screenshots: ${outcome.because}`);
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* The images the judge may look at: every before/after sheet, then each AFTER frame.
|
|
85
|
+
* Names are plain and unique; files are absolute.
|
|
86
|
+
*/
|
|
87
|
+
function judgeImages(capture) {
|
|
88
|
+
const out = [];
|
|
89
|
+
for (const s of capture.manifest.sheets) {
|
|
90
|
+
out.push({ name: `sheet-${(0, node_path_1.basename)(s.file)}`, label: `before/after: ${s.label}`, file: (0, node_path_1.join)(capture.dir, s.file) });
|
|
91
|
+
}
|
|
92
|
+
for (const s of capture.manifest.shots) {
|
|
93
|
+
if (s.side !== 'head' || !s.ok)
|
|
94
|
+
continue;
|
|
95
|
+
const name = `after-${s.app}-${s.routeName || s.route || 'home'}-${s.viewport}-${s.theme}-${s.dir}.jpg`.replace(/[^A-Za-z0-9._-]+/g, '-').toLowerCase();
|
|
96
|
+
out.push({ name, label: `after: ${s.app} /${s.route} · ${s.viewport} · ${s.theme}${s.dir === 'rtl' ? ' · right-to-left' : ''}${s.warning ? ` (${s.warning})` : ''}`, file: (0, node_path_1.join)(capture.dir, s.file) });
|
|
97
|
+
}
|
|
98
|
+
return out;
|
|
99
|
+
}
|
|
100
|
+
function writeJudgePointer(stateDir, goalId, capture) {
|
|
101
|
+
const pointer = { goalId, headSha: capture.manifest.headSha, images: judgeImages(capture) };
|
|
102
|
+
(0, node_fs_1.mkdirSync)(stateDir, { recursive: true });
|
|
103
|
+
const path = (0, node_path_1.join)(stateDir, exports.JUDGE_POINTER);
|
|
104
|
+
const tmp = `${path}.${process.pid}.tmp`;
|
|
105
|
+
(0, node_fs_1.writeFileSync)(tmp, `${JSON.stringify(pointer, null, 2)}\n`, 'utf8');
|
|
106
|
+
(0, node_fs_1.renameSync)(tmp, path);
|
|
107
|
+
return pointer;
|
|
108
|
+
}
|
|
109
|
+
function readJudgePointer(stateDir) {
|
|
110
|
+
try {
|
|
111
|
+
const p = JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(stateDir, exports.JUDGE_POINTER), 'utf8'));
|
|
112
|
+
return Array.isArray(p.images) ? p : null;
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/** One image by the name the pointer lists, as MCP image content; a refusal in words otherwise. */
|
|
119
|
+
function judgeImage(stateDir, name) {
|
|
120
|
+
const pointer = readJudgePointer(stateDir);
|
|
121
|
+
if (pointer === null || pointer.images.length === 0)
|
|
122
|
+
return { ok: false, because: 'there are no screenshots for this work' };
|
|
123
|
+
const img = pointer.images.find((i) => i.name === name);
|
|
124
|
+
if (img === undefined)
|
|
125
|
+
return { ok: false, because: `no screenshot is named ${String(name)}; the names are: ${pointer.images.map((i) => i.name).join(', ')}` };
|
|
126
|
+
if (!(0, node_fs_1.existsSync)(img.file) || (0, node_fs_1.statSync)(img.file).size > 2_000_000)
|
|
127
|
+
return { ok: false, because: `${img.name} is no longer on this machine` };
|
|
128
|
+
return { ok: true, mime: img.file.toLowerCase().endsWith('.png') ? 'image/png' : 'image/jpeg', data: (0, node_fs_1.readFileSync)(img.file).toString('base64') };
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Before a goal is judged: capture (or reuse) the screenshots of this checkout's HEAD and list
|
|
132
|
+
* them for the judge in the checkout's protected state folder. Any stale list is removed first,
|
|
133
|
+
* so a judge never sees another commit's pictures. Never throws; [] when there are none.
|
|
134
|
+
*/
|
|
135
|
+
async function screenshotsForJudge(input) {
|
|
136
|
+
const stateDir = (0, node_path_1.join)(input.cwd, '.looply', 'state');
|
|
137
|
+
try {
|
|
138
|
+
(0, node_fs_1.rmSync)((0, node_path_1.join)(stateDir, exports.JUDGE_POINTER), { force: true });
|
|
139
|
+
const capture = await ensureCapture(input);
|
|
140
|
+
if (capture === null)
|
|
141
|
+
return [];
|
|
142
|
+
return judgeScreenshotList(writeJudgePointer(stateDir, input.goalId, capture));
|
|
143
|
+
}
|
|
144
|
+
catch (e) {
|
|
145
|
+
input.log(`visual : no screenshots: ${e.message}`);
|
|
146
|
+
return [];
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/** For the judge's prompt: the names it can ask for, one line each. */
|
|
150
|
+
function judgeScreenshotList(pointer) {
|
|
151
|
+
return (pointer?.images ?? []).map((i) => ({ name: i.name, label: i.label }));
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=visual-proof-run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"visual-proof-run.js","sourceRoot":"","sources":["../src/visual-proof-run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { ProofApp, ProofRoute, VisualProofConfig } from './visual-proof-config';
|
|
2
|
+
export declare function isUiFile(path: string): boolean;
|
|
3
|
+
export interface AppScope {
|
|
4
|
+
readonly app: ProofApp;
|
|
5
|
+
readonly changed: readonly string[];
|
|
6
|
+
readonly routes: readonly ProofRoute[];
|
|
7
|
+
/** Why each route was chosen, in the order above. */
|
|
8
|
+
readonly why: readonly string[];
|
|
9
|
+
}
|
|
10
|
+
/** The apps a set of changed paths touches with UI files. */
|
|
11
|
+
export declare function touchedApps(cfg: VisualProofConfig, changedPaths: readonly string[]): Array<{
|
|
12
|
+
app: ProofApp;
|
|
13
|
+
changed: string[];
|
|
14
|
+
}>;
|
|
15
|
+
export interface RoutedPage {
|
|
16
|
+
/** Full path relative to the app's mount, nested parents joined (`catalog/items`). */
|
|
17
|
+
readonly path: string;
|
|
18
|
+
readonly component: string;
|
|
19
|
+
/** Repository-relative module path without extension, when the import was found. */
|
|
20
|
+
readonly module: string | null;
|
|
21
|
+
/** A route with child routes: its element (a shell, a layout) shows on every screen under it. */
|
|
22
|
+
readonly layout: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The screens a React Router file declares, best effort. Reads `<Route path=… element={<X`
|
|
26
|
+
* (nested layout routes contribute their path), and resolves `X` through a static
|
|
27
|
+
* `import X from '…'`, `import { X } from '…'`, or `const X = lazy(() => import('…'))`
|
|
28
|
+
* (any wrapper whose argument is `() => import('…')`). Parameterised paths are left out:
|
|
29
|
+
* nobody can screenshot `orders/:id` without an id.
|
|
30
|
+
*/
|
|
31
|
+
export declare function readRouter(source: string, routerPath: string): RoutedPage[];
|
|
32
|
+
/** The screens to capture for one touched app. */
|
|
33
|
+
export declare function pickRoutes(input: {
|
|
34
|
+
app: ProofApp;
|
|
35
|
+
changed: readonly string[];
|
|
36
|
+
goalText: string;
|
|
37
|
+
/** The router file's text, when the app names one and it could be read. */
|
|
38
|
+
routerSource: string | null;
|
|
39
|
+
maxRoutes: number;
|
|
40
|
+
}): AppScope;
|
|
41
|
+
//# sourceMappingURL=visual-proof-scope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"visual-proof-scope.d.ts","sourceRoot":"","sources":["../src/visual-proof-scope.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAwBrF,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9C;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC;IACvC,qDAAqD;IACrD,QAAQ,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,CAAC;CACjC;AAED,6DAA6D;AAC7D,wBAAgB,WAAW,CAAC,GAAG,EAAE,iBAAiB,EAAE,YAAY,EAAE,SAAS,MAAM,EAAE,GAAG,KAAK,CAAC;IAAE,GAAG,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAShI;AAED,MAAM,WAAW,UAAU;IACzB,sFAAsF;IACtF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,oFAAoF;IACpF,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,iGAAiG;IACjG,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,UAAU,EAAE,CA4C3E;AAuDD,kDAAkD;AAClD,wBAAgB,UAAU,CAAC,KAAK,EAAE;IAChC,GAAG,EAAE,QAAQ,CAAC;IACd,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,QAAQ,CA4CX"}
|