orizu 0.5.18 → 0.5.19
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/diff-comments-cli.js +52 -0
- package/dist/index.js +3 -23
- package/dist/prompt-length-wire.js +30 -0
- package/dist/prompt-summary-table.js +37 -0
- package/package.json +1 -1
- package/src/diff-comments-cli.ts +91 -0
- package/src/index.ts +11 -26
- package/src/prompt-length-wire.ts +65 -0
- package/src/prompt-summary-table.ts +57 -0
- package/vendor/skills/orizu-cli/references/cli-reference.md +10 -0
- package/vendor/skills/orizu-cli/references/prompt-control-plane.md +19 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { extractErrorMessage, isJsonErrorResponsePayload, } from './error-response.js';
|
|
2
2
|
import { sanitizeHumanInlineText } from './json-response.js';
|
|
3
|
+
import { formatFiniteLengthCount, } from './prompt-length-wire.js';
|
|
3
4
|
const DETAIL_LEVELS = ['hunk', 'diff', 'full'];
|
|
4
5
|
const CONTEXT_UNAVAILABLE_WITHOUT_REASON = ' Context unavailable (no reason supplied)';
|
|
5
6
|
function isCandidatePair(pair) {
|
|
@@ -47,6 +48,56 @@ function humanLineNumber(ctx, line) {
|
|
|
47
48
|
? '-'
|
|
48
49
|
: sanitizeHumanInlineText(ctx.sanitizeTerminalText, String(line + 1));
|
|
49
50
|
}
|
|
51
|
+
function formatStats(stats) {
|
|
52
|
+
const tokens = formatFiniteLengthCount(stats.tokens);
|
|
53
|
+
return `${tokens === null ? '—' : `~${tokens}`} tokens · ` +
|
|
54
|
+
`${formatFiniteLengthCount(stats.lines) ?? '—'} lines · ` +
|
|
55
|
+
`${formatFiniteLengthCount(stats.chars) ?? '—'} chars · ` +
|
|
56
|
+
`${formatFiniteLengthCount(stats.words) ?? '—'} words`;
|
|
57
|
+
}
|
|
58
|
+
function formatDeltaValue(value, metric, signed = false) {
|
|
59
|
+
const formatted = formatFiniteLengthCount(value, signed);
|
|
60
|
+
if (formatted === null)
|
|
61
|
+
return '—';
|
|
62
|
+
return metric === 'tokens' ? `~${formatted}` : formatted;
|
|
63
|
+
}
|
|
64
|
+
function printLengthMeasurements(ctx, pair) {
|
|
65
|
+
function unavailableSuffix(reason) {
|
|
66
|
+
if (typeof reason !== 'string' || reason.length === 0)
|
|
67
|
+
return '';
|
|
68
|
+
return ` (${sanitizeHumanInlineText(ctx.sanitizeTerminalText, reason)})`;
|
|
69
|
+
}
|
|
70
|
+
if (!pair.lengthStats && !pair.lengthDelta) {
|
|
71
|
+
ctx.printLine(` Length: unavailable${unavailableSuffix(pair.lengthDeltaUnavailableReason ?? pair.degraded?.reason)}`);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (pair.lengthStats) {
|
|
75
|
+
ctx.printLine(pair.lengthStats.from
|
|
76
|
+
? ` From: ${formatStats(pair.lengthStats.from)}`
|
|
77
|
+
: ` From: unavailable${unavailableSuffix(pair.lengthStats.fromUnavailableReason)}`);
|
|
78
|
+
ctx.printLine(pair.lengthStats.to
|
|
79
|
+
? ` To: ${formatStats(pair.lengthStats.to)}`
|
|
80
|
+
: ` To: unavailable${unavailableSuffix(pair.lengthStats.toUnavailableReason)}`);
|
|
81
|
+
}
|
|
82
|
+
if (!pair.lengthDelta) {
|
|
83
|
+
ctx.printLine(` Length delta: unavailable${unavailableSuffix(pair.lengthDeltaUnavailableReason ?? pair.degraded?.reason)}`);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (pair.lengthDelta.splitUnavailableReason) {
|
|
87
|
+
ctx.printLine(` Split unavailable: ${sanitizeHumanInlineText(ctx.sanitizeTerminalText, pair.lengthDelta.splitUnavailableReason)}`);
|
|
88
|
+
}
|
|
89
|
+
for (const [metric, label] of [
|
|
90
|
+
['tokens', 'Tokens'],
|
|
91
|
+
['lines', 'Lines'],
|
|
92
|
+
['chars', 'Chars'],
|
|
93
|
+
['words', 'Words'],
|
|
94
|
+
]) {
|
|
95
|
+
const delta = pair.lengthDelta[metric];
|
|
96
|
+
ctx.printLine(` ${label}: removed ${formatDeltaValue(delta.removed, metric)} · ` +
|
|
97
|
+
`added ${formatDeltaValue(delta.added, metric)} · ` +
|
|
98
|
+
`net ${formatDeltaValue(delta.net, metric, true)}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
50
101
|
function buildParams(ctx) {
|
|
51
102
|
const runId = ctx.getArg('--run');
|
|
52
103
|
const promptId = ctx.getArg('--prompt');
|
|
@@ -106,6 +157,7 @@ function printDiffComments(ctx, payload) {
|
|
|
106
157
|
ctx.printLine(`${hasCandidateIds ? 'Candidates' : 'Versions'} ` +
|
|
107
158
|
`${sanitizeHumanInlineText(ctx.sanitizeTerminalText, from)} → ` +
|
|
108
159
|
`${sanitizeHumanInlineText(ctx.sanitizeTerminalText, to)}`);
|
|
160
|
+
printLengthMeasurements(ctx, pair);
|
|
109
161
|
if (pair.degraded) {
|
|
110
162
|
ctx.printLine(` Context unavailable: ${sanitizeHumanInlineText(ctx.sanitizeTerminalText, pair.degraded.reason)}`);
|
|
111
163
|
}
|
package/dist/index.js
CHANGED
|
@@ -43,6 +43,7 @@ import { runGitCredentialInvocation } from './git-credential.js';
|
|
|
43
43
|
import { pushPromptDraft } from './prompt-draft-push.js';
|
|
44
44
|
import { readMarkdownReportInput } from './markdown-report-input.js';
|
|
45
45
|
import { promptPushErrorMessage, promptReportCommand } from './prompt-report-cli.js';
|
|
46
|
+
import { printPromptSummaryTable } from './prompt-summary-table.js';
|
|
46
47
|
import { assertSnapshotManifestConfined, verifyGepaRunnerDirsFromArgs, verifyRunnerDirRegistered } from './runner-dir-verify.js';
|
|
47
48
|
import { runScorersRegister } from './scorer-draft-push.js';
|
|
48
49
|
import { runZipArtifactPush } from './zip-draft-push.js';
|
|
@@ -246,27 +247,6 @@ export function formatTerminalLink(url) {
|
|
|
246
247
|
function shellQuote(value) {
|
|
247
248
|
return `"${value.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
|
|
248
249
|
}
|
|
249
|
-
function printPromptSummaries(items, emptyMessage) {
|
|
250
|
-
if (items.length === 0) {
|
|
251
|
-
printLine(emptyMessage);
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
const rows = items.map(item => ({
|
|
255
|
-
id: sanitizeTerminalText(item.id),
|
|
256
|
-
name: sanitizeTerminalText(item.name),
|
|
257
|
-
role: sanitizeTerminalText(item.role),
|
|
258
|
-
status: sanitizeTerminalText(item.status || 'active'),
|
|
259
|
-
}));
|
|
260
|
-
const idWidth = Math.max('ID'.length, ...rows.map(row => row.id.length));
|
|
261
|
-
const nameWidth = Math.max('NAME'.length, ...rows.map(row => row.name.length));
|
|
262
|
-
const roleWidth = Math.max('ROLE'.length, ...rows.map(row => row.role.length));
|
|
263
|
-
const statusWidth = Math.max('STATUS'.length, ...rows.map(row => row.status.length));
|
|
264
|
-
printLine(`${'ID'.padEnd(idWidth)} ${'NAME'.padEnd(nameWidth)} ${'ROLE'.padEnd(roleWidth)} ${'STATUS'.padEnd(statusWidth)}`);
|
|
265
|
-
printLine(`${'-'.repeat(idWidth)} ${'-'.repeat(nameWidth)} ${'-'.repeat(roleWidth)} ${'-'.repeat(statusWidth)}`);
|
|
266
|
-
rows.forEach(row => {
|
|
267
|
-
printLine(`${row.id.padEnd(idWidth)} ${row.name.padEnd(nameWidth)} ${row.role.padEnd(roleWidth)} ${row.status.padEnd(statusWidth)}`);
|
|
268
|
-
});
|
|
269
|
-
}
|
|
270
250
|
function readJsonObjectArg(valueArg, label) {
|
|
271
251
|
if (!valueArg) {
|
|
272
252
|
return {};
|
|
@@ -905,7 +885,7 @@ async function listPrompts() {
|
|
|
905
885
|
printJson(data);
|
|
906
886
|
return;
|
|
907
887
|
}
|
|
908
|
-
|
|
888
|
+
printPromptSummaryTable(data.prompts, 'No prompts found.', printLine);
|
|
909
889
|
}
|
|
910
890
|
async function listJudges() {
|
|
911
891
|
const project = getArg('--project') || await resolveProjectSlug(null);
|
|
@@ -923,7 +903,7 @@ async function listJudges() {
|
|
|
923
903
|
printJson(data);
|
|
924
904
|
return;
|
|
925
905
|
}
|
|
926
|
-
|
|
906
|
+
printPromptSummaryTable(data.judges, 'No judges found.', printLine);
|
|
927
907
|
}
|
|
928
908
|
async function listScorers() {
|
|
929
909
|
const project = getArg('--project') || await resolveProjectSlug(null);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export const CLI_LENGTH_STATS_FIELDS = [
|
|
2
|
+
'tokens',
|
|
3
|
+
'lines',
|
|
4
|
+
'chars',
|
|
5
|
+
'words',
|
|
6
|
+
];
|
|
7
|
+
export const CLI_LENGTH_DELTA_SPLIT_UNAVAILABLE_REASONS = [
|
|
8
|
+
'diff_degraded_size_limit',
|
|
9
|
+
'diff_degraded_cell_limit',
|
|
10
|
+
];
|
|
11
|
+
export const CLI_LENGTH_MEASUREMENT_UNAVAILABLE_REASONS = [
|
|
12
|
+
'length_measurement_size_limit',
|
|
13
|
+
'length_measurement_failed',
|
|
14
|
+
'body_resolution_failed',
|
|
15
|
+
'measurement_cap_exceeded',
|
|
16
|
+
'enrichment_failed',
|
|
17
|
+
'bodies_unavailable_event_cap',
|
|
18
|
+
];
|
|
19
|
+
export function formatFiniteLengthCount(value, signed = false) {
|
|
20
|
+
if (typeof value !== 'number' || !Number.isFinite(value))
|
|
21
|
+
return null;
|
|
22
|
+
const formatted = Math.abs(value).toLocaleString('en-US');
|
|
23
|
+
if (!signed)
|
|
24
|
+
return formatted;
|
|
25
|
+
if (value > 0)
|
|
26
|
+
return `+${formatted}`;
|
|
27
|
+
if (value < 0)
|
|
28
|
+
return `-${formatted}`;
|
|
29
|
+
return formatted;
|
|
30
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { sanitizeTerminalText } from './json-response.js';
|
|
2
|
+
import { formatFiniteLengthCount, } from './prompt-length-wire.js';
|
|
3
|
+
export function printPromptSummaryTable(items, emptyMessage, printLine) {
|
|
4
|
+
if (items.length === 0) {
|
|
5
|
+
printLine(emptyMessage);
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
const rows = items.map(item => ({
|
|
9
|
+
id: sanitizeTerminalText(item.id),
|
|
10
|
+
name: sanitizeTerminalText(item.name),
|
|
11
|
+
role: sanitizeTerminalText(item.role),
|
|
12
|
+
status: sanitizeTerminalText(item.status || 'active'),
|
|
13
|
+
tokens: item.lengthStats == null
|
|
14
|
+
? '—'
|
|
15
|
+
: (() => {
|
|
16
|
+
const count = formatFiniteLengthCount(item.lengthStats.tokens);
|
|
17
|
+
return count === null ? '—' : `~${count}`;
|
|
18
|
+
})(),
|
|
19
|
+
lines: item.lengthStats == null
|
|
20
|
+
? '—'
|
|
21
|
+
: formatFiniteLengthCount(item.lengthStats.lines) ?? '—',
|
|
22
|
+
chars: item.lengthStats == null
|
|
23
|
+
? '—'
|
|
24
|
+
: formatFiniteLengthCount(item.lengthStats.chars) ?? '—',
|
|
25
|
+
words: item.lengthStats == null
|
|
26
|
+
? '—'
|
|
27
|
+
: formatFiniteLengthCount(item.lengthStats.words) ?? '—',
|
|
28
|
+
}));
|
|
29
|
+
const headers = ['ID', 'NAME', 'ROLE', 'STATUS', 'TOKENS', 'LINES', 'CHARS', 'WORDS'];
|
|
30
|
+
const keys = ['id', 'name', 'role', 'status', 'tokens', 'lines', 'chars', 'words'];
|
|
31
|
+
const widths = keys.map((key, index) => Math.max(headers[index].length, ...rows.map(row => row[key].length)));
|
|
32
|
+
printLine(headers.map((header, index) => header.padEnd(widths[index])).join(' '));
|
|
33
|
+
printLine(widths.map(width => '-'.repeat(width)).join(' '));
|
|
34
|
+
rows.forEach(row => {
|
|
35
|
+
printLine(keys.map((key, index) => row[key].padEnd(widths[index])).join(' '));
|
|
36
|
+
});
|
|
37
|
+
}
|
package/package.json
CHANGED
package/src/diff-comments-cli.ts
CHANGED
|
@@ -3,6 +3,13 @@ import {
|
|
|
3
3
|
isJsonErrorResponsePayload,
|
|
4
4
|
} from './error-response.js'
|
|
5
5
|
import { sanitizeHumanInlineText } from './json-response.js'
|
|
6
|
+
import {
|
|
7
|
+
formatFiniteLengthCount,
|
|
8
|
+
type CliLengthDelta,
|
|
9
|
+
type CliLengthMeasurementUnavailableReason,
|
|
10
|
+
type CliLengthStats,
|
|
11
|
+
type CliLengthStatsPair,
|
|
12
|
+
} from './prompt-length-wire.js'
|
|
6
13
|
|
|
7
14
|
interface DiffCommentAuthor {
|
|
8
15
|
name?: string
|
|
@@ -42,6 +49,9 @@ interface DiffCommentPayloadPairContext {
|
|
|
42
49
|
diff: string | null
|
|
43
50
|
bodies: { from: string; to: string } | null
|
|
44
51
|
degraded: { reason: DiffCommentContextUnavailableReason } | null
|
|
52
|
+
lengthStats: CliLengthStatsPair | null
|
|
53
|
+
lengthDelta: CliLengthDelta | null
|
|
54
|
+
lengthDeltaUnavailableReason?: CliLengthMeasurementUnavailableReason
|
|
45
55
|
comments: DiffCommentPayloadComment[]
|
|
46
56
|
}
|
|
47
57
|
|
|
@@ -143,6 +153,86 @@ function humanLineNumber(
|
|
|
143
153
|
: sanitizeHumanInlineText(ctx.sanitizeTerminalText, String(line + 1))
|
|
144
154
|
}
|
|
145
155
|
|
|
156
|
+
function formatStats(stats: CliLengthStats): string {
|
|
157
|
+
const tokens = formatFiniteLengthCount(stats.tokens)
|
|
158
|
+
return `${tokens === null ? '—' : `~${tokens}`} tokens · ` +
|
|
159
|
+
`${formatFiniteLengthCount(stats.lines) ?? '—'} lines · ` +
|
|
160
|
+
`${formatFiniteLengthCount(stats.chars) ?? '—'} chars · ` +
|
|
161
|
+
`${formatFiniteLengthCount(stats.words) ?? '—'} words`
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function formatDeltaValue(
|
|
165
|
+
value: number | null,
|
|
166
|
+
metric: keyof Omit<CliLengthDelta, 'splitUnavailableReason'>,
|
|
167
|
+
signed = false
|
|
168
|
+
): string {
|
|
169
|
+
const formatted = formatFiniteLengthCount(value, signed)
|
|
170
|
+
if (formatted === null) return '—'
|
|
171
|
+
return metric === 'tokens' ? `~${formatted}` : formatted
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function printLengthMeasurements(
|
|
175
|
+
ctx: DiffCommentsCliContext,
|
|
176
|
+
pair: DiffCommentPayloadPair
|
|
177
|
+
) {
|
|
178
|
+
function unavailableSuffix(reason: unknown): string {
|
|
179
|
+
if (typeof reason !== 'string' || reason.length === 0) return ''
|
|
180
|
+
return ` (${sanitizeHumanInlineText(ctx.sanitizeTerminalText, reason)})`
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (!pair.lengthStats && !pair.lengthDelta) {
|
|
184
|
+
ctx.printLine(
|
|
185
|
+
` Length: unavailable${unavailableSuffix(
|
|
186
|
+
pair.lengthDeltaUnavailableReason ?? pair.degraded?.reason
|
|
187
|
+
)}`
|
|
188
|
+
)
|
|
189
|
+
return
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (pair.lengthStats) {
|
|
193
|
+
ctx.printLine(pair.lengthStats.from
|
|
194
|
+
? ` From: ${formatStats(pair.lengthStats.from)}`
|
|
195
|
+
: ` From: unavailable${unavailableSuffix(
|
|
196
|
+
pair.lengthStats.fromUnavailableReason
|
|
197
|
+
)}`)
|
|
198
|
+
ctx.printLine(pair.lengthStats.to
|
|
199
|
+
? ` To: ${formatStats(pair.lengthStats.to)}`
|
|
200
|
+
: ` To: unavailable${unavailableSuffix(
|
|
201
|
+
pair.lengthStats.toUnavailableReason
|
|
202
|
+
)}`)
|
|
203
|
+
}
|
|
204
|
+
if (!pair.lengthDelta) {
|
|
205
|
+
ctx.printLine(
|
|
206
|
+
` Length delta: unavailable${unavailableSuffix(
|
|
207
|
+
pair.lengthDeltaUnavailableReason ?? pair.degraded?.reason
|
|
208
|
+
)}`
|
|
209
|
+
)
|
|
210
|
+
return
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (pair.lengthDelta.splitUnavailableReason) {
|
|
214
|
+
ctx.printLine(
|
|
215
|
+
` Split unavailable: ${sanitizeHumanInlineText(
|
|
216
|
+
ctx.sanitizeTerminalText,
|
|
217
|
+
pair.lengthDelta.splitUnavailableReason
|
|
218
|
+
)}`
|
|
219
|
+
)
|
|
220
|
+
}
|
|
221
|
+
for (const [metric, label] of [
|
|
222
|
+
['tokens', 'Tokens'],
|
|
223
|
+
['lines', 'Lines'],
|
|
224
|
+
['chars', 'Chars'],
|
|
225
|
+
['words', 'Words'],
|
|
226
|
+
] as const) {
|
|
227
|
+
const delta = pair.lengthDelta[metric]
|
|
228
|
+
ctx.printLine(
|
|
229
|
+
` ${label}: removed ${formatDeltaValue(delta.removed, metric)} · ` +
|
|
230
|
+
`added ${formatDeltaValue(delta.added, metric)} · ` +
|
|
231
|
+
`net ${formatDeltaValue(delta.net, metric, true)}`
|
|
232
|
+
)
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
146
236
|
function buildParams(ctx: DiffCommentsCliContext): URLSearchParams {
|
|
147
237
|
const runId = ctx.getArg('--run')
|
|
148
238
|
const promptId = ctx.getArg('--prompt')
|
|
@@ -210,6 +300,7 @@ function printDiffComments(ctx: DiffCommentsCliContext, payload: DiffCommentsPay
|
|
|
210
300
|
`${sanitizeHumanInlineText(ctx.sanitizeTerminalText, from)} → ` +
|
|
211
301
|
`${sanitizeHumanInlineText(ctx.sanitizeTerminalText, to)}`
|
|
212
302
|
)
|
|
303
|
+
printLengthMeasurements(ctx, pair)
|
|
213
304
|
if (pair.degraded) {
|
|
214
305
|
ctx.printLine(
|
|
215
306
|
` Context unavailable: ${sanitizeHumanInlineText(ctx.sanitizeTerminalText, pair.degraded.reason)}`
|
package/src/index.ts
CHANGED
|
@@ -88,6 +88,11 @@ import { runGitCredentialInvocation } from './git-credential.js'
|
|
|
88
88
|
import { pushPromptDraft } from './prompt-draft-push.js'
|
|
89
89
|
import { readMarkdownReportInput } from './markdown-report-input.js'
|
|
90
90
|
import { promptPushErrorMessage, promptReportCommand } from './prompt-report-cli.js'
|
|
91
|
+
import { printPromptSummaryTable } from './prompt-summary-table.js'
|
|
92
|
+
import type {
|
|
93
|
+
CliLengthMeasurementUnavailableReason,
|
|
94
|
+
CliLengthStats,
|
|
95
|
+
} from './prompt-length-wire.js'
|
|
91
96
|
import { assertSnapshotManifestConfined, verifyGepaRunnerDirsFromArgs, verifyRunnerDirRegistered } from './runner-dir-verify.js'
|
|
92
97
|
import { runScorersRegister } from './scorer-draft-push.js'
|
|
93
98
|
import { runZipArtifactPush } from './zip-draft-push.js'
|
|
@@ -182,6 +187,10 @@ interface PromptSummary {
|
|
|
182
187
|
status?: string
|
|
183
188
|
archivedAt?: string | null
|
|
184
189
|
description?: string | null
|
|
190
|
+
lengthStats?: CliLengthStats | null
|
|
191
|
+
lengthStatsUnavailableReason?: CliLengthMeasurementUnavailableReason
|
|
192
|
+
lengthStatsVersionId?: string
|
|
193
|
+
lengthStatsVersionNumber?: number
|
|
185
194
|
}
|
|
186
195
|
|
|
187
196
|
interface TaskReportPayload {
|
|
@@ -536,30 +545,6 @@ function shellQuote(value: string): string {
|
|
|
536
545
|
return `"${value.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`
|
|
537
546
|
}
|
|
538
547
|
|
|
539
|
-
function printPromptSummaries(items: PromptSummary[], emptyMessage: string) {
|
|
540
|
-
if (items.length === 0) {
|
|
541
|
-
printLine(emptyMessage)
|
|
542
|
-
return
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
const rows = items.map(item => ({
|
|
546
|
-
id: sanitizeTerminalText(item.id),
|
|
547
|
-
name: sanitizeTerminalText(item.name),
|
|
548
|
-
role: sanitizeTerminalText(item.role),
|
|
549
|
-
status: sanitizeTerminalText(item.status || 'active'),
|
|
550
|
-
}))
|
|
551
|
-
const idWidth = Math.max('ID'.length, ...rows.map(row => row.id.length))
|
|
552
|
-
const nameWidth = Math.max('NAME'.length, ...rows.map(row => row.name.length))
|
|
553
|
-
const roleWidth = Math.max('ROLE'.length, ...rows.map(row => row.role.length))
|
|
554
|
-
const statusWidth = Math.max('STATUS'.length, ...rows.map(row => row.status.length))
|
|
555
|
-
|
|
556
|
-
printLine(`${'ID'.padEnd(idWidth)} ${'NAME'.padEnd(nameWidth)} ${'ROLE'.padEnd(roleWidth)} ${'STATUS'.padEnd(statusWidth)}`)
|
|
557
|
-
printLine(`${'-'.repeat(idWidth)} ${'-'.repeat(nameWidth)} ${'-'.repeat(roleWidth)} ${'-'.repeat(statusWidth)}`)
|
|
558
|
-
rows.forEach(row => {
|
|
559
|
-
printLine(`${row.id.padEnd(idWidth)} ${row.name.padEnd(nameWidth)} ${row.role.padEnd(roleWidth)} ${row.status.padEnd(statusWidth)}`)
|
|
560
|
-
})
|
|
561
|
-
}
|
|
562
|
-
|
|
563
548
|
function readJsonObjectArg(valueArg: string | null, label: string): Record<string, unknown> {
|
|
564
549
|
if (!valueArg) {
|
|
565
550
|
return {}
|
|
@@ -1383,7 +1368,7 @@ async function listPrompts() {
|
|
|
1383
1368
|
printJson(data as unknown as Record<string, unknown>)
|
|
1384
1369
|
return
|
|
1385
1370
|
}
|
|
1386
|
-
|
|
1371
|
+
printPromptSummaryTable(data.prompts, 'No prompts found.', printLine)
|
|
1387
1372
|
}
|
|
1388
1373
|
|
|
1389
1374
|
async function listJudges() {
|
|
@@ -1404,7 +1389,7 @@ async function listJudges() {
|
|
|
1404
1389
|
printJson(data as unknown as Record<string, unknown>)
|
|
1405
1390
|
return
|
|
1406
1391
|
}
|
|
1407
|
-
|
|
1392
|
+
printPromptSummaryTable(data.judges, 'No judges found.', printLine)
|
|
1408
1393
|
}
|
|
1409
1394
|
|
|
1410
1395
|
async function listScorers() {
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
export const CLI_LENGTH_STATS_FIELDS = [
|
|
2
|
+
'tokens',
|
|
3
|
+
'lines',
|
|
4
|
+
'chars',
|
|
5
|
+
'words',
|
|
6
|
+
] as const
|
|
7
|
+
|
|
8
|
+
export const CLI_LENGTH_DELTA_SPLIT_UNAVAILABLE_REASONS = [
|
|
9
|
+
'diff_degraded_size_limit',
|
|
10
|
+
'diff_degraded_cell_limit',
|
|
11
|
+
] as const
|
|
12
|
+
export const CLI_LENGTH_MEASUREMENT_UNAVAILABLE_REASONS = [
|
|
13
|
+
'length_measurement_size_limit',
|
|
14
|
+
'length_measurement_failed',
|
|
15
|
+
'body_resolution_failed',
|
|
16
|
+
'measurement_cap_exceeded',
|
|
17
|
+
'enrichment_failed',
|
|
18
|
+
'bodies_unavailable_event_cap',
|
|
19
|
+
] as const
|
|
20
|
+
|
|
21
|
+
export type CliLengthStatsField = typeof CLI_LENGTH_STATS_FIELDS[number]
|
|
22
|
+
export type CliLengthDeltaSplitUnavailableReason =
|
|
23
|
+
typeof CLI_LENGTH_DELTA_SPLIT_UNAVAILABLE_REASONS[number]
|
|
24
|
+
export type CliLengthMeasurementUnavailableReason =
|
|
25
|
+
typeof CLI_LENGTH_MEASUREMENT_UNAVAILABLE_REASONS[number]
|
|
26
|
+
|
|
27
|
+
export interface CliLengthStats {
|
|
28
|
+
tokens: number
|
|
29
|
+
lines: number
|
|
30
|
+
chars: number
|
|
31
|
+
words: number
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface CliLengthStatsPair {
|
|
35
|
+
from: CliLengthStats | null
|
|
36
|
+
to: CliLengthStats | null
|
|
37
|
+
fromUnavailableReason?: CliLengthMeasurementUnavailableReason
|
|
38
|
+
toUnavailableReason?: CliLengthMeasurementUnavailableReason
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface CliLengthMetricDelta {
|
|
42
|
+
removed: number | null
|
|
43
|
+
added: number | null
|
|
44
|
+
net: number
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface CliLengthDelta extends Record<
|
|
48
|
+
CliLengthStatsField,
|
|
49
|
+
CliLengthMetricDelta
|
|
50
|
+
> {
|
|
51
|
+
splitUnavailableReason: CliLengthDeltaSplitUnavailableReason | null
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function formatFiniteLengthCount(
|
|
55
|
+
value: unknown,
|
|
56
|
+
signed = false
|
|
57
|
+
): string | null {
|
|
58
|
+
if (typeof value !== 'number' || !Number.isFinite(value)) return null
|
|
59
|
+
|
|
60
|
+
const formatted = Math.abs(value).toLocaleString('en-US')
|
|
61
|
+
if (!signed) return formatted
|
|
62
|
+
if (value > 0) return `+${formatted}`
|
|
63
|
+
if (value < 0) return `-${formatted}`
|
|
64
|
+
return formatted
|
|
65
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { sanitizeTerminalText } from './json-response.js'
|
|
2
|
+
import {
|
|
3
|
+
formatFiniteLengthCount,
|
|
4
|
+
type CliLengthStats,
|
|
5
|
+
} from './prompt-length-wire.js'
|
|
6
|
+
|
|
7
|
+
interface PromptSummaryRow {
|
|
8
|
+
id: string
|
|
9
|
+
name: string
|
|
10
|
+
role: string
|
|
11
|
+
status?: string
|
|
12
|
+
lengthStats?: CliLengthStats | null
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function printPromptSummaryTable(
|
|
16
|
+
items: PromptSummaryRow[],
|
|
17
|
+
emptyMessage: string,
|
|
18
|
+
printLine: (line: string) => void
|
|
19
|
+
) {
|
|
20
|
+
if (items.length === 0) {
|
|
21
|
+
printLine(emptyMessage)
|
|
22
|
+
return
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const rows = items.map(item => ({
|
|
26
|
+
id: sanitizeTerminalText(item.id),
|
|
27
|
+
name: sanitizeTerminalText(item.name),
|
|
28
|
+
role: sanitizeTerminalText(item.role),
|
|
29
|
+
status: sanitizeTerminalText(item.status || 'active'),
|
|
30
|
+
tokens: item.lengthStats == null
|
|
31
|
+
? '—'
|
|
32
|
+
: (() => {
|
|
33
|
+
const count = formatFiniteLengthCount(item.lengthStats.tokens)
|
|
34
|
+
return count === null ? '—' : `~${count}`
|
|
35
|
+
})(),
|
|
36
|
+
lines: item.lengthStats == null
|
|
37
|
+
? '—'
|
|
38
|
+
: formatFiniteLengthCount(item.lengthStats.lines) ?? '—',
|
|
39
|
+
chars: item.lengthStats == null
|
|
40
|
+
? '—'
|
|
41
|
+
: formatFiniteLengthCount(item.lengthStats.chars) ?? '—',
|
|
42
|
+
words: item.lengthStats == null
|
|
43
|
+
? '—'
|
|
44
|
+
: formatFiniteLengthCount(item.lengthStats.words) ?? '—',
|
|
45
|
+
}))
|
|
46
|
+
const headers = ['ID', 'NAME', 'ROLE', 'STATUS', 'TOKENS', 'LINES', 'CHARS', 'WORDS']
|
|
47
|
+
const keys = ['id', 'name', 'role', 'status', 'tokens', 'lines', 'chars', 'words'] as const
|
|
48
|
+
const widths = keys.map((key, index) =>
|
|
49
|
+
Math.max(headers[index].length, ...rows.map(row => row[key].length))
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
printLine(headers.map((header, index) => header.padEnd(widths[index])).join(' '))
|
|
53
|
+
printLine(widths.map(width => '-'.repeat(width)).join(' '))
|
|
54
|
+
rows.forEach(row => {
|
|
55
|
+
printLine(keys.map((key, index) => row[key].padEnd(widths[index])).join(' '))
|
|
56
|
+
})
|
|
57
|
+
}
|
|
@@ -290,6 +290,15 @@ orizu comments diff --prompt <prompt-id> [--from <version> --to <version>] [--de
|
|
|
290
290
|
Exactly one target is required, and `--from` / `--to` must appear together.
|
|
291
291
|
Prompt pair selectors are integer version numbers. Human output groups comments
|
|
292
292
|
by pair and renders anchored hunks; `--json` emits the complete machine payload.
|
|
293
|
+
Each available side prints `From:` or `To:` length stats; one side can be
|
|
294
|
+
`unavailable (<reason>)` while the other remains visible. Machine output allows
|
|
295
|
+
`lengthStats.from` and `lengthStats.to` to be independently null and names the
|
|
296
|
+
side failures in `fromUnavailableReason` and `toUnavailableReason`. A wholly
|
|
297
|
+
unavailable pair prints `Length: unavailable (<reason>)`; a missing delta
|
|
298
|
+
prints `Length delta: unavailable`. Otherwise `Tokens:`, `Lines:`, `Chars:`,
|
|
299
|
+
and `Words:` show removed/added/net rows. A `Split unavailable:` row names the
|
|
300
|
+
exact guard when split churn cannot be computed; removed/added are `—` but the
|
|
301
|
+
independent net remains numeric.
|
|
293
302
|
Unrecoverable context is retained with a named degradation reason rather than
|
|
294
303
|
dropping a comment. Optimization export includes the same data at
|
|
295
304
|
`diffComments` using hunk detail. It also includes
|
|
@@ -313,6 +322,7 @@ Behavior:
|
|
|
313
322
|
- `run-gepa` writes a complete local trace under `logs/<optimization_run_id>` by default.
|
|
314
323
|
- The local trace is the best artifact for coding-agent analysis because it includes full rows, outputs, scores, feedback, scorer responses, reflection prompts, reflection responses, candidate text, and `result.json`.
|
|
315
324
|
- `optimizations export` writes a portable JSON artifact from server data when the local log is unavailable or the run happened elsewhere.
|
|
325
|
+
- The v1 export preserves the run row's `best_candidate_id` in `summary.bestCandidateId` when event derivation rejects it as unknown; candidate detail may be absent, and the field is `null` when neither source names a best candidate.
|
|
316
326
|
- Server optimization events redact row snapshots and reflection prompts by default; export rehydrates row inputs from dataset artifacts when possible and includes bundled `run-gepa` reflection responses.
|
|
317
327
|
|
|
318
328
|
## End-to-End Flows
|
|
@@ -413,6 +413,20 @@ orizu --local judges list --project <team>/<project>
|
|
|
413
413
|
Prompt and judge lists show active artifacts by default. Use `--status archived`
|
|
414
414
|
or `--status all` when you need archived artifacts.
|
|
415
415
|
|
|
416
|
+
Prompt and judge list tables include `ID`, `NAME`, `ROLE`, `STATUS`, `TOKENS`,
|
|
417
|
+
`LINES`, `CHARS`, and `WORDS`, measured from the latest sealed version. `—`
|
|
418
|
+
means the canonical body could not be measured; zero remains `0`. The `~`
|
|
419
|
+
prefix on token counts means approximate: Orizu uses one fixed, model-agnostic
|
|
420
|
+
`gpt-tokenizer` encoding rather than claiming an exact count for every model.
|
|
421
|
+
Failed or deliberately skipped JSON enrichment carries a named
|
|
422
|
+
`lengthStatsUnavailableReason`. Measured summaries also include
|
|
423
|
+
`lengthStatsVersionId` and `lengthStatsVersionNumber`, identifying the latest
|
|
424
|
+
sealed version behind each measurement even when the canonical body could not
|
|
425
|
+
be measured. Length enrichment is best-effort: a supporting query failure
|
|
426
|
+
leaves the list available with null stats and `enrichment_failed`. At most the
|
|
427
|
+
first 500 sorted summaries are enriched per request; later summaries carry
|
|
428
|
+
null stats and `measurement_cap_exceeded`.
|
|
429
|
+
|
|
416
430
|
Archive or restore a prompt:
|
|
417
431
|
|
|
418
432
|
```bash
|
|
@@ -742,6 +756,11 @@ orizu --local optimizations export <optimization-run-id> \
|
|
|
742
756
|
|
|
743
757
|
Use export when the local log is unavailable, the run happened on another machine, or a coding agent needs a portable single JSON artifact. The export fetches all optimization events, derives seed vs best, Pareto frontier, score-over-time, candidates, iterations, minibatch rows, and validation rows, and rehydrates row inputs from the dataset version artifact when possible. Server events may not contain row snapshots or reflection prompts unless the run used `--log-row-snapshots`; reflection responses are included for bundled `run-gepa` runs.
|
|
744
758
|
|
|
759
|
+
The v1 export keeps the run row's `best_candidate_id` in
|
|
760
|
+
`summary.bestCandidateId` when event derivation rejects that identifier as an
|
|
761
|
+
unknown candidate. Candidate detail can therefore be absent for the preserved
|
|
762
|
+
identifier. If neither source names a best candidate, the field is `null`.
|
|
763
|
+
|
|
745
764
|
Lifecycle controls:
|
|
746
765
|
|
|
747
766
|
```bash
|