-
Notifications
You must be signed in to change notification settings - Fork 18
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
Prism 2.1 Scoring #166
Changes from 8 commits
2f9facd
42211ee
faac738
f22bc30
0208bcd
29125fc
f4e65a9
1143210
abe9605
cce88a3
ee0e95f
a00f619
89b70e2
331cbe2
8df2f6d
d41ee0c
c16248e
4b45232
2334aea
fee031a
2665e60
61bda29
cf324c2
68e6d90
6f31b85
b626958
2e766fd
6667b41
a082a80
cdc9a79
9ddb8fa
f550d08
a4af6b9
a1b4fbf
d83cd64
f3838f8
08a829d
5e41e73
ecca7c3
4f7ea87
c640da9
9893554
e5d28e4
57ef48f
c41674c
76fcf30
088ec1c
bf9b758
c4c714f
13fc65f
500497d
247102a
4e1452c
c0ebd29
03478be
947fc49
7fcf56c
2cbcac9
bf84a31
bf392c6
2686b91
f6a2c50
d0fd56c
e2d6b73
9dff388
1d6c57c
824d162
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