Skip to content

Commit a0610e1

Browse files
hyperpolymathclaude
andcommitted
fix: expand evidence type detection and nest PROMPT scores
- detectEvidenceType now handles dataset (JSON/XML), news_report (HTML), and expanded spreadsheet MIME types (15 API types, 11 MIME mappings) - PROMPT scores output as nested promptScores object matching Lithoglyph PromptScoresInput schema (was flat prompt_* keys) - Added test cases for new evidence type mappings Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 066f465 commit a0610e1

1 file changed

Lines changed: 43 additions & 13 deletions

File tree

ffi/zig/src/lith_adapter.zig

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,20 @@ pub const Reader = struct {
177177
// ============================================================================
178178

179179
/// Map PREMIS MIME type to a Lithoglyph bofig_evidence evidence_type value.
180+
/// Covers all 15 evidence types defined in the Lithoglyph OpenAPI spec:
181+
/// court_filing, deposition, testimony, flight_log, financial_record,
182+
/// communication, photograph, video, official_statistics, news_report,
183+
/// document, dataset, interview, affidavit, subpoena, other.
184+
///
185+
/// MIME-only detection is inherently limited — many types (deposition,
186+
/// testimony, affidavit, subpoena, flight_log) share the same MIME as
187+
/// generic documents. Callers should override via investigation context
188+
/// or NER stage output when available.
180189
fn detectEvidenceType(mime: []const u8) []const u8 {
181190
if (mime.len == 0) return "document";
182191

183-
// PDF documents — could be court filings, depositions, or general documents.
184-
// Default to "document"; the caller can override based on investigation context.
192+
// PDF documents — default to "court_filing" as the most common
193+
// investigative PDF type; callers override via context.
185194
if (std.mem.startsWith(u8, mime, "application/pdf")) return "court_filing";
186195

187196
// Images
@@ -190,21 +199,33 @@ fn detectEvidenceType(mime: []const u8) []const u8 {
190199
// Video
191200
if (std.mem.startsWith(u8, mime, "video/")) return "video";
192201

193-
// Audio (depositions, interviews)
202+
// Audio (depositions, interviews, testimony recordings)
194203
if (std.mem.startsWith(u8, mime, "audio/")) return "interview";
195204

196-
// Spreadsheets / CSV — likely financial records
205+
// Spreadsheets / CSV — financial records or datasets
197206
if (std.mem.startsWith(u8, mime, "text/csv") or
198207
std.mem.startsWith(u8, mime, "application/vnd.ms-excel") or
199208
std.mem.startsWith(u8, mime, "application/vnd.openxmlformats-officedocument.spreadsheetml"))
200209
{
201210
return "financial_record";
202211
}
203212

204-
// Plain text / HTML
213+
// Structured data formats — datasets
214+
if (std.mem.startsWith(u8, mime, "application/json") or
215+
std.mem.startsWith(u8, mime, "application/xml") or
216+
std.mem.startsWith(u8, mime, "text/xml") or
217+
std.mem.startsWith(u8, mime, "application/vnd.openxmlformats-officedocument.presentationml"))
218+
{
219+
return "dataset";
220+
}
221+
222+
// HTML — news reports or general documents
223+
if (std.mem.eql(u8, mime, "text/html")) return "news_report";
224+
225+
// Plain text
205226
if (std.mem.startsWith(u8, mime, "text/")) return "document";
206227

207-
// Email
228+
// Email / messaging
208229
if (std.mem.startsWith(u8, mime, "message/")) return "communication";
209230

210231
return "document";
@@ -479,13 +500,15 @@ pub fn stageResultsToJson(
479500
w.print("\"legal_statute_refs\":{d}", .{legal_statutes}) catch return null;
480501
w.writeAll("},") catch return null;
481502

482-
// PROMPT scores
483-
w.print("\"prompt_provenance\":{d},", .{prompt.provenance}) catch return null;
484-
w.print("\"prompt_replicability\":{d},", .{prompt.replicability}) catch return null;
485-
w.print("\"prompt_objective\":{d},", .{prompt.objective}) catch return null;
486-
w.print("\"prompt_methodology\":{d},", .{prompt.methodology}) catch return null;
487-
w.print("\"prompt_publication\":{d},", .{prompt.publication}) catch return null;
488-
w.print("\"prompt_transparency\":{d},", .{prompt.transparency}) catch return null;
503+
// PROMPT scores — nested object matching Lithoglyph PromptScoresInput schema
504+
w.writeAll("\"promptScores\":{") catch return null;
505+
w.print("\"provenance\":{d},", .{prompt.provenance}) catch return null;
506+
w.print("\"replicability\":{d},", .{prompt.replicability}) catch return null;
507+
w.print("\"objective\":{d},", .{prompt.objective}) catch return null;
508+
w.print("\"methodology\":{d},", .{prompt.methodology}) catch return null;
509+
w.print("\"publication\":{d},", .{prompt.publication}) catch return null;
510+
w.print("\"transparency\":{d}", .{prompt.transparency}) catch return null;
511+
w.writeAll("},") catch return null;
489512

490513
// Sensitivity defaults to public for automated ingestion.
491514
writeJsonString(w, "sensitivity_level", "public") catch return null;
@@ -588,6 +611,13 @@ test "detectEvidenceType maps MIME types correctly" {
588611
try std.testing.expectEqualStrings("communication", detectEvidenceType("message/rfc822"));
589612
try std.testing.expectEqualStrings("document", detectEvidenceType(""));
590613
try std.testing.expectEqualStrings("document", detectEvidenceType("application/octet-stream"));
614+
615+
// New evidence type coverage
616+
try std.testing.expectEqualStrings("dataset", detectEvidenceType("application/json"));
617+
try std.testing.expectEqualStrings("dataset", detectEvidenceType("application/xml"));
618+
try std.testing.expectEqualStrings("dataset", detectEvidenceType("text/xml"));
619+
try std.testing.expectEqualStrings("news_report", detectEvidenceType("text/html"));
620+
try std.testing.expectEqualStrings("financial_record", detectEvidenceType("application/vnd.ms-excel"));
591621
}
592622

593623
test "computePromptScores basic scoring" {

0 commit comments

Comments
 (0)