mirror of
https://github.com/razzant/ouroboros.git
synced 2026-10-19 10:04:16 +00:00
Owner-approved big release (plan: большой_релиз_v6.26.0). Workstreams:
- WS-A lint gate: ruff F-rules step in CI quick-test; fixed the real F823
NameError class (supervisor/events.py utc_now_iso shadowing); make lint/health.
- WS-B memory integrity: atomic dialogue_blocks with corrupt-quarantine
(.corrupt-<ts>.bak + memory_store_corrupt event); honest scratchpad journal
(block_append_failed, corrupt storage renders as corruption not "(empty)");
full Pattern Register window (16K cap vs 3K cut); merge-aware scratchpad
consolidation under the sidecar lock; backlog writes through locked helpers;
chat omission notes ("[N older unconsolidated messages omitted]").
- WS-C provider SSOT: provider registry (prefixes/credentials/resolution) in
provider_models.py replacing 5 duplicated knowledge sites; credential-aware
consolidation model; pricing empty-fetch retry; direct-route correctness
(o-series max_completion_tokens, reasoning_effort, Anthropic error bodies,
per-request timeouts on cached clients); deep/plan review budgets reserve
output headroom inside the 1M window (min(SSOT, window − output − margin)).
- WS-D races/state: utils.update_json_locked (locked RMW, loud TimeoutError);
task_results merge under per-file lock (cancel-latch safe); update_state
migration for owner binding, evolution counters, budget_line, post-task
activation; queue-lock coverage (enqueue, timeouts, worker health, task_done,
snapshot); visible supervisor death (supervisor_error + owner notice + ghost
consciousness/chat-agent cleanup on re-init); chat.jsonl rotation via
os.replace under the append lock; unbounded _outbox removed; host-service
port probe + actual-port panic sweep; skill lifecycle lane deadline
(OUROBOROS_SKILL_LIFECYCLE_TIMEOUT_SEC, dedupe-leak-safe); consilium
force-plan structured flag (plan_review_aggregate from the FULL result);
atomic writers (update-intent, repo-manifest, metrics cache, post-task pair);
review_state.save_state raises on lock timeout (advisory ledger honesty);
apply_pending_request no-ops while a campaign is active;
api_update_apply kills workers only AFTER update validation, with respawn
on aborted checkout and "interrupted" terminal status.
- WS-E immune hardening: triad anti-refusal coverage contract (empty array
needs NO_FINDINGS sentinel or bare-[] body; refusal prose with [] is
parse_failure and never enters quorum); BIBLE P3 "Owner-chosen enforcement,
loud advisory" bound + CHECKLISTS sync; every advisory pass-through of a
blocking signal writes review_advisory_override + persistent
advisory_overrides (surfaced by review_status); ToolEntry.mutates_worktree
with dispatcher-level before/after worktree diff invalidation (covers error
paths; read-only runs no longer invalidate; redundant manual calls removed);
scope review fails closed without its checklist; advisory final write is a
locked re-read merge; synthesis severity defaults to critical with WARNING
fallbacks; find removed from SAFE_SHELL_COMMANDS; anti-thrashing state
survives advisory criticals; preflight env scrubs secret-class variables;
.git/index.lock age gate in worker startup checks.
- WS-F security: file-browser symlink containment on the RESOLVED path across
all endpoints (out-of-root symlink targets are listed but inert; tests
rewritten to the new contract deliberately); HMAC-signed session cookies
(server-side persisted key, 30-day TTL, Secure on TLS) replacing the
permanent password-derived cookie; password-class settings mask to a
constant placeholder; conservative SSRF guard for the MAIN agent (link-local
/cloud-metadata only, LAN stays reachable, per-request route re-validation);
ClawHub zip-slip hardening (":"/backslash segments rejected + post-join
containment) and lazy no-proxy OuroborosHub opener; single-execution
signature dispatch for extension handlers (no TypeError re-run after side
effects); onboarding postMessage origin checks; SHA256-pinned
python-standalone download with pipefail; payload-resident dependency
fingerprints only corroborate durable deps.json; skill payload re-hash
immediately before spawn (TOCTOU narrowing).
- WS-G process custody: ouroboros/process_custody.py — spawn_supervised
chokepoint + durable data/state/process_ledger.jsonl (pid, pgid,
fingerprint{start_time, cmd_sha256}, purpose, scope task|session|daemon,
owner_task, session_id); platform_layer.process_start_time primitive;
startup + periodic reaper killing ONLY strict-fingerprint matches from dead
generations/tasks (never by command-line class); migrations: services
(the orphan hole), workspace executor + local model + extension companions
(ledger write-through), worker_pids (write-through; legacy path retained);
parent lifelines (ppid watchdog, group-suicide only as group leader) in
worker_main, extension runner, Claude readonly child; conformance test
pinning the Popen allowlist; ARCHITECTURE/DEVELOPMENT/CHECKLISTS entries.
- WS-H native multimodal chat: supports_vision capability map (static
prefixes + OpenRouter /models input_modalities overlay); web chat uploads
ride the WS frame as structured attachments (additive ChatInbound field)
and image uploads become NATIVE image blocks via the existing Path B;
browser screenshots inject natively for vision models via the multipart
user-merge (tool result stays a string; file persisted under
data/uploads/screenshots for re-view); K=3 newest-image eviction with
caption placeholders carrying the vlm_query re-view path; image-aware token
estimates (fixed ~1.1K-token equivalent instead of base64 length, fixing
permanent emergency-compaction wedges); compaction renders images as
captions (no base64 into the summarizer); GigaChat/local lanes emit explicit
"[image omitted: model has no vision]"; internal _caption/_source_path
metadata stripped from provider payloads.
- WS-I housekeeping (partial): SETTLED_STATUSES SSOT (+ cycle-safe mirror pin);
owner_inject.py renamed to owner_mailbox.py; version-neutral envelope
wording; files.py import-block cleanup. Remaining WS-I/WS-J/WS-K items are
deferred with the owner's context-budget priority on review+release.
Review notes: triad+scope ran via scripts/run_external_review.py on the core
pack across 3 rounds to convergence (scope responded=PASS each round; round-2
criticals fixed: update_apply kill-order + respawn, lifecycle dedupe leak on
lane timeout, OUROBOROS_MAX_ROUNDS hot-reload + docs, toggle_evolution
NameError, async Anthropic timeout forwarding, supports_vision local check,
budget-update lock visibility, ChatInbound additive attachment contract,
file-browser doc sync). The FULL combined diff exceeds every triad model's
context window (~1.59M tokens > 1.05M) — reviewed in packs; remaining
cross-pack findings were verified as slicing artifacts. Adversarial critics
(GPT; Gemini/Opus rounds) ran on the working tree. Deliberate tradeoffs:
metadata-based eviction captions (no light-LLM call in the hot path);
worker ledger records use live-cmdline fingerprints with a synthetic-arg
fallback only where the OS offers no cmdline.
135 lines
6 KiB
Python
135 lines
6 KiB
Python
#!/usr/bin/env python3
|
|
"""Run official SWE-bench Pro eval, then print a diagnostic summary.
|
|
|
|
This wrapper does not replace Pro scoring. The official ``swe_bench_pro_eval.py``
|
|
output remains the source of truth. The post-run table only helps inspect
|
|
per-instance output files.
|
|
|
|
python pro/grade_pro.py --predictions runs/pro_smoke/predictions.jsonl --workers 4
|
|
"""
|
|
from __future__ import annotations
|
|
import argparse, ast, csv, json, pathlib, subprocess, sys
|
|
|
|
if __package__ in {None, ""}:
|
|
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parents[3]))
|
|
|
|
from devtools.benchmarks.common.run_roots import ensure_outside_repo, repo_root_from_devtools, run_root
|
|
|
|
PRO = pathlib.Path(__file__).resolve().parent
|
|
DEFAULT_RUN_ROOT = run_root("swe_bench_pro")
|
|
EVAL_REPO = DEFAULT_RUN_ROOT / "SWE-bench_Pro-os"
|
|
CSV_DEFAULT = PRO / "task_order_pro_70.csv"
|
|
|
|
|
|
def load_predictions(path: pathlib.Path) -> list[dict]:
|
|
return [json.loads(l) for l in path.read_text().splitlines() if l.strip()]
|
|
|
|
|
|
def colleague_verdicts(csv_path: pathlib.Path) -> dict:
|
|
with csv_path.open() as f:
|
|
return {r["instance_id"]: r["verdict"] for r in csv.DictReader(f)}
|
|
|
|
|
|
def raw_sample_index(raw_sample: pathlib.Path) -> dict:
|
|
"""Return raw official sample rows by instance id for diagnostic inspection."""
|
|
idx = {}
|
|
for l in raw_sample.read_text(errors="replace").splitlines():
|
|
if not l.strip():
|
|
continue
|
|
try:
|
|
d = json.loads(l)
|
|
except Exception:
|
|
continue
|
|
idx[d.get("instance_id", "")] = d
|
|
return idx
|
|
|
|
|
|
def as_set(v) -> set:
|
|
if isinstance(v, str):
|
|
try:
|
|
return set(json.loads(v))
|
|
except Exception:
|
|
try:
|
|
return set(ast.literal_eval(v))
|
|
except Exception:
|
|
return set()
|
|
return set(v or [])
|
|
|
|
|
|
def main() -> int:
|
|
ap = argparse.ArgumentParser()
|
|
ap.add_argument("--predictions", default=str(DEFAULT_RUN_ROOT / "predictions.jsonl"))
|
|
ap.add_argument("--out-dir", default=str(DEFAULT_RUN_ROOT / "pro_eval"))
|
|
ap.add_argument("--eval-repo", default=str(EVAL_REPO), help="external checkout of scaleapi/SWE-bench_Pro-os")
|
|
ap.add_argument("--prefix", default="ours")
|
|
ap.add_argument("--workers", type=int, default=4)
|
|
ap.add_argument("--platform", default="linux/amd64")
|
|
ap.add_argument("--skip-run", action="store_true", help="aggregate an existing out-dir without running official eval")
|
|
ap.add_argument("--csv", default="", help="optional CSV with instance_id,verdict columns for baseline comparison")
|
|
args = ap.parse_args()
|
|
|
|
eval_repo = pathlib.Path(args.eval_repo).expanduser().resolve()
|
|
raw_sample = eval_repo / "helper_code" / "sweap_eval_full_v2.jsonl"
|
|
if not eval_repo.is_dir():
|
|
print(f"error: eval harness clone is missing: {eval_repo}\n git clone --depth 1 https://github.com/scaleapi/SWE-bench_Pro-os.git {eval_repo}", file=sys.stderr)
|
|
return 2
|
|
if not raw_sample.is_file():
|
|
print(f"error: raw_sample is missing: {raw_sample}", file=sys.stderr); return 2
|
|
|
|
preds = load_predictions(pathlib.Path(args.predictions).expanduser())
|
|
preds = [p for p in preds if (p.get("model_patch") or "").strip()]
|
|
out_dir = ensure_outside_repo(pathlib.Path(args.out_dir), repo_root_from_devtools())
|
|
patches = [{"instance_id": p["instance_id"], "patch": p["model_patch"], "prefix": args.prefix} for p in preds]
|
|
patches_path = out_dir / "patches.json"
|
|
patches_path.write_text(json.dumps(patches), encoding="utf-8")
|
|
print(f"[swe-pro] wrote {len(patches)} patches to {patches_path}", file=sys.stderr)
|
|
|
|
if not args.skip_run:
|
|
cmd = [sys.executable, "swe_bench_pro_eval.py",
|
|
"--raw_sample_path", str(raw_sample),
|
|
"--patch_path", str(patches_path),
|
|
"--output_dir", str(out_dir),
|
|
"--scripts_dir", "run_scripts",
|
|
"--num_workers", str(args.workers),
|
|
"--dockerhub_username", "jefzda",
|
|
"--use_local_docker", "--docker_platform", args.platform]
|
|
print("[swe-pro] running official eval:\n " + " ".join(cmd), file=sys.stderr)
|
|
r = subprocess.run(cmd, cwd=str(eval_repo))
|
|
if r.returncode != 0:
|
|
print(f"[swe-pro] official eval returned {r.returncode}; summarizing available output", file=sys.stderr)
|
|
|
|
rs = raw_sample_index(raw_sample)
|
|
csv_path = pathlib.Path(args.csv).expanduser() if args.csv else CSV_DEFAULT
|
|
verd = colleague_verdicts(csv_path) if csv_path.is_file() else {}
|
|
print("\n[diagnostic] Non-leaderboard summary derived from official per-instance outputs.")
|
|
print(f"{'instance':52} {'diagnostic':18} {'baseline':10} {'tests P/missing/total'}")
|
|
n_res = 0
|
|
for p in patches:
|
|
iid = p["instance_id"]
|
|
od = out_dir / iid / f"{args.prefix}_output.json"
|
|
if not od.is_file():
|
|
od2 = list((out_dir).glob(f"**/{args.prefix}_output.json"))
|
|
od = next((x for x in od2 if iid in str(x)), od)
|
|
status = "NO_OUTPUT"; ntp = "-"
|
|
if od.is_file():
|
|
try:
|
|
out = json.loads(od.read_text())
|
|
tests = out.get("tests") or []
|
|
passed = {t["name"] for t in tests if t.get("status") == "PASSED"}
|
|
rsd = rs.get(iid, {})
|
|
f2p = as_set(rsd.get("FAIL_TO_PASS") or rsd.get("fail_to_pass"))
|
|
p2p = as_set(rsd.get("PASS_TO_PASS") or rsd.get("pass_to_pass"))
|
|
need = f2p | p2p
|
|
resolved = bool(need) and need <= passed
|
|
n_res += int(resolved)
|
|
status = "DIAGNOSTIC_PASS" if resolved else "DIAGNOSTIC_FAIL"
|
|
ntp = f"{len(passed)}/{len(need - passed)}/{len(need)}"
|
|
except Exception as e:
|
|
status = f"PARSE_ERR:{e}"[:18]
|
|
print(f"{iid[:52]:52} {status:18} {verd.get(iid,'?'):10} {ntp}")
|
|
print(f"\n[diagnostic] pass-like {n_res}/{len(patches)}; official Pro eval output remains source of truth.")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|