Skip to content

Commit aa8f753

Browse files
committed
fix(loc-cap): move static cheats to challenge-ast; drop submit shim
Keep prism-challenge and challenge-agentic under the 1500 LOC gate while preserving pre-pod static screens and GatewayClient via challenge-common.
1 parent c293c9e commit aa8f753

13 files changed

Lines changed: 52 additions & 196 deletions

File tree

crates/challenge-agentic/src/lib.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,17 @@ mod agent;
1818
mod llm;
1919
mod prompts;
2020
mod sim;
21-
mod static_checks;
2221
mod tools;
2322
mod types;
2423

2524
pub use agent::{AgentConfig, OpenRouterAgent};
26-
pub use challenge_ast::{copy_gate, CopyGateHit, GateCorpusEntry};
25+
pub use challenge_ast::{
26+
copy_gate, static_source_cheat, training_has_telemetry_hooks, CopyGateHit, GateCorpusEntry,
27+
SourceCheatHit, SourceCheatKind,
28+
};
2729
pub use llm::{load_api_key_file, DEFAULT_MODEL};
2830
pub use prompts::{AGENTIC_PROMPT_VERSION, DESIGN_DOMAIN_RULES, PRISM_DOMAIN_RULES};
2931
pub use sim::{SimAgent, SIM_CHEAT_BPS, SIM_SUSPICIOUS_BPS};
30-
pub use static_checks::{static_source_cheat, training_has_telemetry_hooks, StaticCheatHit};
3132
pub use types::{
3233
AgenticBackend, AgenticError, AgenticVerdict, CheatCode, ContainerReviewRequest, CorpusEntry,
3334
ReviewRequest, VerdictKind, OPENROUTER_API_BASE,

crates/challenge-agentic/src/sim.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,6 @@ impl AgenticBackend for SimAgent {
7979
return Ok(v);
8080
}
8181

82-
// Source-only screens are also available via [`crate::static_source_cheat`]
83-
// for the pre-pod orchestrator path; sim keeps the in-review copies so
84-
// metrics-relative checks and corpus AST still share one backend.
85-
8682
if let Some(v) = pages_scrape_cheat_verdict(req)? {
8783
return Ok(v);
8884
}
@@ -191,7 +187,7 @@ fn telemetry_hooks_verdict(
191187
return None;
192188
}
193189
let (path, src) = primaries.iter().find(|(p, _)| p.ends_with("training.py"))?;
194-
if crate::training_has_telemetry_hooks(src) {
190+
if challenge_ast::training_has_telemetry_hooks(src) {
195191
return None;
196192
}
197193
Some(AgenticVerdict {

crates/challenge-ast/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
mod fingerprint;
1010
mod gate;
1111
mod similarity;
12+
mod source_cheats;
1213
mod walk;
1314

1415
pub use fingerprint::{fingerprint_source, AstError, Fingerprint};
@@ -19,6 +20,9 @@ pub use gate::{
1920
pub use similarity::{
2021
similarity_bps, structural_diff_summary, summarize_fingerprint, top_k_nearest, Neighbor,
2122
};
23+
pub use source_cheats::{
24+
static_source_cheat, training_has_telemetry_hooks, SourceCheatHit, SourceCheatKind,
25+
};
2226

2327
/// Crate identity smoke.
2428
#[must_use]

crates/challenge-agentic/src/static_checks.rs renamed to crates/challenge-ast/src/source_cheats.rs

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,40 @@
11
//! Cheap source-only cheat screens (no GPU, no private eval assets).
2-
//!
3-
//! Run these **before** renting a Lium pod so a bad submission fails fast
4-
//! instead of burning hours of GPU. Metrics/receipt consistency checks stay
5-
//! post-eval (they need harness output).
62
7-
use crate::types::CheatCode;
3+
/// Kind of static source hit (maps to agentic `CheatCode` at the call site).
4+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5+
pub enum SourceCheatKind {
6+
/// Hardcoded `METRICS_JSON=` short-circuit.
7+
EvalShortCircuit,
8+
/// Missing Prism telemetry hooks in `training.py`.
9+
MissingTelemetryHooks,
10+
}
811

912
/// One static source finding.
1013
#[derive(Debug, Clone, PartialEq, Eq)]
11-
pub struct StaticCheatHit {
12-
/// Cheat taxonomy code.
13-
pub code: CheatCode,
14+
pub struct SourceCheatHit {
15+
/// Cheat kind.
16+
pub kind: SourceCheatKind,
1417
/// Human-readable reason (safe to surface in `error_detail`).
1518
pub rationale: String,
1619
}
1720

1821
/// Scan miner sources for cheap, deterministic cheat patterns.
19-
///
20-
/// Order: hardcoded `METRICS_JSON=` short-circuit first, then missing Prism
21-
/// telemetry hooks in `training.py`. Returns the first hit.
2222
#[must_use]
23-
pub fn static_source_cheat(architecture_py: &str, training_py: &str) -> Option<StaticCheatHit> {
23+
pub fn static_source_cheat(architecture_py: &str, training_py: &str) -> Option<SourceCheatHit> {
2424
for (path, src) in [
2525
("architecture.py", architecture_py),
2626
("training.py", training_py),
2727
] {
2828
if src.contains("METRICS_JSON=") {
29-
return Some(StaticCheatHit {
30-
code: CheatCode::EvalShortCircuit,
29+
return Some(SourceCheatHit {
30+
kind: SourceCheatKind::EvalShortCircuit,
3131
rationale: format!("static: hardcoded METRICS_JSON in {path}"),
3232
});
3333
}
3434
}
3535
if !training_has_telemetry_hooks(training_py) {
36-
return Some(StaticCheatHit {
37-
code: CheatCode::MissingTelemetryHooks,
36+
return Some(SourceCheatHit {
37+
kind: SourceCheatKind::MissingTelemetryHooks,
3838
rationale: "static: training.py missing prism_telemetry report/finish_evaluation hooks"
3939
.into(),
4040
});
@@ -48,9 +48,7 @@ pub fn training_has_telemetry_hooks(training_py: &str) -> bool {
4848
let imports_shim = training_py.contains("prism_telemetry")
4949
|| training_py.contains("ctx[\"telemetry\"]")
5050
|| training_py.contains("ctx['telemetry']");
51-
let calls_report = training_py.contains(".report(");
52-
let calls_finish = training_py.contains("finish_evaluation(");
53-
imports_shim && calls_report && calls_finish
51+
training_py.contains(".report(") && training_py.contains("finish_evaluation(") && imports_shim
5452
}
5553

5654
#[cfg(test)]
@@ -64,7 +62,7 @@ mod tests {
6462
"def train(m, ctx):\n print('METRICS_JSON={}')\n",
6563
)
6664
.expect("hit");
67-
assert_eq!(hit.code, CheatCode::EvalShortCircuit);
65+
assert_eq!(hit.kind, SourceCheatKind::EvalShortCircuit);
6866
}
6967

7068
#[test]
@@ -74,7 +72,7 @@ mod tests {
7472
"def train(m, ctx):\n return {}\n",
7573
)
7674
.expect("hit");
77-
assert_eq!(hit.code, CheatCode::MissingTelemetryHooks);
75+
assert_eq!(hit.kind, SourceCheatKind::MissingTelemetryHooks);
7876
}
7977

8078
#[test]

crates/prism-challenge/src/lib.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,13 @@ mod api;
1616
mod leaf_emit;
1717
pub mod orchestrator;
1818
mod score;
19-
mod submit;
2019

2120
pub use api::{record_epoch, submission_router, AppState};
22-
pub use leaf_emit::{emit_signed_leaf_set, public_key_from_secret, verify_leaf_sig, LeafEmitError};
21+
pub use challenge_common::{
22+
public_key_from_secret, submit_signed_leaf_set, verify_leaf_sig, GatewayClient,
23+
GatewayClientConfig, LeafEmitError, SubmitError, SubmitOutcome,
24+
};
25+
pub use leaf_emit::emit_signed_leaf_set;
2326
pub use orchestrator::{Orchestrator, OrchestratorConfig};
2427
pub use prism_challenge_task::{
2528
CHALLENGE_ID, CHALLENGE_ID_BYTES, SCORE_MAX, SCORING_VERSION, TASK_ID_DOMAIN,
@@ -36,9 +39,6 @@ pub use prism_store::{
3639
StoreError, SubmissionState,
3740
};
3841
pub use score::{combine_final, FinalOutcome};
39-
pub use submit::{
40-
submit_signed_leaf_set, GatewayClient, GatewayClientConfig, SubmitError, SubmitOutcome,
41-
};
4242

4343
pub use bundle::{LeafV1, NoScoreReasonCode, ScoreOrAbsence};
4444
pub use crypto::KEY_LEN;

crates/prism-challenge/src/orchestrator.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use chain::ChainClient;
2222
use challenge_agentic::{
2323
copy_gate, static_source_cheat, AgenticBackend, AgenticVerdict, VerdictKind,
2424
};
25-
use challenge_common::{expected_set_at_chain, PinnedBlockHash};
25+
use challenge_common::{expected_set_at_chain, GatewayClient, PinnedBlockHash};
2626
use crypto::KEY_LEN;
2727
use prism_emit::EpochEmitter;
2828
use prism_lium::{EvalJobBackend, InstanceSpec};
@@ -35,7 +35,6 @@ use tracing::{info, warn};
3535

3636
use crate::agentic::{build_review_request, corpus_from_rows, gate_corpus_from_rows, same_miner};
3737
use crate::score::{combine_final, FinalOutcome};
38-
use crate::submit::GatewayClient;
3938
use prism_store::{FinalScore, PrismStore, Stage, StageEvent, StatePatch, SubmissionState};
4039

4140
/// Worker + emitter settings.
@@ -115,7 +114,7 @@ impl<C: ChainClient + Send> Orchestrator<C> {
115114
chain: Arc<C>,
116115
sk: [u8; KEY_LEN],
117116
) -> Self {
118-
let emitter = EpochEmitter::new(Arc::clone(&store), sk, cfg.netuid, gateway.common());
117+
let emitter = EpochEmitter::new(Arc::clone(&store), sk, cfg.netuid, gateway.clone());
119118
Self {
120119
cfg,
121120
store,
@@ -523,7 +522,7 @@ impl<C: ChainClient + Send> Orchestrator<C> {
523522
};
524523
warn!(
525524
submission_id = %row.id,
526-
code = ?hit.code,
525+
kind = ?hit.kind,
527526
rationale = %hit.rationale,
528527
"static source cheat rejected (pod skipped)"
529528
);
@@ -532,7 +531,7 @@ impl<C: ChainClient + Send> Orchestrator<C> {
532531
None,
533532
Some(serde_json::json!({
534533
"gate": "static_source",
535-
"cheat_code": format!("{:?}", hit.code),
534+
"cheat_kind": format!("{:?}", hit.kind),
536535
"rationale": hit.rationale,
537536
})),
538537
hit.rationale.clone(),

crates/prism-challenge/src/submit.rs

Lines changed: 0 additions & 146 deletions
This file was deleted.

crates/prism-challenge/tests/arch_competition.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,8 @@ fn mk_orchestrator(
138138
let gateway = Arc::new(
139139
GatewayClient::new(GatewayClientConfig {
140140
base_url: "dry-run".into(),
141-
max_retries: 0,
141+
max_attempts: 1,
142+
backoff: std::time::Duration::from_millis(1),
142143
})
143144
.unwrap(),
144145
);

crates/prism-challenge/tests/cheat_arch_copy.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ async fn baseline_arch_train_copy_scores_zero() {
8383
let gateway = Arc::new(
8484
GatewayClient::new(GatewayClientConfig {
8585
base_url: "dry-run".into(),
86-
max_retries: 0,
86+
max_attempts: 1,
87+
backoff: std::time::Duration::from_millis(1),
8788
})
8889
.unwrap(),
8990
);

crates/prism-challenge/tests/cheat_metrics.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ async fn hardcoded_metrics_json_scores_zero() {
8282
let gateway = Arc::new(
8383
GatewayClient::new(GatewayClientConfig {
8484
base_url: "dry-run".into(),
85-
max_retries: 0,
85+
max_attempts: 1,
86+
backoff: std::time::Duration::from_millis(1),
8687
})
8788
.unwrap(),
8889
);

0 commit comments

Comments
 (0)