@trazum/cli 1.35.0 → 1.37.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trazum/cli",
3
- "version": "1.35.0",
3
+ "version": "1.37.0",
4
4
  "description": "Trazum CLI: find where your LLM bill goes, price every finding per month, and enforce token budgets in CI.",
5
5
  "license": "MIT",
6
6
  "author": "David Mu\u00f1oz Rey",
@@ -37,7 +37,7 @@
37
37
  "prepublishOnly": "npm run build && npm test"
38
38
  },
39
39
  "dependencies": {
40
- "@trazum/core": "1.35.0"
40
+ "@trazum/core": "1.37.0"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/node": "^26.2.0",
package/src/i18n/en.ts CHANGED
@@ -78,6 +78,16 @@ ${bold('OPTIONS FOR rank')}
78
78
  --model, --calls, Price the recoverable tokens, as in optimize.
79
79
  --output-tokens, --batch
80
80
  --prompt <name> Which marked prompt to take from each source file.
81
+ --by-source The fleet: one summary per service from the
82
+ config's "sources" block (name → glob patterns
83
+ over log paths), plus a rollup naming the source
84
+ where the money is. Shares compare totals, and
85
+ when the sources' logs cover different periods
86
+ the report says so rather than letting a 3-day
87
+ log look cheap beside a 30-day one. Budgets per
88
+ service live in spend.bySource and fail the run
89
+ naming the service. Files matching no pattern
90
+ are named, never silently dropped.
81
91
  --markdown-out <file> Also write the ranking as Markdown, for a CI job
82
92
  summary or a pull request comment.
83
93
  --json The ranking as data.
@@ -119,6 +129,20 @@ ${bold('OPTIONS FOR optimize')}
119
129
  --calls <n> Calls per month. Default: ${d.callsPerMonth}.
120
130
  --output-tokens <n> Average output tokens. Default: ${d.avgOutputTokens}.
121
131
  --cache-hit-rate <0-1> Estimated cache hit rate. Default: ${d.cacheHitRate}.
132
+ --all-labels With --from-log: every prompt in the config's
133
+ "labels" map, optimised and priced against its
134
+ own measured traffic, ranked by what the change
135
+ is worth — plus the mismatches in both
136
+ directions (mapped prompts with no traffic,
137
+ traffic with no mapped prompt).
138
+ --from-log <usage.jsonl> Measure the three figures above from a usage log
139
+ instead of typing them: real call count, real
140
+ output size, real cache share, and the model the
141
+ calls actually went to. Refuses the typed flags
142
+ beside it, scales to a month only past a full
143
+ week of data, and says which figures are
144
+ measured. Pair with --label, or map the prompt
145
+ under "labels" in trazum.config.json.
122
146
  --batch The work tolerates latency (Batch API, 50% off).
123
147
  --disable <id,id> Turn off specific rules (see "trazum rules").
124
148
  --suggest Ask the LLM for phrase-level rewrites and list them
@@ -444,6 +468,18 @@ ${bold('EXAMPLES')}
444
468
  mustBeNonNegative: (name, raw) =>
445
469
  `--${name} must be a non-negative number (received: "${raw}").`,
446
470
  badLevel: (received) => `--level must be "safe" or "aggressive" (received: "${received}").`,
471
+ allLabelsNeedsLog: () =>
472
+ '--all-labels ranks prompts by measured traffic, so it needs --from-log <usage.jsonl>. Without a log every saving would be multiplied by the same typed guess, which ranks prompts by length and calls it a priority.',
473
+ allLabelsNeedsMap: () =>
474
+ '--all-labels reads the "labels" map in trazum.config.json — label to prompt file — and this config has none. Map at least one workload to its prompt.',
475
+ fromLogConflict: (flag) =>
476
+ `--from-log measures the figure --${flag} types, and merging a measurement with a guess produces a number that is neither. Pass one or the other.`,
477
+ fromLogNeedsLabel: (available) =>
478
+ `--from-log needs to know which workload this prompt is: pass --label, or map the prompt file under "labels" in trazum.config.json. Labels with traffic in this log: ${available}.`,
479
+ fromLogAmbiguousLabel: (target, labels) =>
480
+ `${target} is mapped to more than one label in trazum.config.json (${labels}), so --from-log cannot pick one silently. Pass --label.`,
481
+ fromLogLabelEmpty: (label, available) =>
482
+ `No priced call in this log carries the label "${label}", so there is nothing to measure — a zero-call profile would price this change as worthless rather than as unmeasured. Labels with traffic: ${available}.`,
447
483
  unknownRuleInDisable: (id) => `Unknown rule in --disable: "${id}". Full list: trazum rules`,
448
484
  unknownCommand: (command) => `Unknown command: "${command}". Try "trazum --help".`,
449
485
  missingInputFile: () => 'Missing input file. Use "-" to read from standard input.',
@@ -510,6 +546,30 @@ ${bold('EXAMPLES')}
510
546
  costWith: (modelName) => `Cost with ${modelName}`,
511
547
  usageLine: (calls, outputTokens, batch) =>
512
548
  `${calls} calls/month · ${outputTokens} output tokens per call${batch ? ' · Batch API' : ''}`,
549
+ allLabelsHeading: (count) => `Every mapped prompt against its own measured traffic — ${count} ranked by what the change is worth`,
550
+ allLabelsRow: (saving) => `${saving}/month if optimised`,
551
+ allLabelsRowPeriod: (saving) => `${saving} over the measured period if optimised`,
552
+ allLabelsFooter: () =>
553
+ 'Ranked by measured traffic, not by prompt length: a big prompt on a dead workload is worth less than a small one on a busy one. Each figure is this prompt\'s token delta at its own label\'s measured rate.',
554
+ allLabelsUnmapped: (label, usd) =>
555
+ `${label} carries ${usd} of measured spend and no prompt file is mapped to it — the workload nobody can optimise because nobody said where it lives. Map it under "labels" in trazum.config.json.`,
556
+ allLabelsDead: (label, path) =>
557
+ `${label} is mapped to ${path} and has no traffic in this log — a retired workload, a renamed label, or a typo that has been silently doing nothing.`,
558
+ allLabelsUnreadable: (label, path) =>
559
+ `${label} is mapped to ${path}, which could not be read. The mapping exists; the file does not.`,
560
+ usageLineMeasured: (calls, days, scaled, outputTokens, batch) =>
561
+ `${calls} calls measured over ${days} days — ${scaled}/month at that rate · ${outputTokens} output tokens per call, measured${batch ? ' · Batch API' : ''}`,
562
+ usageLineMeasuredPeriod: (calls, days, outputTokens, batch) =>
563
+ `${calls} calls measured${days === null ? ' (the log carries no clock)' : ` over ${days} days`} · ${outputTokens} output tokens per call, measured${batch ? ' · Batch API' : ''}`,
564
+ measuredModelShare: (model, share, count) =>
565
+ `This label ran on ${count} models; the figures use ${model}, which carried ${share} of its spend.`,
566
+ measuredNoOutput: () =>
567
+ 'No call in this slice recorded output tokens, so the output half of every figure below is $0 measured — not $0 assumed.',
568
+ perPeriodSaving: (saving, pct) => `saving ${saving} over the measured period (${pct}%)`,
569
+ periodNotScaled: (days) =>
570
+ days === null
571
+ ? 'Not scaled to a month: the log carries no clock, so there is no rate to scale. These figures cover exactly the calls measured.'
572
+ : `Not scaled to a month: ${days} days is under the week a scaling needs — shorter than one weekly cycle multiplies whichever part of the cycle it caught. These figures cover exactly the period measured.`,
513
573
  perMonthSaving: (saving, pct) => `saving ${saving}/month (${pct}%)`,
514
574
  beyondShortening: () => 'Beyond shortening the prompt',
515
575
  biggestLever: () => 'Start here:',
@@ -1177,6 +1237,31 @@ ${bold('EXAMPLES')}
1177
1237
  'A ✗ is not a defect in the log; it is a finding this log cannot support yet. The README\'s recording recipe carries every field above.',
1178
1238
  dryRunNoGates: () =>
1179
1239
  '--dry-run produces no bill, so a gate beside it would exit green having judged nothing. Run the gates without --dry-run.',
1240
+ bySourceNeedsConfig: () =>
1241
+ '--by-source reads the "sources" block in trazum.config.json — a name per service, each with glob patterns over log paths — and this config has none. Name at least one source.',
1242
+ bySourceNothingMatched: (sources) =>
1243
+ 'No log file matched any source pattern. The sources configured: ${sources}. Patterns match the paths as given on the command line.'.replace('${sources}', sources),
1244
+ fleetHeading: (count, total, calls) => `The fleet: ${count} sources · ${total} · ${calls}`,
1245
+ fleetRow: (name, usd, share, calls, span) => `${name} ${usd} ${share} of the fleet · ${calls} · ${span}`,
1246
+ fleetSpan: (days) => `${days} days`,
1247
+ fleetNoClock: () => 'no clock',
1248
+ fleetWorst: (name, usd, share) =>
1249
+ `${name} is where the money is: ${usd}, ${share} of the fleet's total.`,
1250
+ fleetMismatchedSpans: () =>
1251
+ 'These sources cover different periods, so the shares above compare totals, not rates — a 3-day log looks cheap next to a 30-day one for reasons that have nothing to do with cost. Each row states its own span.',
1252
+ fleetSplitBrain: (label, detail) =>
1253
+ `The same workload runs on different models in different sources — ${label}: ${detail}. Same job, different rate cards; whether that is a decision or an accident is not in the logs.`,
1254
+ fleetCacheUnderwater: (name, usd) =>
1255
+ `Caching pays for the fleet overall but loses ${usd} in ${name} — the aggregate verdict was hiding it.`,
1256
+ fleetUnmatched: (file) =>
1257
+ `${file} matched no source pattern, so it is in no report above — spend missing from every bill until a pattern covers it.`,
1258
+ fleetFooter: () =>
1259
+ 'Summaries per source; the full report for one service is "trazum profile <its logs>". Same thresholds, same findings, one source at a time.',
1260
+ fleetBudgetOk: (name, usd, max) => `Within budget: ${name} spent ${usd} against its ${max} in spend.bySource.`,
1261
+ fleetBudgetFailed: (name, usd, max) =>
1262
+ `FAILED — ${name} spent ${usd} against its budget of ${max} in spend.bySource. The fleet total can be fine while one service bleeds; this gate names which.`,
1263
+ fleetBudgetMissing: (name) =>
1264
+ `${name} has a budget in spend.bySource and no logs matched it in this run, so nothing was measured for it. Not a pass: a service that did not appear is not a service under budget.`,
1180
1265
  coverageHeading: () => 'What this log cannot answer yet',
1181
1266
  needsLabel: (seen) =>
1182
1267
  `"label" on ${seen} records: without it every workload is one row, so no per-workload spend, no drill-down, and the levers describe a mixture rather than a decision.`,
package/src/i18n/es.ts CHANGED
@@ -66,6 +66,18 @@ ${bold('OPCIONES DE rank')}
66
66
  --model, --calls, Calcula el coste de los tokens recuperables, como
67
67
  --output-tokens, --batch en optimize.
68
68
  --prompt <nombre> Qué prompt marcado tomar de cada fichero de código.
69
+ --by-source La flota: un resumen por servicio desde el
70
+ bloque "sources" de la config (nombre → patrones
71
+ glob sobre rutas de registros), más un rollup
72
+ que nombra la fuente donde está el dinero. Los
73
+ porcentajes comparan totales, y cuando los
74
+ registros cubren periodos distintos el informe
75
+ lo dice en vez de dejar que un registro de 3
76
+ días parezca barato junto a uno de 30. Los
77
+ presupuestos por servicio viven en
78
+ spend.bySource y hacen fallar la ejecución
79
+ nombrando el servicio. Los ficheros sin patrón
80
+ se nombran, nunca se descartan en silencio.
69
81
  --markdown-out <fichero> Escribe además el ranking en Markdown, para el
70
82
  resumen de un job de CI o un comentario de PR.
71
83
  --json El ranking como datos.
@@ -109,6 +121,20 @@ ${bold('OPCIONES DE optimize')}
109
121
  --calls <n> Llamadas al mes. Por defecto: ${d.callsPerMonth}.
110
122
  --output-tokens <n> Tokens de salida medios. Por defecto: ${d.avgOutputTokens}.
111
123
  --cache-hit-rate <0-1> Tasa de acierto de caché estimada. Por defecto: ${d.cacheHitRate}.
124
+ --all-labels Con --from-log: cada prompt del mapa "labels"
125
+ de la config, optimizado y valorado contra su
126
+ propio tráfico medido, ordenado por lo que vale
127
+ el cambio — más los desajustes en ambos sentidos
128
+ (prompts mapeados sin tráfico, tráfico sin
129
+ prompt mapeado).
130
+ --from-log <usage.jsonl> Mide las tres cifras de arriba desde un registro
131
+ de uso en vez de teclearlas: llamadas reales,
132
+ tamaño de salida real, cuota de caché real y el
133
+ modelo al que fueron las llamadas. Rechaza los
134
+ flags tecleados a su lado, escala a un mes solo
135
+ con una semana completa de datos, y dice qué
136
+ cifras están medidas. Combínalo con --label, o
137
+ mapea el prompt en "labels" de trazum.config.json.
112
138
  --batch El trabajo tolera latencia (Batch API, 50% menos).
113
139
  --disable <id,id> Desactiva reglas concretas (ver "trazum rules").
114
140
  --suggest Pide al LLM reescrituras a nivel de frase y las lista
@@ -451,6 +477,18 @@ ${bold('EJEMPLOS')}
451
477
  mustBeNonNegative: (name, raw) =>
452
478
  `--${name} debe ser un número no negativo (recibido: "${raw}").`,
453
479
  badLevel: (received) => `--level debe ser "safe" o "aggressive" (recibido: "${received}").`,
480
+ allLabelsNeedsLog: () =>
481
+ '--all-labels ordena los prompts por tráfico medido, así que necesita --from-log <usage.jsonl>. Sin registro cada ahorro se multiplicaría por la misma suposición tecleada, lo que ordena los prompts por longitud y lo llama prioridad.',
482
+ allLabelsNeedsMap: () =>
483
+ '--all-labels lee el mapa "labels" de trazum.config.json — etiqueta a fichero de prompt — y esta config no tiene ninguno. Mapea al menos una carga a su prompt.',
484
+ fromLogConflict: (flag) =>
485
+ `--from-log mide la cifra que --${flag} teclea, y mezclar una medición con una suposición produce un número que no es ninguna de las dos. Pasa una u otra.`,
486
+ fromLogNeedsLabel: (available) =>
487
+ `--from-log necesita saber qué carga es este prompt: pasa --label, o mapea el fichero bajo "labels" en trazum.config.json. Etiquetas con tráfico en este registro: ${available}.`,
488
+ fromLogAmbiguousLabel: (target, labels) =>
489
+ `${target} está mapeado a más de una etiqueta en trazum.config.json (${labels}), así que --from-log no puede elegir una en silencio. Pasa --label.`,
490
+ fromLogLabelEmpty: (label, available) =>
491
+ `Ninguna llamada valorada de este registro lleva la etiqueta "${label}", así que no hay nada que medir — un perfil de cero llamadas valoraría este cambio como inútil en vez de como no medido. Etiquetas con tráfico: ${available}.`,
454
492
  unknownRuleInDisable: (id) =>
455
493
  `Regla desconocida en --disable: "${id}". Lista completa: trazum rules`,
456
494
  unknownCommand: (command) => `Comando desconocido: "${command}". Prueba con "trazum --help".`,
@@ -519,6 +557,30 @@ ${bold('EJEMPLOS')}
519
557
  `${calls} llamadas/mes · ${outputTokens} tokens de salida por llamada${
520
558
  batch ? ' · Batch API' : ''
521
559
  }`,
560
+ allLabelsHeading: (count) => `Cada prompt mapeado contra su propio tráfico medido — ${count} ordenados por lo que vale el cambio`,
561
+ allLabelsRow: (saving) => `${saving}/mes si se optimiza`,
562
+ allLabelsRowPeriod: (saving) => `${saving} en el periodo medido si se optimiza`,
563
+ allLabelsFooter: () =>
564
+ 'Ordenado por tráfico medido, no por longitud del prompt: un prompt grande en una carga muerta vale menos que uno pequeño en una ocupada. Cada cifra es el delta de tokens de este prompt al ritmo medido de su propia etiqueta.',
565
+ allLabelsUnmapped: (label, usd) =>
566
+ `${label} lleva ${usd} de gasto medido y ningún fichero de prompt está mapeado a ella — la carga que nadie puede optimizar porque nadie dijo dónde vive. Mapéala en "labels" de trazum.config.json.`,
567
+ allLabelsDead: (label, path) =>
568
+ `${label} está mapeada a ${path} y no tiene tráfico en este registro — una carga retirada, una etiqueta renombrada, o una errata que lleva sin hacer nada en silencio.`,
569
+ allLabelsUnreadable: (label, path) =>
570
+ `${label} está mapeada a ${path}, que no se pudo leer. El mapeo existe; el fichero no.`,
571
+ usageLineMeasured: (calls, days, scaled, outputTokens, batch) =>
572
+ `${calls} llamadas medidas en ${days} días — ${scaled}/mes a ese ritmo · ${outputTokens} tokens de salida por llamada, medidos${batch ? ' · Batch API' : ''}`,
573
+ usageLineMeasuredPeriod: (calls, days, outputTokens, batch) =>
574
+ `${calls} llamadas medidas${days === null ? ' (el registro no tiene reloj)' : ` en ${days} días`} · ${outputTokens} tokens de salida por llamada, medidos${batch ? ' · Batch API' : ''}`,
575
+ measuredModelShare: (model, share, count) =>
576
+ `Esta etiqueta corrió en ${count} modelos; las cifras usan ${model}, que llevó el ${share} de su gasto.`,
577
+ measuredNoOutput: () =>
578
+ 'Ninguna llamada de este corte registró tokens de salida, así que la mitad de salida de cada cifra de abajo es $0 medido — no $0 supuesto.',
579
+ perPeriodSaving: (saving, pct) => `ahorro de ${saving} en el periodo medido (${pct}%)`,
580
+ periodNotScaled: (days) =>
581
+ days === null
582
+ ? 'Sin escalar a un mes: el registro no tiene reloj, así que no hay ritmo que escalar. Estas cifras cubren exactamente las llamadas medidas.'
583
+ : `Sin escalar a un mes: ${days} días queda por debajo de la semana que un escalado necesita — menos de un ciclo semanal multiplica la parte del ciclo que pilló. Estas cifras cubren exactamente el periodo medido.`,
522
584
  perMonthSaving: (saving, pct) => `ahorro ${saving}/mes (${pct}%)`,
523
585
  beyondShortening: () => 'Además de acortar el prompt',
524
586
  biggestLever: () => 'Empieza por aquí:',
@@ -1193,6 +1255,31 @@ ${bold('EJEMPLOS')}
1193
1255
  'Una ✗ no es un defecto del registro; es un hallazgo que este registro aún no puede sostener. La receta de registro del README lleva todos los campos de arriba.',
1194
1256
  dryRunNoGates: () =>
1195
1257
  '--dry-run no produce factura, así que un gate a su lado saldría en verde sin haber juzgado nada. Corre los gates sin --dry-run.',
1258
+ bySourceNeedsConfig: () =>
1259
+ '--by-source lee el bloque "sources" de trazum.config.json — un nombre por servicio, cada uno con patrones glob sobre rutas de registros — y esta config no tiene ninguno. Nombra al menos una fuente.',
1260
+ bySourceNothingMatched: (sources) =>
1261
+ 'Ningún fichero de registro coincidió con ningún patrón de fuente. Las fuentes configuradas: ${sources}. Los patrones casan con las rutas tal como se dan en la línea de comandos.'.replace('${sources}', sources),
1262
+ fleetHeading: (count, total, calls) => `La flota: ${count} fuentes · ${total} · ${calls}`,
1263
+ fleetRow: (name, usd, share, calls, span) => `${name} ${usd} ${share} de la flota · ${calls} · ${span}`,
1264
+ fleetSpan: (days) => `${days} días`,
1265
+ fleetNoClock: () => 'sin reloj',
1266
+ fleetWorst: (name, usd, share) =>
1267
+ `${name} es donde está el dinero: ${usd}, el ${share} del total de la flota.`,
1268
+ fleetMismatchedSpans: () =>
1269
+ 'Estas fuentes cubren periodos distintos, así que los porcentajes de arriba comparan totales, no ritmos — un registro de 3 días parece barato junto a uno de 30 por motivos que nada tienen que ver con el coste. Cada fila indica su propio periodo.',
1270
+ fleetSplitBrain: (label, detail) =>
1271
+ `La misma carga corre en modelos distintos en fuentes distintas — ${label}: ${detail}. Mismo trabajo, tarifas distintas; si es una decisión o un accidente no está en los registros.`,
1272
+ fleetCacheUnderwater: (name, usd) =>
1273
+ `La caché es rentable para la flota en conjunto pero pierde ${usd} en ${name} — el veredicto agregado lo escondía.`,
1274
+ fleetUnmatched: (file) =>
1275
+ `${file} no coincidió con ningún patrón de fuente, así que no está en ningún informe de arriba — gasto ausente de todas las facturas hasta que un patrón lo cubra.`,
1276
+ fleetFooter: () =>
1277
+ 'Resúmenes por fuente; el informe completo de un servicio es "trazum profile <sus registros>". Mismos umbrales, mismos hallazgos, una fuente cada vez.',
1278
+ fleetBudgetOk: (name, usd, max) => `Dentro de presupuesto: ${name} gastó ${usd} contra su ${max} en spend.bySource.`,
1279
+ fleetBudgetFailed: (name, usd, max) =>
1280
+ `FALLÓ — ${name} gastó ${usd} contra su presupuesto de ${max} en spend.bySource. El total de la flota puede estar bien mientras un servicio sangra; este gate nombra cuál.`,
1281
+ fleetBudgetMissing: (name) =>
1282
+ `${name} tiene presupuesto en spend.bySource y ningún registro coincidió con él en esta ejecución, así que no se midió nada. No es un aprobado: un servicio que no apareció no es un servicio dentro de presupuesto.`,
1196
1283
  coverageHeading: () => 'Lo que este registro todavía no puede responder',
1197
1284
  needsLabel: (seen) =>
1198
1285
  `"label" en ${seen} registros: sin él todas las cargas son una sola fila, así que no hay gasto por carga, ni zoom, y las palancas describen una mezcla en vez de una decisión.`,
package/src/i18n/types.ts CHANGED
@@ -37,6 +37,13 @@ export interface CliMessages {
37
37
  optionNeedsValue(name: string): string;
38
38
  mustBeNonNegative(name: string, raw: string): string;
39
39
  badLevel(received: string): string;
40
+ /** `--from-log`'s refusals: contradiction, missing label, ambiguity, emptiness. */
41
+ allLabelsNeedsLog(): string;
42
+ allLabelsNeedsMap(): string;
43
+ fromLogConflict(flag: string): string;
44
+ fromLogNeedsLabel(available: string): string;
45
+ fromLogAmbiguousLabel(target: string, labels: string): string;
46
+ fromLogLabelEmpty(label: string, available: string): string;
40
47
  unknownRuleInDisable(id: string): string;
41
48
  unknownCommand(command: string): string;
42
49
  unknownFlag(name: string, allowed: string): string;
@@ -82,6 +89,28 @@ export interface CliMessages {
82
89
  llmRejected(reason: string): string;
83
90
  costWith(modelName: string): string;
84
91
  usageLine(calls: string, outputTokens: number, batch: boolean): string;
92
+ /**
93
+ * `--from-log`: the usage line names its provenance. Measured and typed
94
+ * are different claims about the same multiplication, and under the week
95
+ * floor nothing says "month".
96
+ */
97
+ /**
98
+ * `--all-labels`: every mapped prompt against its own measured traffic,
99
+ * ranked by what the change is worth, with both coverage mismatches named.
100
+ */
101
+ allLabelsHeading(count: string): string;
102
+ allLabelsRow(saving: string): string;
103
+ allLabelsRowPeriod(saving: string): string;
104
+ allLabelsFooter(): string;
105
+ allLabelsUnmapped(label: string, usd: string): string;
106
+ allLabelsDead(label: string, path: string): string;
107
+ allLabelsUnreadable(label: string, path: string): string;
108
+ usageLineMeasured(calls: string, days: string, scaled: string, outputTokens: number, batch: boolean): string;
109
+ usageLineMeasuredPeriod(calls: string, days: string | null, outputTokens: number, batch: boolean): string;
110
+ measuredModelShare(model: string, share: string, count: string): string;
111
+ measuredNoOutput(): string;
112
+ perPeriodSaving(saving: string, pct: string): string;
113
+ periodNotScaled(days: string | null): string;
85
114
  perMonthSaving(saving: string, pct: string): string;
86
115
  beyondShortening(): string;
87
116
  biggestLever(): string;
@@ -946,6 +975,26 @@ export interface CliMessages {
946
975
  dryRunNoCacheTraffic(): string;
947
976
  dryRunFooter(): string;
948
977
  dryRunNoGates(): string;
978
+ /**
979
+ * `--by-source`: the fleet. One summary per service, the rollup naming
980
+ * the worst offender, cross-source findings a merged bill cannot make,
981
+ * and per-source budgets that fail naming the service.
982
+ */
983
+ bySourceNeedsConfig(): string;
984
+ bySourceNothingMatched(sources: string): string;
985
+ fleetHeading(count: string, total: string, calls: string): string;
986
+ fleetRow(name: string, usd: string, share: string, calls: string, span: string): string;
987
+ fleetSpan(days: string): string;
988
+ fleetNoClock(): string;
989
+ fleetWorst(name: string, usd: string, share: string): string;
990
+ fleetMismatchedSpans(): string;
991
+ fleetSplitBrain(label: string, detail: string): string;
992
+ fleetCacheUnderwater(name: string, usd: string): string;
993
+ fleetUnmatched(file: string): string;
994
+ fleetFooter(): string;
995
+ fleetBudgetOk(name: string, usd: string, max: string): string;
996
+ fleetBudgetFailed(name: string, usd: string, max: string): string;
997
+ fleetBudgetMissing(name: string): string;
949
998
  coverageHeading(): string;
950
999
  needsLabel(seen: string): string;
951
1000
  needsSession(seen: string): string;