-
Notifications
You must be signed in to change notification settings - Fork 16
Prism 2.1 Scoring #166
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Prism 2.1 Scoring #166
Changes from all commits
2f9facd
42211ee
faac738
f22bc30
0208bcd
29125fc
f4e65a9
1143210
abe9605
cce88a3
ee0e95f
a00f619
89b70e2
331cbe2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,7 +23,7 @@ use prism_pipeline::{ | |
| }; | ||
| use prism_recipe::{BASELINE_ARCHITECTURE_PY, BASELINE_TRAINING_PY}; | ||
| use prism_review::{ReviewBackend, SimilarityVerdict, SourceSnippet}; | ||
| use submission_gating::GatingStore; | ||
| use submission_gating::{classify_eval_fail, GatingStore}; | ||
| use tokio::time::sleep; | ||
| use tracing::{info, warn}; | ||
|
|
||
|
|
@@ -50,6 +50,11 @@ pub struct OrchestratorConfig { | |
| pub auto_retry_max: u32, | ||
| pub scoring_mode: ScoringMode, | ||
| pub orphan_grace_secs: u64, | ||
| /// GPUs rented per eval pod (`PRISM_POD_GPU_COUNT`, default 4). | ||
| /// | ||
| /// Miners may train across all of them; the eval battery stays pinned to | ||
| /// GPU 0 so G7 timings stay comparable across submissions. | ||
| pub pod_gpu_count: u32, | ||
| } | ||
|
|
||
| impl Default for OrchestratorConfig { | ||
|
|
@@ -69,6 +74,7 @@ impl Default for OrchestratorConfig { | |
| auto_retry_max: 3, | ||
| scoring_mode: ScoringMode::from_env(), | ||
| orphan_grace_secs: DEFAULT_ORPHAN_GRACE_SECS, | ||
| pod_gpu_count: prism_lium::pod_gpu_count_from_env(), | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -365,16 +371,16 @@ impl<C: ChainClient + Send> Orchestrator<C> { | |
| ) -> Result<(), String> { | ||
| let msg = format!("measure: {err}"); | ||
| // Harness EVAL_FAIL is miner/model code, not Lium infra — do not burn | ||
| // auto-retries (BYOK seal is kept on Err; see finish_measure). | ||
| // auto-retries (BYOK seal is kept on Err; see finish_measure). The | ||
| // miner-fixable phases (`install_deps` custom-deps install, | ||
| // `train_script` training crash) additionally fail terminal under | ||
| // their own class, which grants unbounded resubmit. Every other | ||
| // EVAL_FAIL phase (eval / battery / score) stays the historical | ||
| // windowed `install` class. Non-EVAL_FAIL failures are Lium infra and | ||
| // keep `install` + operator-paid auto-retry. | ||
| if msg.contains("EVAL_FAIL") { | ||
| fail_terminal( | ||
| self.store.as_ref(), | ||
| self.gating.as_ref(), | ||
| row, | ||
| "install", | ||
| &msg, | ||
| ) | ||
| .await; | ||
| let class = classify_eval_fail(&msg); | ||
| fail_terminal(self.store.as_ref(), self.gating.as_ref(), row, class, &msg).await; | ||
|
Comment on lines
381
to
+383
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Description: Check whether harness/miner log output is embedded in the measure error string.
set -euo pipefail
# Where the EVAL_FAIL error text is built.
rg -n -C 12 'EVAL_FAIL' --type=rust
# finish_measure and exec_eval error construction.
ast-grep run --pattern 'async fn finish_measure($$$) { $$$ }' --lang rust
rg -n -C 8 'fn exec_eval|HARNESS_LOG_RETAIN_BYTES|truncate_tail' --type=rust
# Confirm the harness emits the marker on its own stdout stream.
rg -n -C 4 'DEPS_INSTALL_FAIL' --glob '*.py'Repository: BaseIntelligence/base Length of output: 159 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- EVAL_FAIL and measurement flow ---'
rg -n -C 20 'EVAL_FAIL|classify_eval_fail|finish_measure|format!\("measure: \{err\}"\)|measure:' crates/prism-challenge crates --glob '*.rs' | head -n 500
printf '%s\n' '--- execution and retained logs ---'
rg -n -C 15 'exec_eval|HARNESS_LOG_RETAIN_BYTES|truncate_tail|stdout|stderr|log tail' crates/prism-challenge crates --glob '*.rs' | head -n 500
printf '%s\n' '--- marker sources ---'
rg -n -C 8 'DEPS_INSTALL_FAIL|stage' . --glob '*.py' --glob '*.rs' --glob '*.json' | head -n 500
printf '%s\n' '--- orchestrator outline ---'
ast-grep outline crates/prism-challenge/src/orchestrator.rsRepository: BaseIntelligence/base Length of output: 50378 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- finish_measure implementation ---'
sed -n '90,190p' crates/prism-orphan/src/terminal.rs
printf '%s\n' '--- EvalJobBackend and RemoteExecResult definitions/usages ---'
rg -n -C 20 'trait EvalJobBackend|struct RemoteExecResult|enum LiumError|impl.*EvalJobBackend|async fn exec_eval' crates --glob '*.rs' | head -n 500
printf '%s\n' '--- all marker occurrences ---'
rg -n -C 12 'DEPS_INSTALL_FAIL' . --glob '*.py' --glob '*.rs' --glob '*.sh' --glob '*.md'
printf '%s\n' '--- harness output/error construction ---'
rg -n -C 15 'EVAL_FAIL|HARNESS_LOG_RETAIN_BYTES|truncate_tail|RemoteExecResult' crates/prism-lium crates --glob '*.rs' | head -n 600Repository: BaseIntelligence/base Length of output: 50377 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- live evaluation path ---'
sed -n '403,575p' crates/prism-lium/src/client.rs
printf '%s\n' '--- client eval delegation and error path ---'
sed -n '780,900p' crates/prism-lium/src/client.rs
printf '%s\n' '--- SSH command helpers used by live evaluation ---'
sed -n '150,245p' crates/prism-lium/src/ssh.rs
rg -n -C 10 'ssh_exec|harness.log|HARNESS_LOG_RETAIN_BYTES|EVAL_FAIL' crates/prism-lium/src crates/prism-lium-harness/src --glob '*.rs'
printf '%s\n' '--- harness fail implementation ---'
rg -n -C 20 '^def fail|EVAL_FAIL|run_miner_subprocess|subprocess' crates/prism-recipe/harness --glob '*.py'Repository: BaseIntelligence/base Length of output: 50378 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- log classification implementation ---'
sed -n '1,180p' crates/prism-lium-harness/src/detached.rs
rg -n -C 25 'fn classify_log|HarnessProgress::Failed|parse_metrics_output|EVAL_FAIL' crates/prism-lium-harness/src crates/prism-recipe/harness --glob '*.rs' --glob '*.py'
printf '%s\n' '--- log harvest implementation ---'
sed -n '650,735p' crates/prism-lium/src/client.rs
printf '%s\n' '--- harness fail and terminal output ---'
rg -n -C 15 'def fail|EVAL_FAIL|print\(|run_miner_subprocess' crates/prism-recipe/harness/main.py | head -n 300Repository: BaseIntelligence/base Length of output: 50377 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- miner subprocess output and error propagation ---'
rg -n -C 30 'def run_miner_subprocess|stdout|stderr|error.*stdout|returncode|failed|train_script|build' crates/prism-recipe/harness/prismlib/runner.py crates/prism-recipe/harness/main.py
printf '%s\n' '--- all parent fail call sites ---'
rg -n -C 18 '\bfail\(' crates/prism-recipe/harness/main.py crates/prism-recipe/harness/prismlib --glob '*.py'
printf '%s\n' '--- harness log prefixing and terminal parser behavior ---'
sed -n '170,230p' crates/prism-lium-harness/src/detached.rs
rg -n -C 12 'miner stdout|stdout.*prefix|prefix.*stdout|run_miner_subprocess' crates/prism-recipe/harness --glob '*.py'Repository: BaseIntelligence/base Length of output: 50377 🏁 Script executed: #!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
detached = Path("crates/prism-lium-harness/src/detached.rs").read_text()
runner = Path("crates/prism-recipe/harness/prismlib/runner.py").read_text()
client = Path("crates/prism-lium/src/client.rs").read_text()
gating = Path("crates/submission-gating/src/lib.rs").read_text()
checks = {
"harness redirects stdout and stderr to harness.log":
">> harness.log 2>&1" in detached,
"runner reads child stdout":
"for line in proc.stdout:" in runner,
"runner writes child lines to harness log":
'log(f"miner| {line[:500]}")' in runner,
"harvest includes harness log tail":
"tail -c 8192 harness.log" in detached,
"timeout embeds harvested log in LiumError":
'truncate_tail(&h, 4000)' in client and "harvested:" in client,
"classifier trusts marker in full message":
'msg.contains("DEPS_INSTALL_FAIL")' in gating,
"classifier trusts stage in full message":
'.split_once("\\"stage\\"")' in gating,
}
for name, ok in checks.items():
print(f"{'PASS' if ok else 'FAIL'}: {name}")
if not all(checks.values()):
raise SystemExit(1)
# Model the exact downstream decision on a miner-controlled log line.
def classify(msg):
stage = ""
marker = '"stage"'
if marker in msg:
rest = msg.split(marker, 1)[1]
if ":" in rest:
value = rest.split(":", 1)[1].lstrip().lstrip('"')
stage = value.split('"', 1)[0].split(",", 1)[0].split("}", 1)[0].strip()
if "DEPS_INSTALL_FAIL" in msg or stage in {"install_deps", "install"}:
return "install_deps"
if stage in {"train", "build"}:
return "train_script"
return "install"
for payload, expected in [
("EVAL_FAIL\\n[harness] miner| DEPS_INSTALL_FAIL", "install_deps"),
('EVAL_FAIL\\n[harness] miner| {"stage": "install_deps"}', "install_deps"),
('EVAL_FAIL\\n[harness] miner| {"stage": "train"}', "train_script"),
]:
actual = classify(payload)
print(f"{actual == expected and 'PASS' or 'FAIL'}: {payload!r} -> {actual}")
if actual != expected:
raise SystemExit(1)
PYRepository: BaseIntelligence/base Length of output: 698 Classify Miner stdout reaches 🤖 Prompt for AI Agents |
||
| return Ok(()); | ||
| } | ||
| if self.maybe_auto_retry(row, "install", &msg).await { | ||
|
|
@@ -707,7 +713,7 @@ impl<C: ChainClient + Send> Orchestrator<C> { | |
| name: format!("prism-{}", &id[..12.min(id.len())]), | ||
| max_lifetime_hours: self.cfg.max_lifetime_hours, | ||
| max_price_per_hour: self.cfg.max_price_per_hour, | ||
| gpu_count: 1, | ||
| gpu_count: self.cfg.pod_gpu_count, | ||
| image_digest: self.cfg.image_digest.clone(), | ||
| ssh_public_keys: self.cfg.ssh_public_keys.clone(), | ||
| ssh_key_name: Some("prism-mission-worker".into()), | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| [package] | ||
| name = "prism-competition" | ||
| description = "PRISM emission competition math (WTA / top3 collapse, owner split)" | ||
| version.workspace = true | ||
| edition.workspace = true | ||
| license.workspace = true | ||
| repository.workspace = true | ||
| rust-version.workspace = true | ||
| publish = false | ||
|
|
||
| [dependencies] | ||
| prism-store = { path = "../prism-store" } | ||
|
|
||
| [lints] | ||
| workspace = true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: BaseIntelligence/base
Length of output: 159
🏁 Script executed:
Repository: BaseIntelligence/base
Length of output: 50378
🏁 Script executed:
Repository: BaseIntelligence/base
Length of output: 15675
🏁 Script executed:
Repository: BaseIntelligence/base
Length of output: 12955
Keep
/retryoninfra_resubmit_allowed.resubmit_allowedhas no expiry forinstall_depsandtrain_script.fail_terminalrecordsChallengeInternalfor these failures, so/retrysetsinfraand skips both the admin bearer check andretry_max. A miner can repeat retries without an admin token or retry limit, subject to the live Lium key requirement.Use
infra_resubmit_allowedat line 437. FreshPOST /v1/submissionsalready usesresubmit_allowedfor miner-fixable failures.🤖 Prompt for AI Agents
Source: Coding guidelines