@dailephd/my-dev-kit-lab 0.9.1 → 0.9.3

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.
Files changed (53) hide show
  1. package/CHANGELOG.md +19 -2
  2. package/README.md +10 -2
  3. package/dist/src/agents/adapters/codexAdapter.js +4 -1
  4. package/dist/src/cli/help.js +38 -2
  5. package/dist/src/cli/runLabCli.js +9 -1
  6. package/dist/src/commands/buildGalleryCommand.js +16 -3
  7. package/dist/src/commands/runComparePromptsCommand.js +109 -0
  8. package/dist/src/commands/runExperimentRunCommand.js +51 -5
  9. package/dist/src/core/processTree.js +41 -17
  10. package/dist/src/core/runMeasuredCommand.js +14 -8
  11. package/dist/src/experiments/plugins/agentSuccessRate/campaignCheckpointStore.js +24 -2
  12. package/dist/src/experiments/plugins/agentSuccessRate/campaignExecution.js +7 -2
  13. package/dist/src/experiments/plugins/agentSuccessRate/campaignIdentity.js +29 -4
  14. package/dist/src/experiments/plugins/agentSuccessRate/campaignProgress.js +4 -2
  15. package/dist/src/experiments/plugins/agentSuccessRate/campaignResumableExecution.js +1 -1
  16. package/dist/src/experiments/plugins/agentSuccessRate/config.js +47 -2
  17. package/dist/src/experiments/plugins/agentSuccessRate/plugin.js +4 -2
  18. package/dist/src/experiments/plugins/agentSuccessRate/promptContract.js +121 -0
  19. package/dist/src/experiments/plugins/agentSuccessRate/realAgentExecution.js +32 -2
  20. package/dist/src/experiments/plugins/agentSuccessRate/realAgentPrompt.js +105 -11
  21. package/dist/src/experiments/plugins/agentSuccessRate/strictDiffResponse.js +312 -0
  22. package/dist/src/gallery/galleryPathSafety.js +111 -0
  23. package/dist/src/gallery/readGallerySources.js +542 -0
  24. package/dist/src/gallery/writeGalleryManifest.js +57 -3
  25. package/dist/src/report/experiments/buildPluginExperimentReport.js +4 -16
  26. package/dist/src/report/experiments/htmlSafety.js +32 -0
  27. package/dist/src/report/experiments/metricEvidence.js +389 -0
  28. package/dist/src/report/experiments/metricGlossary.js +227 -0
  29. package/dist/src/report/experiments/metricGlossaryCatalog.js +199 -0
  30. package/dist/src/report/experiments/promptTemplateComparisonEvidence.js +377 -0
  31. package/dist/src/report/experiments/promptTemplateComparisonModel.js +436 -0
  32. package/dist/src/report/experiments/renderPluginExperimentReportHtml.js +158 -64
  33. package/dist/src/report/experiments/renderPluginExperimentReportText.js +22 -677
  34. package/dist/src/report/experiments/renderPromptTemplateComparison.js +192 -0
  35. package/dist/src/report/experiments/renderSpecializedTextSections.js +633 -0
  36. package/dist/src/report/experiments/reportSectionRegistry.js +79 -0
  37. package/dist/src/report/experiments/specializedReportSections.js +142 -0
  38. package/dist/src/report/experiments/writeAgentSuccessCampaignProgressReport.js +6 -2
  39. package/dist/src/report/experiments/writePluginExperimentReports.js +4 -2
  40. package/dist/src/securityValidation/attackScenarios/payloadCorpus.js +0 -0
  41. package/dist/src/securityValidation/attackScenarios/scenarios/secretLeakageScenario.js +146 -133
  42. package/dist/src/securityValidation/attackScenarios/scenarios/subprocessInjectionScenario.js +54 -36
  43. package/dist/src/securityValidation/commandRunner.js +13 -6
  44. package/dist/src/securityValidation/packageChecks/parseNpmPackDryRun.js +34 -4
  45. package/dist/src/securityValidation/packageChecks/requiredPackageContents.js +106 -2
  46. package/dist/src/securityValidation/packageChecks/runPackageChecks.js +31 -16
  47. package/dist/src/securityValidation/staticScans/semgrep.js +68 -64
  48. package/dist/src/securityValidation/types.js +0 -4
  49. package/dist/src/securityValidation/validate/runSecurityValidation.js +1 -1
  50. package/docs/METRICS.md +12 -2
  51. package/examples/tutorial-browser/prepare.mjs +13 -13
  52. package/examples/tutorial-browser/server.mjs +13 -13
  53. package/package.json +1 -1
@@ -0,0 +1,32 @@
1
+ // Context-correct HTML helpers for the generic static report. Text escaping and link validation are separate
2
+ // concerns: escaping alone never makes a URL safe, so every emitted href is validated here independently.
3
+ export function escapeHtml(value) {
4
+ return String(value ?? "")
5
+ .replaceAll("&", "&")
6
+ .replaceAll("<", "&lt;")
7
+ .replaceAll(">", "&gt;")
8
+ .replaceAll('"', "&quot;")
9
+ .replaceAll("'", "&#39;");
10
+ }
11
+ const SAFE_ANCHOR_ID = /^[a-z][a-z0-9-]{0,127}$/;
12
+ /** True only for a plain lowercase in-document anchor id that this renderer generated. */
13
+ export function isSafeAnchorId(value) {
14
+ return typeof value === "string" && SAFE_ANCHOR_ID.test(value);
15
+ }
16
+ /**
17
+ * Returns an href that is safe to emit, or null. Only in-document fragment links to a safe anchor id are
18
+ * permitted: no scheme-bearing URL (javascript:, data:, file:, http:, ...) and no filesystem path is ever linked.
19
+ */
20
+ export function safeInternalHref(value) {
21
+ if (typeof value !== "string" || !value.startsWith("#"))
22
+ return null;
23
+ return isSafeAnchorId(value.slice(1)) ? value : null;
24
+ }
25
+ /** Derives a safe, lowercase section anchor id from a registry/descriptor identifier. */
26
+ export function sectionAnchorId(identifier) {
27
+ const slug = identifier
28
+ .toLowerCase()
29
+ .replace(/[^a-z0-9]+/g, "-")
30
+ .replace(/^-+|-+$/g, "");
31
+ return `section-${slug || "unnamed"}`;
32
+ }
@@ -0,0 +1,389 @@
1
+ // Report-presentation projection of metric evidence. It reads an already built PluginExperimentReport and
2
+ // produces display views and deterministic caveats. It never recalculates a scientific value, never converts
3
+ // unavailable or not-applicable evidence to zero, and never mutates its input. Provenance and reliability are
4
+ // taken only from evidence the report carries; anything else stays explicitly `unknown`.
5
+ import { RAW_FULL_FILE_VARIANT_ID, WARM_INDEX_REUSE_VARIANT_ID } from "../../experiments/plugins/warmIndexReuse/plugin.js";
6
+ import { attemptEvidenceOf } from "../../experiments/plugins/agentSuccessRate/attemptEvidence.js";
7
+ import { pluginLocalMetricId, resolveMetricDescriptor, } from "./metricGlossary.js";
8
+ const KIND_ORDER = [
9
+ "metric-unavailable",
10
+ "metric-not-applicable",
11
+ "telemetry-partial",
12
+ "telemetry-provenance-unknown",
13
+ "telemetry-reliability-low",
14
+ "telemetry-reliability-unknown",
15
+ "estimated-not-provider-usage",
16
+ "glossary-missing",
17
+ ];
18
+ /** Collects per-attempt telemetry already recorded in agent-success execution evidence. Pure; no I/O. */
19
+ export function collectMetricReportEvidence(run) {
20
+ // Only the agent-success-rate plugin records per-attempt token telemetry in this shape.
21
+ if (run.pluginId !== "agent-success-rate")
22
+ return {};
23
+ const cases = run.caseExecutionEvidence;
24
+ if (!Array.isArray(cases))
25
+ return {};
26
+ const attempts = [];
27
+ for (const entry of cases) {
28
+ if (!entry || !Array.isArray(entry.treatments))
29
+ continue;
30
+ for (const treatment of entry.treatments) {
31
+ attemptEvidenceOf(treatment).forEach((evidence, index) => {
32
+ const usage = evidence.agentTokenUsage;
33
+ attempts.push({
34
+ caseId: entry.caseId,
35
+ treatmentId: treatment.treatmentId,
36
+ attemptNumber: index + 1,
37
+ providerInvoked: evidence.realAgent?.providerInvoked === true,
38
+ tokenSource: usage ? usage.source : null,
39
+ tokenReliability: usage ? usage.reliability : null,
40
+ totalTokensAvailable: usage !== null && typeof usage.totalTokens === "number"
41
+ });
42
+ });
43
+ }
44
+ }
45
+ return { agentSuccessAttempts: attempts };
46
+ }
47
+ const MAX_LISTED = 10;
48
+ const MAX_REASONS = 3;
49
+ const AGENT_SUCCESS_PREFIX = "agent-success-rate.";
50
+ const DESCRIPTION_PATTERN = /^(available|unavailable|not-applicable)(?::\s*([\s\S]*))?$/;
51
+ function provenanceOfTokenSource(source) {
52
+ switch (source) {
53
+ case "provider-reported":
54
+ return "provider-reported";
55
+ case "agent-reported":
56
+ case "cli-json":
57
+ return "agent-reported";
58
+ case "estimated-from-text":
59
+ return "estimated";
60
+ default:
61
+ // "otel" is unattributed telemetry and "unavailable" carries no source: neither is assumed.
62
+ return "unknown";
63
+ }
64
+ }
65
+ function reliabilityOf(value) {
66
+ return value === "high" || value === "medium" || value === "low" || value === "unavailable" ? value : "unknown";
67
+ }
68
+ function basisProvenance(descriptor) {
69
+ switch (descriptor?.measurementBasis) {
70
+ case "measured":
71
+ return "measured";
72
+ case "estimated":
73
+ return "estimated";
74
+ case "derived":
75
+ case "verification-verdict":
76
+ case "answer-key-set-measure":
77
+ return "derived";
78
+ default:
79
+ return "unknown";
80
+ }
81
+ }
82
+ function isTokenTelemetry(descriptor) {
83
+ return descriptor?.measurementBasis === "agent-token-telemetry";
84
+ }
85
+ function telemetryKey(variantId, caseId) {
86
+ return `${variantId ?? ""}\u0000${caseId ?? ""}`;
87
+ }
88
+ /** Per variant/case token telemetry that the warm-index report already carries. */
89
+ function warmIndexTelemetry(report) {
90
+ const result = new Map();
91
+ for (const project of report.warmIndexReuse?.projects ?? []) {
92
+ for (const task of project.tasks) {
93
+ for (const [variantId, agent] of [
94
+ [RAW_FULL_FILE_VARIANT_ID, task.rawAgent],
95
+ [WARM_INDEX_REUSE_VARIANT_ID, task.warmAgent],
96
+ ]) {
97
+ if (!agent)
98
+ continue;
99
+ result.set(telemetryKey(variantId, task.caseId), {
100
+ provenance: provenanceOfTokenSource(agent.tokenUsageSource),
101
+ reliability: reliabilityOf(agent.tokenUsageReliability),
102
+ });
103
+ }
104
+ }
105
+ }
106
+ return result;
107
+ }
108
+ function commonValue(values, unknownValue) {
109
+ if (values.length === 0)
110
+ return unknownValue;
111
+ const first = values[0];
112
+ return values.every((value) => value === first) ? first : unknownValue;
113
+ }
114
+ /**
115
+ * Aggregate telemetry across contributing measurements. Provenance and reliability are attributed only when every
116
+ * contributor is known and identical; any missing or differing contributor leaves the aggregate unknown.
117
+ */
118
+ function aggregateTelemetry(parts) {
119
+ if (parts.length === 0 || parts.some((part) => part === null))
120
+ return { provenance: "unknown", reliability: "unknown" };
121
+ const known = parts;
122
+ const provenance = commonValue(known.map((part) => part.provenance), "unknown");
123
+ const reliability = commonValue(known.map((part) => part.reliability), "unknown");
124
+ return { provenance, reliability };
125
+ }
126
+ /** Cumulative warm-index token telemetry per variant/case: the strict prefix of tasks 1..N in the project. */
127
+ function warmIndexCumulativeTelemetry(report) {
128
+ const result = new Map();
129
+ for (const project of report.warmIndexReuse?.projects ?? []) {
130
+ const tasks = [...project.tasks].sort((a, b) => a.taskOrdinal - b.taskOrdinal);
131
+ for (const [variantId, pick] of [
132
+ [RAW_FULL_FILE_VARIANT_ID, (task) => task.rawAgent],
133
+ [WARM_INDEX_REUSE_VARIANT_ID, (task) => task.warmAgent]
134
+ ]) {
135
+ const parts = [];
136
+ for (const task of tasks) {
137
+ const agent = pick(task);
138
+ parts.push(agent ? { provenance: provenanceOfTokenSource(agent.tokenUsageSource), reliability: reliabilityOf(agent.tokenUsageReliability) } : null);
139
+ result.set(telemetryKey(variantId, task.caseId), aggregateTelemetry(parts));
140
+ }
141
+ }
142
+ }
143
+ return result;
144
+ }
145
+ function agentSuccessTelemetry(localId, caseId, variantId, evidence) {
146
+ if (!evidence?.agentSuccessAttempts || caseId === null || variantId === null)
147
+ return null;
148
+ const attempts = evidence.agentSuccessAttempts
149
+ .filter((attempt) => attempt.caseId === caseId && attempt.treatmentId === variantId)
150
+ .sort((a, b) => a.attemptNumber - b.attemptNumber);
151
+ if (attempts.length === 0)
152
+ return null;
153
+ const one = (attempt) => attempt && attempt.providerInvoked && attempt.totalTokensAvailable && attempt.tokenSource !== null
154
+ ? { provenance: provenanceOfTokenSource(attempt.tokenSource), reliability: reliabilityOf(attempt.tokenReliability) }
155
+ : null;
156
+ switch (localId) {
157
+ case "firstAttemptProviderTokens":
158
+ return one(attempts[0]);
159
+ case "agentTotalTokens":
160
+ case "finalAttemptProviderTokens":
161
+ return one(attempts[attempts.length - 1]);
162
+ case "totalProviderTokens":
163
+ // Cumulative over the attempts that actually ran provider processes.
164
+ return aggregateTelemetry(attempts.filter((attempt) => attempt.providerInvoked).map(one));
165
+ default:
166
+ return null;
167
+ }
168
+ }
169
+ function warmUnavailableAgentTokenViews(report, telemetry) {
170
+ const pluginId = report.plugin.id;
171
+ const descriptor = resolveMetricDescriptor(pluginId, "agent-total-tokens");
172
+ const views = [];
173
+ for (const project of report.warmIndexReuse?.projects ?? []) {
174
+ for (const task of project.tasks) {
175
+ for (const [variantId, metric] of [
176
+ [RAW_FULL_FILE_VARIANT_ID, task.raw?.agentTotalTokens],
177
+ [WARM_INDEX_REUSE_VARIANT_ID, task.warm?.agentTotalTokens],
178
+ ]) {
179
+ const measurement = metric;
180
+ if (!measurement || measurement.availability === "available")
181
+ continue;
182
+ const known = telemetry.get(telemetryKey(variantId, task.caseId));
183
+ views.push({
184
+ metricId: "agent-total-tokens",
185
+ pluginId,
186
+ displayName: descriptor?.displayName ?? "Agent total tokens",
187
+ value: null,
188
+ unit: measurement.unit ?? null,
189
+ availability: measurement.availability,
190
+ reason: measurement.reason,
191
+ provenance: known?.provenance ?? "unknown",
192
+ reliability: known?.reliability ?? "unknown",
193
+ variantId,
194
+ caseId: task.caseId,
195
+ glossaryAnchor: descriptor?.anchor ?? null,
196
+ });
197
+ }
198
+ }
199
+ }
200
+ return views;
201
+ }
202
+ /** Builds one evidence view per rendered metric, preserving report order. Pure; never mutates the report. */
203
+ export function buildMetricEvidenceViews(report, evidence) {
204
+ const pluginId = report.plugin.id;
205
+ const telemetry = warmIndexTelemetry(report);
206
+ const cumulative = warmIndexCumulativeTelemetry(report);
207
+ const views = report.metrics.map((metric) => {
208
+ const descriptor = resolveMetricDescriptor(pluginId, metric.id);
209
+ const parsed = metric.id.startsWith(AGENT_SUCCESS_PREFIX) && metric.description ? DESCRIPTION_PATTERN.exec(metric.description) : null;
210
+ let availability = metric.value === null ? "unavailable" : "available";
211
+ let reason = null;
212
+ if (parsed) {
213
+ availability = parsed[1];
214
+ reason = parsed[2] !== undefined && parsed[2].trim() !== "" ? parsed[2].trim() : null;
215
+ if (availability === "available")
216
+ reason = null;
217
+ }
218
+ const localId = pluginLocalMetricId(pluginId, metric.id);
219
+ const key = telemetryKey(metric.variantId ?? null, metric.caseId ?? null);
220
+ const tokenMetric = isTokenTelemetry(descriptor);
221
+ const known = !tokenMetric
222
+ ? null
223
+ : pluginId === "agent-success-rate"
224
+ ? agentSuccessTelemetry(localId, metric.caseId ?? null, metric.variantId ?? null, evidence)
225
+ : localId.startsWith("cumulative-")
226
+ ? cumulative.get(key)
227
+ : telemetry.get(key);
228
+ return {
229
+ metricId: metric.id,
230
+ pluginId,
231
+ displayName: descriptor?.displayName ?? metric.name,
232
+ value: metric.value,
233
+ unit: metric.unit ?? descriptor?.unit ?? null,
234
+ availability,
235
+ reason,
236
+ provenance: tokenMetric ? (known ? known.provenance : "unknown") : basisProvenance(descriptor),
237
+ reliability: tokenMetric && known ? known.reliability : "unknown",
238
+ variantId: metric.variantId ?? null,
239
+ caseId: metric.caseId ?? null,
240
+ glossaryAnchor: descriptor?.anchor ?? null,
241
+ };
242
+ });
243
+ return [...views, ...warmUnavailableAgentTokenViews(report, telemetry)];
244
+ }
245
+ function groupByMetric(views) {
246
+ const groups = new Map();
247
+ for (const view of views) {
248
+ const key = `${view.pluginId}\u0000${view.metricId}`;
249
+ const group = groups.get(key) ?? { pluginId: view.pluginId, metricId: view.metricId, displayName: view.displayName, views: [] };
250
+ group.views.push(view);
251
+ groups.set(key, group);
252
+ }
253
+ return [...groups.values()];
254
+ }
255
+ function boundedList(values, limit) {
256
+ const sorted = values.map((value) => value.replace(/[.s]+$/, "")).sort();
257
+ const shown = sorted.slice(0, limit).join("; ");
258
+ return sorted.length > limit ? `${shown}; and ${sorted.length - limit} more` : shown;
259
+ }
260
+ function label(group) {
261
+ return `"${group.displayName}" (${group.metricId})`;
262
+ }
263
+ /**
264
+ * Deterministic, de-duplicated caveats derived from the views and from evidence the report already carries.
265
+ * Caveats supplement the report's own warnings and never change a scientific conclusion.
266
+ */
267
+ export function buildMetricEvidenceCaveats(report, views) {
268
+ const byId = new Map();
269
+ const add = (caveat) => {
270
+ if (!byId.has(caveat.id))
271
+ byId.set(caveat.id, caveat);
272
+ };
273
+ for (const group of groupByMetric(views)) {
274
+ const total = group.views.length;
275
+ const descriptor = resolveMetricDescriptor(group.pluginId, group.metricId);
276
+ const base = { pluginId: group.pluginId, metricId: group.metricId };
277
+ const unavailable = group.views.filter((view) => view.availability === "unavailable");
278
+ if (unavailable.length > 0) {
279
+ const reasons = [...new Set(unavailable.map((view) => view.reason).filter((reason) => reason !== null))];
280
+ add({
281
+ ...base,
282
+ id: `metric-unavailable:${group.pluginId}:${group.metricId}`,
283
+ kind: "metric-unavailable",
284
+ severity: "warning",
285
+ text: `${label(group)} is unavailable for ${unavailable.length} of ${total} measurement(s); unavailable is not zero.` +
286
+ (reasons.length > 0 ? ` Recorded reason(s): ${boundedList(reasons, MAX_REASONS)}.` : " No reason was recorded."),
287
+ });
288
+ }
289
+ const notApplicable = group.views.filter((view) => view.availability === "not-applicable");
290
+ if (notApplicable.length > 0) {
291
+ const reasons = [...new Set(notApplicable.map((view) => view.reason).filter((reason) => reason !== null))];
292
+ add({
293
+ ...base,
294
+ id: `metric-not-applicable:${group.pluginId}:${group.metricId}`,
295
+ kind: "metric-not-applicable",
296
+ severity: "info",
297
+ text: `${label(group)} is not applicable for ${notApplicable.length} of ${total} measurement(s); this is not a zero or a failure.` +
298
+ (reasons.length > 0 ? ` Recorded reason(s): ${boundedList(reasons, MAX_REASONS)}.` : " No reason was recorded."),
299
+ });
300
+ }
301
+ const estimated = group.views.filter((view) => view.provenance === "estimated" && view.availability === "available");
302
+ if (estimated.length > 0) {
303
+ add({
304
+ ...base,
305
+ id: `estimated-not-provider-usage:${group.pluginId}:${group.metricId}`,
306
+ kind: "estimated-not-provider-usage",
307
+ severity: "info",
308
+ text: `${label(group)} is an estimate; it is not provider-reported usage and must not be compared to provider token totals.`,
309
+ });
310
+ }
311
+ if (isTokenTelemetry(descriptor)) {
312
+ const available = group.views.filter((view) => view.availability === "available");
313
+ if (available.some((view) => view.provenance === "unknown")) {
314
+ add({
315
+ ...base,
316
+ id: `telemetry-provenance-unknown:${group.pluginId}:${group.metricId}`,
317
+ kind: "telemetry-provenance-unknown",
318
+ severity: "warning",
319
+ text: `${label(group)}: the token telemetry source and reliability are not recorded in this report; the value is neither assumed provider-reported nor estimated.`,
320
+ });
321
+ }
322
+ else if (available.some((view) => view.reliability === "unknown")) {
323
+ add({
324
+ ...base,
325
+ id: `telemetry-reliability-unknown:${group.pluginId}:${group.metricId}`,
326
+ kind: "telemetry-reliability-unknown",
327
+ severity: "warning",
328
+ text: `${label(group)}: the token telemetry reliability is not recorded in this report.`,
329
+ });
330
+ }
331
+ const weak = group.views.filter((view) => view.reliability === "low" || view.reliability === "unavailable");
332
+ if (weak.length > 0) {
333
+ const levels = [...new Set(weak.map((view) => view.reliability))].sort().join(", ");
334
+ add({
335
+ ...base,
336
+ id: `telemetry-reliability-low:${group.pluginId}:${group.metricId}`,
337
+ kind: "telemetry-reliability-low",
338
+ severity: "warning",
339
+ text: `${label(group)}: ${weak.length} of ${total} measurement(s) carry ${levels} telemetry reliability; interpret token comparisons cautiously.`,
340
+ });
341
+ }
342
+ }
343
+ }
344
+ const tokenStatus = report.warmIndexReuse?.agentCampaign?.tokenEvidenceStatus;
345
+ if (tokenStatus === "partial" || tokenStatus === "unavailable") {
346
+ add({
347
+ pluginId: report.plugin.id,
348
+ metricId: null,
349
+ id: `telemetry-partial:${report.plugin.id}`,
350
+ kind: "telemetry-partial",
351
+ severity: "warning",
352
+ text: tokenStatus === "partial"
353
+ ? "Token evidence for the agent campaign is partial: some agent sides reported no token total, and missing totals are not zero."
354
+ : "Token evidence for the agent campaign is unavailable: no agent side reported a token total, and missing totals are not zero.",
355
+ });
356
+ }
357
+ const pluginId = report.plugin.id;
358
+ const missing = new Set();
359
+ for (const view of views) {
360
+ if (view.glossaryAnchor === null)
361
+ missing.add(pluginLocalMetricId(pluginId, view.metricId));
362
+ }
363
+ if (missing.size > 0) {
364
+ const ids = [...missing].sort();
365
+ const shown = ids.slice(0, MAX_LISTED).join(", ");
366
+ add({
367
+ pluginId,
368
+ metricId: null,
369
+ id: `glossary-missing:${pluginId}`,
370
+ kind: "glossary-missing",
371
+ severity: "info",
372
+ text: `Glossary metadata is missing for ${ids.length} rendered metric(s): ${shown}` +
373
+ (ids.length > MAX_LISTED ? `, and ${ids.length - MAX_LISTED} more` : "") +
374
+ ". They are shown without a definition or glossary link.",
375
+ });
376
+ }
377
+ return [...byId.values()].sort((a, b) => {
378
+ const rank = KIND_ORDER.indexOf(a.kind) - KIND_ORDER.indexOf(b.kind);
379
+ if (rank !== 0)
380
+ return rank;
381
+ if (a.pluginId !== b.pluginId)
382
+ return a.pluginId < b.pluginId ? -1 : 1;
383
+ const am = a.metricId ?? "";
384
+ const bm = b.metricId ?? "";
385
+ if (am !== bm)
386
+ return am < bm ? -1 : 1;
387
+ return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
388
+ });
389
+ }