-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add preset selection and corpus manifest #29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
cceaa37
4df9019
1efdc8f
7353f65
1ef1aff
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -84,6 +84,7 @@ Future<Map<String, Object?>> buildLeaderboardExport( | |
| for (final runId in sortedRunIds) | ||
| if (runsById[runId] != null) runsById[runId]!, | ||
| ]; | ||
| final corpusManifest = _corpusManifestForRun(runsById[selected.anchorRunId]); | ||
| final taskKeys = selected.taskRuns.map(_taskKey).toSet(); | ||
| final modelKeys = selected.taskRuns | ||
| .map((taskRun) => '${taskRun.providerId}:${taskRun.modelId}') | ||
|
|
@@ -132,7 +133,7 @@ Future<Map<String, Object?>> buildLeaderboardExport( | |
| ); | ||
|
|
||
| return <String, Object?>{ | ||
| 'schemaVersion': 1, | ||
| 'schemaVersion': 2, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Publishing a freshly exported leaderboard now writes Useful? React with 👍 / 👎.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Already handled in this diff: the Svelte loader at |
||
| 'generatedAt': generatedAt.toIso8601String(), | ||
| 'benchmark': <String, Object?>{ | ||
| 'name': 'PickArena', | ||
|
|
@@ -143,6 +144,11 @@ Future<Map<String, Object?>> buildLeaderboardExport( | |
| 'evaluatorSchemaVersion': dartArenaEvaluatorSchemaVersion, | ||
| 'track': options.track, | ||
| 'dataPolicy': options.strategy.kebabName, | ||
| if (corpusManifest != null) ...{ | ||
| 'preset': corpusManifest['preset'], | ||
| 'selectedTasks': corpusManifest['tasks'], | ||
| 'corpusManifestDigestSha256': corpusManifest['digestSha256'], | ||
| }, | ||
| }, | ||
| 'source': <String, Object?>{ | ||
| 'anchorRunId': selected.anchorRunId, | ||
|
|
@@ -167,6 +173,21 @@ Future<Map<String, Object?>> buildLeaderboardExport( | |
| }; | ||
| } | ||
|
|
||
| Map<String, Object?>? _corpusManifestForRun(Run? run) { | ||
| if (run == null) return null; | ||
| final provenance = _decodeRunProvenance(run.provenanceJson); | ||
| if (provenance == null) return null; | ||
| final manifest = _objectMap( | ||
| _objectMap(provenance['config'])['corpusManifest'], | ||
| ); | ||
| if (manifest['preset'] is! String || | ||
| manifest['tasks'] is! List || | ||
| manifest['digestSha256'] is! String) { | ||
| return null; | ||
| } | ||
| return manifest; | ||
| } | ||
|
|
||
| _SelectedTaskRuns _selectTaskRuns({ | ||
| required LeaderboardExportOptions options, | ||
| required List<Run> completedRuns, | ||
|
|
@@ -188,6 +209,7 @@ _SelectedTaskRuns _selectTaskRuns({ | |
| final anchorSignature = _RunCompatibilitySignature.fromTaskRuns( | ||
| taskRunsByRunId[anchorRun.id] ?? const <TaskRun>[], | ||
| scoringSchemaVersion: anchorWeights.scoringSchemaVersion, | ||
| corpusManifestDigest: _corpusManifestDigestForRun(anchorRun), | ||
| harnessKinds: _harnessKinds( | ||
| anchorRun, | ||
| taskRunsByRunId[anchorRun.id] ?? const <TaskRun>[], | ||
|
|
@@ -202,6 +224,7 @@ _SelectedTaskRuns _selectTaskRuns({ | |
| final candidateSignature = _RunCompatibilitySignature.fromTaskRuns( | ||
| entry.value, | ||
| scoringSchemaVersion: candidateWeights.scoringSchemaVersion, | ||
| corpusManifestDigest: _corpusManifestDigestForRun(candidateRun), | ||
| harnessKinds: _harnessKinds(candidateRun, entry.value), | ||
| ); | ||
| if (!anchorSignature.isCompatibleWith(candidateSignature)) continue; | ||
|
|
@@ -1260,11 +1283,13 @@ class _RunCompatibilitySignature { | |
| required this.harnessIds, | ||
| required this.harnessKinds, | ||
| required this.scoringSchemaVersion, | ||
| required this.corpusManifestDigest, | ||
| }); | ||
|
|
||
| factory _RunCompatibilitySignature.fromTaskRuns( | ||
| List<TaskRun> taskRuns, { | ||
| required int? scoringSchemaVersion, | ||
| required String? corpusManifestDigest, | ||
| required Map<String, String> harnessKinds, | ||
| }) { | ||
| return _RunCompatibilitySignature( | ||
|
|
@@ -1283,18 +1308,21 @@ class _RunCompatibilitySignature { | |
| .toList() | ||
| ..sort()), | ||
| scoringSchemaVersion: scoringSchemaVersion, | ||
| corpusManifestDigest: corpusManifestDigest, | ||
| ); | ||
| } | ||
|
|
||
| final List<String> taskKeys; | ||
| final List<String> harnessIds; | ||
| final List<String> harnessKinds; | ||
| final int? scoringSchemaVersion; | ||
| final String? corpusManifestDigest; | ||
|
|
||
| bool isCompatibleWith(_RunCompatibilitySignature other) { | ||
| return _listEquals(taskKeys, other.taskKeys) && | ||
| _listEquals(harnessIds, other.harnessIds) && | ||
| _listEquals(harnessKinds, other.harnessKinds) && | ||
| corpusManifestDigest == other.corpusManifestDigest && | ||
| (scoringSchemaVersion == null || | ||
| other.scoringSchemaVersion == null || | ||
| scoringSchemaVersion == other.scoringSchemaVersion); | ||
|
|
@@ -1306,6 +1334,7 @@ class _RunCompatibilitySignature { | |
| _listEquals(taskKeys, other.taskKeys) && | ||
| _listEquals(harnessIds, other.harnessIds) && | ||
| _listEquals(harnessKinds, other.harnessKinds) && | ||
| corpusManifestDigest == other.corpusManifestDigest && | ||
| scoringSchemaVersion == other.scoringSchemaVersion; | ||
| } | ||
|
|
||
|
|
@@ -1315,9 +1344,15 @@ class _RunCompatibilitySignature { | |
| Object.hashAll(harnessIds), | ||
| Object.hashAll(harnessKinds), | ||
| scoringSchemaVersion, | ||
| corpusManifestDigest, | ||
| ); | ||
| } | ||
|
|
||
| String? _corpusManifestDigestForRun(Run run) { | ||
| final digest = _corpusManifestForRun(run)?['digestSha256']; | ||
| return digest is String && digest.isNotEmpty ? digest : null; | ||
| } | ||
|
|
||
| Map<String, String> _harnessKinds(Run run, List<TaskRun> taskRuns) { | ||
| final provenanceJson = run.provenanceJson; | ||
| if (provenanceJson == null || provenanceJson.trim().isEmpty) return const {}; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,7 +14,7 @@ const _requiredArtifactBundleChecksumPaths = [ | |
| ..._standardBundleFilePaths, | ||
| ]; | ||
|
|
||
| const _artifactBundleManifestSchemaVersion = 1; | ||
| const _artifactBundleManifestSchemaVersions = {1, 2}; | ||
| const _artifactBundleChecksumsSchemaVersion = 1; | ||
| const _artifactRunResultsSchemaVersion = 1; | ||
| const _taskQaSummarySchemaVersion = 1; | ||
|
|
@@ -202,6 +202,23 @@ Map<String, Object?> buildReleaseReport({ | |
| if (taskSetId == null) { | ||
| blockers.add('Leaderboard benchmark task set id metadata is missing.'); | ||
| } | ||
| final preset = _nonEmptyString(benchmark['preset']); | ||
| final corpusManifestDigest = _nonEmptyString( | ||
| benchmark['corpusManifestDigestSha256'], | ||
| ); | ||
| final selectedTasks = benchmark['selectedTasks']; | ||
| final digestIsSha256 = | ||
| corpusManifestDigest != null && | ||
| RegExp(r'^[0-9a-f]{64}$').hasMatch(corpusManifestDigest); | ||
| if (preset == null || | ||
| !digestIsSha256 || | ||
| selectedTasks is! List || | ||
| selectedTasks.isEmpty) { | ||
|
Comment on lines
+213
to
+216
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
For a release-report input with a malformed or hand-edited leaderboard, any non-empty Useful? React with 👍 / 👎.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added a 64-hex sha256 format guard on the digest here so a non-sha256 no longer passes. The deeper cross-validation (recompute manifest entries against
Comment on lines
+213
to
+216
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a leaderboard file has Useful? React with 👍 / 👎.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Valid, and deferred to #6 (the fresh-execution release gate) rather than expanding this PR. This PR's gate now requires preset + a 64-hex top-level digest + non-empty selectedTasks; the deeper per-entry validation (each selected taskId/taskVersion/taskBundleDigest matches leaderboard.tasks, plus a digest recomputed over those entries) is exactly #6's scope. In practice this only bites a hand-edited leaderboard — our own exporter emits the correct snapshot. Tracked in #6. |
||
| blockers.add( | ||
| 'Leaderboard is missing the frozen corpus manifest; run with --preset to ' | ||
| 'snapshot the corpus before an official release.', | ||
| ); | ||
| } | ||
| if (evaluatorSchemaVersion <= 0) { | ||
| blockers.add( | ||
| 'Leaderboard benchmark evaluator schema version metadata is missing.', | ||
|
|
@@ -344,7 +361,7 @@ Map<String, Object?> buildReleaseReport({ | |
| ); | ||
|
|
||
| return { | ||
| 'schemaVersion': 1, | ||
| 'schemaVersion': 2, | ||
| 'releaseId': options.releaseId, | ||
| 'generatedAt': generatedAt.toIso8601String(), | ||
| 'status': blockers.isEmpty ? 'ready' : 'blocked', | ||
|
|
@@ -362,6 +379,9 @@ Map<String, Object?> buildReleaseReport({ | |
| 'evaluatorSchemaVersion': evaluatorSchemaVersion, | ||
| 'track': benchmark['track'], | ||
| 'dataPolicy': benchmark['dataPolicy'], | ||
| 'preset': benchmark['preset'], | ||
| 'selectedTasks': benchmark['selectedTasks'], | ||
| 'corpusManifestDigestSha256': benchmark['corpusManifestDigestSha256'], | ||
|
Comment on lines
+382
to
+384
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a leaderboard was not produced from Useful? React with 👍 / 👎. |
||
| }, | ||
| 'source': { | ||
| 'anchorRunId': source['anchorRunId'], | ||
|
|
@@ -1749,7 +1769,7 @@ Map<String, Object?> _artifactBundleSummary({ | |
|
|
||
| if (schemaVersion <= 0) { | ||
| blockers.add('Run artifact bundle manifest schema version is missing.'); | ||
| } else if (schemaVersion != _artifactBundleManifestSchemaVersion) { | ||
| } else if (!_artifactBundleManifestSchemaVersions.contains(schemaVersion)) { | ||
| blockers.add( | ||
| 'Run artifact bundle manifest schema version $schemaVersion is unsupported.', | ||
| ); | ||
|
|
@@ -2016,7 +2036,7 @@ Map<String, Object?> _artifactBundleSummary({ | |
|
|
||
| final complete = | ||
| schemaVersion > 0 && | ||
| schemaVersion == _artifactBundleManifestSchemaVersion && | ||
| _artifactBundleManifestSchemaVersions.contains(schemaVersion) && | ||
| manifestRunId != null && | ||
| runIdInLeaderboardSource && | ||
| manifestTaskRunCount > 0 && | ||
|
|
@@ -6344,11 +6364,37 @@ Map<String, Object?> _taskQaSummary( | |
| 'track': entry['track'], | ||
| 'status': entry['status'], | ||
| 'failureCount': _intValue(entry['failureCount']), | ||
| ..._f2pP2pForTaskQaReport(_taskQaReportForEntry(reports, entry)), | ||
| }, | ||
| ], | ||
| }; | ||
| } | ||
|
|
||
| Map<String, Object?>? _taskQaReportForEntry( | ||
| List<Map<String, Object?>> reports, | ||
| Map<String, Object?> entry, | ||
| ) { | ||
| final key = _taskQaReportKey(entry); | ||
| if (key == null) return null; | ||
| for (final report in reports) { | ||
| if (_taskQaReportKey(report) == key) return report; | ||
| } | ||
| return null; | ||
| } | ||
|
|
||
| Map<String, Object?> _f2pP2pForTaskQaReport(Map<String, Object?>? report) { | ||
| final checks = _objectMap(report?['checks']); | ||
| final f2p = checks['baselineHiddenFailed']; | ||
| final publicPassed = checks['referencePublicPassed']; | ||
| final hiddenPassed = checks['referenceHiddenPassed']; | ||
| return { | ||
| 'f2p': f2p is bool ? f2p : null, | ||
| 'p2p': publicPassed is bool && hiddenPassed is bool | ||
| ? publicPassed && hiddenPassed | ||
| : null, | ||
| }; | ||
| } | ||
|
|
||
| Map<String, Object?> _taskQaSummaryIntegrityAudit({ | ||
| required Map<String, Object?> summary, | ||
| required Object? rawReports, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -82,7 +82,7 @@ class RunManifestV1 { | |
| final Object? provenance; | ||
|
|
||
| Map<String, Object?> toJson() => { | ||
| 'schemaVersion': 1, | ||
| 'schemaVersion': 2, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Newly exported bundles now write Useful? React with 👍 / 👎.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Already handled in this same diff: |
||
| 'generatedAt': generatedAt, | ||
| 'run': run, | ||
| 'appVersion': appVersion, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For aggregate-compatible exports this takes the corpus manifest only from the anchor run, while
selected.taskRunsmay include other runs whose compatibility was checked only by task id/version/track, harness, scoring, and weights. If a second selected run has the same task versions but a differentconfig.corpusManifest.digestSha256, the leaderboard advertises the anchor digest and selectedTasks while mixing results from another corpus; include the manifest digest in compatibility or omit/flag the manifest when selected runs disagree.Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Already covered:
_RunCompatibilitySignatureincludescorpusManifestDigest, and bothisCompatibleWithand==requirecorpusManifestDigest == other.corpusManifestDigest, so selected runs with different corpus digests are not aggregated. The advertised anchor digest therefore always matches every combined run.