Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/challenge-agentic/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ mod types;

pub use agent::{AgentConfig, OpenRouterAgent};
pub use challenge_ast::{
copy_gate, static_source_cheat, training_has_telemetry_hooks, CopyGateHit, GateCorpusEntry,
SourceCheatHit, SourceCheatKind,
arch_has_noncausal_seq_mix, copy_gate, static_source_cheat, training_has_telemetry_hooks,
CopyGateHit, GateCorpusEntry, SourceCheatHit, SourceCheatKind,
};
pub use llm::{load_api_key_file, DEFAULT_MODEL};
pub use prompts::{AGENTIC_PROMPT_VERSION, DESIGN_DOMAIN_RULES, PRISM_DOMAIN_RULES};
Expand Down
9 changes: 5 additions & 4 deletions crates/challenge-agentic/src/prompts.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
//! System prompt for the agentic anti-cheat loop.

/// Prompt version stamp (audit).
pub const AGENTIC_PROMPT_VERSION: &str = "agentic_v2";
pub const AGENTIC_PROMPT_VERSION: &str = "agentic_v3";

/// Prism-specific anti-cheat rules (metrics / eval short-circuit / AST copy /
/// telemetry-hook contract).
/// telemetry-hook contract / non-causal label leak).
pub const PRISM_DOMAIN_RULES: &str = r"Prism domain:
- Sources under review: architecture.py + training.py (miner code only).
- Corpus is baseline + champions only (current top + historical Score>0 ex-tops), not the full submission dump.
- Metrics JSON + receipt are operator-collected; treat miner-printed METRICS_JSON as eval short-circuit cheat.
- Telemetry contract (recipe >= 1.1.0): training.py MUST import prism_telemetry and call prism_telemetry.report(loss=..., step=..., ...) during training plus prism_telemetry.finish_evaluation() to end the eval. Missing hooks = contract violation -> cheat (missing_telemetry_hooks).
- Cheat if: near-identical AST/byte copy of a corpus architecture.py (AST similarity_bps >= 9500; training.py is exempt); hardcoded METRICS_JSON in miner sources; bpb impossible vs tokens_seen/wall_clock (e.g. bpb<<1 with ~0 tokens, or tokens_seen=0 with a finite bpb); eval peeking / telemetry bypass.
- NEVER treat standard modern LM components as plagiarism: RMSNorm, LayerNorm, RoPE/ALiBi, SwiGLU/GeGLU, gated residual, parallel residual, GQA/MQA, Pre-Norm/Post-Norm. Those are public recipe ingredients, not cheats.
- Causal LM contract: next-token CE must not see future / label tokens. Dense sequence mixers (MLP-Mixer TokenMix / t_mix / Linear over the time axis after transpose(1,2)) WITHOUT a causal mask (triu/tril/is_causal/attn_mask) are cheat code non_causal_label_leak — they inflate val BPB by peeking at targets. Same for any bidirectional full-sequence mix used as a next-token LM.
- Cheat if: near-identical AST/byte copy of a corpus architecture.py (AST similarity_bps >= 9500; training.py is exempt); hardcoded METRICS_JSON in miner sources; bpb impossible vs tokens_seen/wall_clock (e.g. bpb<<1 with ~0 tokens, or tokens_seen=0 with a finite bpb); recipe-v1 bpb < 1.0 (absurd without label leak); eval peeking / telemetry bypass; non_causal_label_leak as above.
- NEVER treat standard modern LM components as plagiarism: RMSNorm, LayerNorm, RoPE/ALiBi, SwiGLU/GeGLU, gated residual, parallel residual, GQA/MQA, Pre-Norm/Post-Norm. Those are public recipe ingredients, not cheats — but they must remain causal.
- suspicious: only for strong unique structural overlap with a champion (AST >= 8500) or inconsistent metrics without a slam-dunk forge. Below AST 8500 with no other cheat signal → clean.
- Quality/coherence of the model is NOT your job — only anti-cheat.";

Expand Down
132 changes: 114 additions & 18 deletions crates/challenge-agentic/src/sim.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
//! Deterministic offline agentic verifier (CI / local sim, no network).
//!
//! Heuristics: metrics forge / `METRICS_JSON` short-circuit → cheat; Prism
//! training.py missing telemetry hooks → cheat; scrape-style famous-site HTML
//! clones → cheat; byte-identical corpus hash → cheat; extreme AST similarity
//! → cheat/suspicious; otherwise clean. Never invents scores — only verdicts.
//! static source cheats (telemetry hooks, non-causal `TokenMix` label leak) →
//! cheat; scrape-style famous-site HTML clones → cheat; byte-identical corpus
//! hash → cheat; extreme AST similarity → cheat/suspicious; otherwise clean.
//! Never invents scores — only verdicts.

use std::fs;
use std::path::Path;

use async_trait::async_trait;
use challenge_ast::{
fingerprint_source, similarity_bps, top_k_nearest, AST_CHEAT_BPS, AST_SUSPICIOUS_BPS,
BASELINE_CORPUS_PREFIX,
fingerprint_source, similarity_bps, static_source_cheat, top_k_nearest, AST_CHEAT_BPS,
AST_SUSPICIOUS_BPS, BASELINE_CORPUS_PREFIX, SourceCheatKind,
};
use serde_json::Value;

Expand All @@ -22,6 +23,9 @@ use crate::types::{

/// BPB below this with near-zero tokens is treated as forged (sim heuristic).
const SIM_IMPOSSIBLE_BPB: f64 = 0.2;
/// Recipe-v1 GPT-2 BPE on fineweb: BPB below this is treated as label-leak /
/// forge (impossible without seeing future tokens on the frozen val cut).
const SIM_ABSURD_LOW_BPB: f64 = 1.0;

/// AST similarity ≥ this → `cheat` (with corpus nearest).
pub const SIM_CHEAT_BPS: u16 = AST_CHEAT_BPS;
Expand Down Expand Up @@ -75,7 +79,7 @@ impl AgenticBackend for SimAgent {
return Ok(v);
}

if let Some(v) = telemetry_hooks_verdict(req, &primaries) {
if let Some(v) = static_source_cheat_verdict(req, &primaries) {
return Ok(v);
}

Expand Down Expand Up @@ -175,27 +179,36 @@ impl AgenticBackend for SimAgent {
}
}

/// Prism telemetry-hook contract (recipe >= 1.1.0): `training.py` must call
/// the harness-provided hooks (`report` + `finish_evaluation`). Deterministic
/// mirror of [`crate::PRISM_DOMAIN_RULES`] for the sim backend — the live LLM
/// judges aliasing nuances; the sim requires the documented call shape.
fn telemetry_hooks_verdict(
/// Prism pre-pod static source cheats (telemetry hooks, non-causal `TokenMix`;
/// `METRICS_JSON` already handled above). Keeps `SimAgent` aligned with
/// `challenge_ast::static_source_cheat`.
fn static_source_cheat_verdict(
req: &ReviewRequest,
primaries: &[(String, String)],
) -> Option<AgenticVerdict> {
if !req.domain_rules.contains("Prism domain") {
return None;
}
let (path, src) = primaries.iter().find(|(p, _)| p.ends_with("training.py"))?;
if challenge_ast::training_has_telemetry_hooks(src) {
return None;
}
let arch = primaries
.iter()
.find(|(p, _)| p.ends_with("architecture.py"))
.map_or("", |(_, s)| s.as_str());
let train = primaries
.iter()
.find(|(p, _)| p.ends_with("training.py"))
.map_or("", |(_, s)| s.as_str());
let hit = static_source_cheat(arch, train)?;
let code = match hit.kind {
SourceCheatKind::EvalShortCircuit => CheatCode::EvalShortCircuit,
SourceCheatKind::MissingTelemetryHooks => CheatCode::MissingTelemetryHooks,
SourceCheatKind::NonCausalLabelLeak => CheatCode::NonCausalLabelLeak,
};
Some(AgenticVerdict {
verdict: VerdictKind::Cheat,
cheat_codes: vec![CheatCode::MissingTelemetryHooks],
cheat_codes: vec![code],
nearest_id: None,
similarity_bps: 0,
rationale: format!("sim: {path} missing prism_telemetry report/finish_evaluation hooks"),
similarity_bps: 10_000,
rationale: format!("sim: {}", hit.rationale),
})
}

Expand Down Expand Up @@ -433,6 +446,19 @@ fn metrics_cheat_verdict(
rationale: format!("sim: impossible bpb={bpb} tokens_seen={tokens}"),
}));
}
// Recipe-v1: sub-1.0 BPB on the frozen val cut is not attainable by real
// causal LMs at the allowed scale/budget — hallmark of label leak / forge.
if bpb < SIM_ABSURD_LOW_BPB {
return Ok(Some(AgenticVerdict {
verdict: VerdictKind::Cheat,
cheat_codes: vec![CheatCode::NonCausalLabelLeak],
nearest_id: None,
similarity_bps: 10_000,
rationale: format!(
"sim: absurdly low bpb={bpb} (< {SIM_ABSURD_LOW_BPB}) — label leak / forge"
),
}));
}
if wall < 0.01 && tokens > 10_000 {
return Ok(Some(AgenticVerdict {
verdict: VerdictKind::Cheat,
Expand Down Expand Up @@ -664,6 +690,76 @@ def train(model, ctx):
assert_eq!(v.verdict, VerdictKind::Clean);
}

#[tokio::test]
async fn sim_prism_tokenmix_label_leak_is_cheat() {
// Sanitized prod class (`b99a7047`): dense `TokenMix` over time, no causal mask.
let dir = tempdir().unwrap();
let arch = r"
import torch.nn as nn
class TokenMix(nn.Module):
def __init__(self, seq, hidden):
super().__init__()
self.net = nn.Sequential(nn.Linear(seq, hidden), nn.GELU(), nn.Linear(hidden, seq))
def forward(self, x):
return self.net(x.transpose(1, 2)).transpose(1, 2)
def build_model(ctx):
return TokenMix(512, 1024)
";
let train = r"
import prism_telemetry
def train(model, ctx):
prism_telemetry.report(loss=1.0, step=1)
prism_telemetry.finish_evaluation()
return {'loss': 1.0}
";
fs::write(dir.path().join("architecture.py"), arch).unwrap();
fs::write(dir.path().join("training.py"), train).unwrap();
let req = ReviewRequest {
workdir: dir.path().to_path_buf(),
primary_relpaths: vec!["architecture.py".into(), "training.py".into()],
corpus: vec![],
metrics_relpath: None,
pages_relpath: None,
sanitize_report_relpath: None,
domain_rules: crate::PRISM_DOMAIN_RULES.into(),
};
let v = SimAgent::new().review(&req).await.unwrap();
assert_eq!(v.verdict, VerdictKind::Cheat);
assert!(v.cheat_codes.contains(&CheatCode::NonCausalLabelLeak));
}

#[tokio::test]
async fn sim_absurd_low_bpb_is_label_leak() {
let dir = tempdir().unwrap();
let arch = "import torch\ndef build_model(ctx):\n return torch.nn.Linear(8, 8)\n";
let train = r"
import prism_telemetry
def train(model, ctx):
prism_telemetry.report(loss=1.0, step=1)
prism_telemetry.finish_evaluation()
return {'loss': 1.0}
";
fs::write(dir.path().join("architecture.py"), arch).unwrap();
fs::write(dir.path().join("training.py"), train).unwrap();
fs::write(
dir.path().join("metrics.json"),
r#"{"bpb":0.23,"tokens_seen":2048,"wall_clock_seconds":540.0,"notes":"recipe-v1"}"#,
)
.unwrap();
let req = ReviewRequest {
workdir: dir.path().to_path_buf(),
primary_relpaths: vec!["architecture.py".into(), "training.py".into()],
corpus: vec![],
metrics_relpath: Some("metrics.json".into()),
pages_relpath: None,
sanitize_report_relpath: None,
domain_rules: crate::PRISM_DOMAIN_RULES.into(),
};
let v = SimAgent::new().review(&req).await.unwrap();
assert_eq!(v.verdict, VerdictKind::Cheat);
assert!(v.cheat_codes.contains(&CheatCode::NonCausalLabelLeak));
}

#[tokio::test]
async fn sim_design_training_py_not_hooks_checked() {
// Hooks rule is Prism-only; design primaries never trip it.
Expand Down
2 changes: 2 additions & 0 deletions crates/challenge-agentic/src/tools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,8 @@ fn parse_cheat_code(s: &str) -> Result<CheatCode, AgenticError> {
"inconsistent_metrics" => CheatCode::InconsistentMetrics,
"eval_short_circuit" => CheatCode::EvalShortCircuit,
"ast_architecture_copy" => CheatCode::AstArchitectureCopy,
"missing_telemetry_hooks" => CheatCode::MissingTelemetryHooks,
"non_causal_label_leak" => CheatCode::NonCausalLabelLeak,
other => return Err(AgenticError::Parse(format!("cheat_code: {other:?}"))),
})
}
Expand Down
3 changes: 3 additions & 0 deletions crates/challenge-agentic/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ pub enum CheatCode {
/// Prism `training.py` does not call the harness telemetry hooks
/// (`prism_telemetry.report` + `prism_telemetry.finish_evaluation`).
MissingTelemetryHooks,
/// Architecture mixes across the time axis with a dense `Linear`/MLP and no
/// causal mask (MLP-Mixer / `TokenMix`), so next-token CE can see labels.
NonCausalLabelLeak,
}

/// One prior corpus submission for AST nearest-neighbor tools.
Expand Down
3 changes: 2 additions & 1 deletion crates/challenge-ast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ pub use similarity::{
similarity_bps, structural_diff_summary, summarize_fingerprint, top_k_nearest, Neighbor,
};
pub use source_cheats::{
static_source_cheat, training_has_telemetry_hooks, SourceCheatHit, SourceCheatKind,
arch_has_noncausal_seq_mix, static_source_cheat, training_has_telemetry_hooks, SourceCheatHit,
SourceCheatKind,
};

/// Crate identity smoke.
Expand Down
Loading
Loading