spb/autoscholar
Public
1import { z } from "zod";2import { StageKey } from "./run.js";34export const ArtifactKind = z.enum([5 "instruction",6 "manifest",7 "plan",8 "source",9 "data",10 "code",11 "result",12 "figure",13 "table",14 "manuscript",15 "pdf",16 "review",17 "provenance",18 "log",19 "checksum",20 "other",21]);22export type ArtifactKind = z.infer<typeof ArtifactKind>;2324export const ArtifactVisibility = z.enum(["private", "public"]);2526export const ArtifactDescriptor = z.object({27 path: z28 .string()29 .min(1)30 .max(512)31 .refine((p) => !p.startsWith("/") && !p.split("/").includes("..") && !p.includes("\\"), "unsafe path"),32 kind: ArtifactKind,33 sha256: z.string().regex(/^[a-f0-9]{64}$/),34 bytes: z.number().int().nonnegative(),35 contentType: z.string().max(128).default("application/octet-stream"),36 stage: StageKey,37 synthetic: z.boolean().default(false),38});39export type ArtifactDescriptor = z.infer<typeof ArtifactDescriptor>;4041/** The required mode-aware artifact structure under runs/<run-id>/ (relative paths). */42export const CONTRACT_PATHS = {43 instruction: "input/CLAUDE.md",44 manifest: "input/run.json",45 plan: "plan/research-plan.md",46 feasibility: "plan/feasibility.json",47 referencesBib: "sources/references.bib",48 sources: "sources/sources.json",49 sourceMap: "sources/source-map.json",50 dataReadme: "data/README.md",51 dataManifest: "data/manifest.json",52 codeReadme: "code/README.md",53 metrics: "results/metrics.json",54 robustness: "results/robustness.md",55 experimentLog: "results/experiment-log.jsonl",56 mainTex: "manuscript/main.tex",57 manuscriptBib: "manuscript/references.bib",58 mainPdf: "manuscript/main.pdf",59 abstract: "manuscript/abstract.md",60 metadata: "manuscript/metadata.json",61 review1: "review/review-1.md",62 revisions: "review/revisions.md",63 qaReport: "review/qa-report.json",64 events: "provenance/events.jsonl",65 runSummary: "provenance/run-summary.json",66 checksums: "provenance/checksums.sha256",67} as const;6869export const ManuscriptMetadata = z.object({70 title: z.string().min(3).max(300),71 abstract: z.string().min(50).max(5000),72 keywords: z.array(z.string().min(1).max(60)).min(2).max(12),73 discipline: z.string(),74 researchMode: z.string(),75 secondaryModes: z.array(z.string()).default([]),76 contributions: z.array(z.string()).min(1).max(8),77 methods: z.string().max(3000),78 mainResults: z.string().max(3000),79 limitations: z.string().max(3000),80 dataAvailability: z.string().max(2000).default(""),81 codeAvailability: z.string().max(2000).default(""),82 ethics: z.string().max(2000).default(""),83 synthetic: z.boolean().default(false),84 language: z.string().default("en"),85});86export type ManuscriptMetadata = z.infer<typeof ManuscriptMetadata>;8788export const SourceRecord = z.object({89 key: z.string().min(1),90 kind: z.enum(["doi", "arxiv", "pmid", "openalex", "url", "isbn", "other"]),91 identifier: z.string().min(1),92 title: z.string().min(1),93 authors: z.array(z.string()).default([]),94 year: z.number().int().optional(),95 venue: z.string().optional(),96 url: z.string().url().optional(),97 verified: z.boolean(),98 verifiedAt: z.string().datetime().optional(),99 verificationMethod: z.string().optional(),100 accessLevel: z.enum(["metadata", "abstract", "full-text"]).default("metadata"),101 notes: z.string().optional(),102});103export type SourceRecord = z.infer<typeof SourceRecord>;104105export const SourcesFile = z.object({ sources: z.array(SourceRecord) });106107export const SourceMapEntry = z.object({108 claim: z.string().min(1),109 location: z.string().optional(),110 sourceKeys: z.array(z.string()).default([]),111 artifactPaths: z.array(z.string()).default([]),112 kind: z.enum(["literature", "result", "data", "derivation", "definition"]).default("literature"),113});114export const SourceMapFile = z.object({ claims: z.array(SourceMapEntry) });115116export const FeasibilityFile = z.object({117 feasible: z.boolean(),118 researchMode: z.string(),119 secondaryModes: z.array(z.string()).default([]),120 summary: z.string(),121 restrictedActivities: z.array(z.string()).default([]),122 requiredApprovals: z.array(z.string()).default([]),123 missingInputs: z.array(z.string()).default([]),124 risks: z.array(z.string()).default([]),125 estimatedBudgetUsd: z.number().optional(),126 rejectReason: z.string().optional(),127});128export type FeasibilityFile = z.infer<typeof FeasibilityFile>;129130export const DataManifestEntry = z.object({131 name: z.string(),132 source: z.string(),133 url: z.string().optional(),134 license: z.string(),135 acquiredAt: z.string(),136 sha256: z137 .string()138 .regex(/^[a-f0-9]{64}$/)139 .optional(),140 bytes: z.number().int().optional(),141 synthetic: z.boolean(),142 transformations: z.array(z.string()).default([]),143 notes: z.string().optional(),144});145export const DataManifestFile = z.object({ datasets: z.array(DataManifestEntry) });146147export const MetricsFile = z.object({148 metrics: z.record(z.string(), z.unknown()),149 reportedValues: z150 .array(151 z.object({152 label: z.string(),153 value: z.union([z.number(), z.string()]),154 unit: z.string().optional(),155 location: z.string().optional(),156 }),157 )158 .default([]),159 synthetic: z.boolean().default(false),160});161162export const ExperimentLogEntry = z.object({163 name: z.string(),164 command: z.string(),165 startedAt: z.string(),166 endedAt: z.string(),167 exitCode: z.number().int(),168 seed: z.union([z.number(), z.string()]).optional(),169 environment: z.record(z.string(), z.string()).optional(),170 outputs: z.array(z.string()).default([]),171 synthetic: z.boolean().default(false),172});173174export const RunSummary = z.object({175 runId: z.string().uuid(),176 attemptNo: z.number().int(),177 researchMode: z.string(),178 stagesCompleted: z.array(z.string()),179 costUsd: z.number(),180 turns: z.number().int(),181 model: z.string(),182 reviewerModel: z.string(),183 workerName: z.string(),184 startedAt: z.string(),185 endedAt: z.string(),186 sdkVersion: z.string(),187 toolchain: z.record(z.string(), z.string()).default({}),188 synthetic: z.boolean().default(false),189});190export type RunSummary = z.infer<typeof RunSummary>;191