Skip to content

Commit c90d270

Browse files
hyperpolymathclaude
andcommitted
feat(echidnabot+retrain): wire VeriSimDB dogfood loop end-to-end
- echidnabot check: add --slug flag + VeriSimWriter recording so ad-hoc file checks (not just webhook jobs) also populate proof_attempts - verisim_writer: fix timestamp format to milliseconds without Z suffix (ClickHouse DateTime64(3) rejects trailing Z and nanosecond precision) - retrain_from_verisim.jl: fix three syntax bugs found during live run: * @info line-continuation with subscript args → split into two @info calls * grow_vocab called with keyword arg max_vocab= → positional arg * lpad(epoch,3)/epochs string interpolation fix (was dividing String by Int) - models/: retrained artefacts from 1233 real proof_attempts rows (13 prover classes, 422-word vocab, 53.7% training accuracy) Dogfood: echidnabot verified echidna's own Lean4 ConfidenceLattice.lean (success) and Agda/Coq proofs (failure — provers not locally installed). All 4 attempts landed in ClickHouse with correct millisecond timestamps. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent bdaf6f4 commit c90d270

6 files changed

Lines changed: 741 additions & 30 deletions

File tree

echidnabot/src/main.rs

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ enum Commands {
7171

7272
/// Manually trigger a proof check
7373
Check {
74-
/// Repository in format owner/name
74+
/// Repository in format owner/name, or path to a proof file
7575
#[arg(short, long)]
7676
repo: String,
7777

@@ -82,6 +82,12 @@ enum Commands {
8282
/// Specific prover to use
8383
#[arg(short, long)]
8484
prover: Option<String>,
85+
86+
/// Repository slug for VeriSimDB recording (owner/name).
87+
/// Defaults to the repo arg when it looks like owner/name,
88+
/// otherwise "local/adhoc".
89+
#[arg(long)]
90+
slug: Option<String>,
8591
},
8692

8793
/// Show status of a repository or job
@@ -131,9 +137,10 @@ async fn main() -> Result<()> {
131137
repo,
132138
commit,
133139
prover,
140+
slug,
134141
} => {
135142
tracing::info!("Triggering check for {} at {:?}", repo, commit);
136-
check(&config, &repo, commit.as_deref(), prover.as_deref()).await
143+
check(&config, &repo, commit.as_deref(), prover.as_deref(), slug.as_deref()).await
137144
}
138145
Commands::Status { target } => {
139146
tracing::info!("Getting status for {}", target);
@@ -250,7 +257,13 @@ async fn register(config: &Config, repo: &str, platform: &str, provers: &str) ->
250257
Ok(())
251258
}
252259

253-
async fn check(config: &Config, repo: &str, commit: Option<&str>, prover: Option<&str>) -> Result<()> {
260+
async fn check(
261+
config: &Config,
262+
repo: &str,
263+
commit: Option<&str>,
264+
prover: Option<&str>,
265+
slug: Option<&str>,
266+
) -> Result<()> {
254267
let client = EchidnaClient::new(&config.echidna);
255268
let health = client.health_check().await?;
256269
tracing::info!("ECHIDNA health check: {}", if health { "ok" } else { "unhealthy" });
@@ -268,9 +281,7 @@ async fn check(config: &Config, repo: &str, commit: Option<&str>, prover: Option
268281
(None, None)
269282
};
270283

271-
let selected_prover = prover
272-
.and_then(parse_prover_arg)
273-
.or(inferred_prover);
284+
let selected_prover = prover.and_then(parse_prover_arg).or(inferred_prover);
274285

275286
if let Some(kind) = selected_prover {
276287
let status = client.prover_status(kind).await?;
@@ -283,6 +294,7 @@ async fn check(config: &Config, repo: &str, commit: Option<&str>, prover: Option
283294

284295
if let Some(content) = proof_content {
285296
let kind = selected_prover.unwrap_or(ProverKind::Metamath);
297+
let attempt_started = Utc::now();
286298
let result = client.verify_proof(kind, &content).await?;
287299
tracing::info!(
288300
"Proof result: {:?} ({} ms)",
@@ -299,6 +311,22 @@ async fn check(config: &Config, repo: &str, commit: Option<&str>, prover: Option
299311
if let Some(commit) = commit {
300312
tracing::info!("Checked commit {}", commit);
301313
}
314+
315+
// Derive slug: explicit arg > owner/name-shaped repo arg > fallback.
316+
let repo_slug = slug
317+
.map(str::to_string)
318+
.unwrap_or_else(|| {
319+
if repo.contains('/') && !repo.starts_with('/') && !repo.starts_with('.') {
320+
repo.to_string()
321+
} else {
322+
"local/adhoc".to_string()
323+
}
324+
});
325+
326+
let verisim_writer = VeriSimWriter::from_env();
327+
verisim_writer
328+
.record(&result, kind, &repo_slug, repo, attempt_started)
329+
.await;
302330
} else {
303331
tracing::warn!(
304332
"Repo '{}' is not a proof file; pass a local proof file path to run verification",

echidnabot/src/verisim_writer.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,8 @@ impl VeriSimWriter {
180180
confidence,
181181
parent_attempt_id: None,
182182
strategy_tag: "echidnabot".to_string(),
183-
started_at: started_at.to_rfc3339(),
184-
completed_at: completed_at.to_rfc3339(),
183+
started_at: started_at.format("%Y-%m-%dT%H:%M:%S%.3f").to_string(),
184+
completed_at: completed_at.format("%Y-%m-%dT%H:%M:%S%.3f").to_string(),
185185
prover_output: truncate_utf8(&result.prover_output, 8 * 1024),
186186
error_message: if result.status == ProofStatus::Verified {
187187
None

0 commit comments

Comments
 (0)