diff --git a/submissions/sn60__bitsec/miner/jimcody1995-20260709-01/agent.py b/submissions/sn60__bitsec/miner/jimcody1995-20260709-01/agent.py new file mode 100644 index 0000000..3779142 --- /dev/null +++ b/submissions/sn60__bitsec/miner/jimcody1995-20260709-01/agent.py @@ -0,0 +1,194 @@ +from __future__ import annotations + +"""SN60 miner tuned for July 2026 validation rules. + +Three inference calls per problem, depth-first audits on graph-ranked targets, +crash-safe execution for smoke tests and replica stability, and matcher-shaped +output. Helpers live under helpers/ per current submission rules. +""" + +import time +from pathlib import Path +from typing import Any + +from helpers.discovery import ( + EXT, + build_catalog, + graph_digest, + hot_functions, + import_graph, + import_neighbors, + rank_catalog, + resolve_targets, + suffix_index, +) +from helpers.findings import collapse_findings, format_finding +from helpers.llm import CallBudget, infer, load_json + +TIME_BUDGET = 220.0 +DEEP_CHARS = 46_000 +IMPORT_CHARS = 3_200 +TRIAGE_TOKENS = 4200 +DEEP_TOKENS = 7600 + +SYSTEM = ( + "You are a senior smart-contract security auditor. Report only high or critical " + "vulnerabilities with a concrete exploit path and material impact. Reject style, " + "gas, centralization, and speculation. Return strict JSON only." +) + +HUNT = ( + "Hunt exhaustively for: missing access control; reentrancy and CEI violations; " + "oracle/price manipulation; LP/share accounting and rounding; slippage bypass; " + "liquidation math; unsafe delegatecall/upgrade/initializer; signature replay; " + "decimal mismatches; cross-function invariant breaks." +) + + +def agent_main(project_dir: str | None = None, inference_api: str | None = None) -> dict: + collected: list[dict[str, Any]] = [] + try: + collected = _run(project_dir, inference_api) + except Exception: + pass + by_rel: dict[str, dict[str, Any]] = {} + root = locate_project(project_dir) + if root is not None: + by_rel = {row["rel"]: row for row in build_catalog(root)} + shaped: list[dict[str, Any]] = [] + for raw in collected: + item = format_finding(raw, by_rel) + if item is not None: + shaped.append(item) + return {"vulnerabilities": collapse_findings(shaped)} + + +def _run(project_dir: str | None, inference_api: str | None) -> list[dict[str, Any]]: + collected: list[dict[str, Any]] = [] + root = locate_project(project_dir) + if root is None: + return collected + + clock = time.monotonic() + catalog = build_catalog(root) + if not catalog: + return collected + + lookup = suffix_index(catalog) + graph = import_graph(catalog, lookup) + ranked = rank_catalog(catalog, graph) + + budget = CallBudget() + targets = run_triage(inference_api, ranked, graph, budget) + ordered = resolve_targets(targets, ranked) + + primary = ordered[:1] + secondary = ordered[1:3] + if time.monotonic() - clock < TIME_BUDGET and budget.can_call(): + collected.extend(deep_audit(inference_api, primary, lookup, budget)) + if time.monotonic() - clock < TIME_BUDGET and budget.can_call(): + collected.extend(deep_audit(inference_api, secondary, lookup, budget)) + return collected + + +def locate_project(project_dir: str | None) -> Path | None: + options: list[str] = [] + if project_dir: + options.append(project_dir) + for key in ("PROJECT_DIR", "PROJECT_PATH", "PROJECT_ROOT", "PROJECT_CODE"): + val = __import__("os").environ.get(key) + if val: + options.append(val) + options.extend(("/app/project_code", "/app/project", "/project", "/code", ".")) + for raw in options: + try: + p = Path(raw).expanduser().resolve() + except (OSError, RuntimeError): + continue + if p.is_dir() and any(f.is_file() and f.suffix.lower() in EXT for f in p.rglob("*")): + return p + return None + + +def run_triage( + api: str | None, + ranked: list[dict[str, Any]], + graph: dict[str, set[str]], + budget: CallBudget, +) -> list[str]: + prompt = ( + "Given this import-graph ranked map, pick the files most likely to contain ALL " + "high/critical bugs in this codebase. Return strict JSON only:\n" + '{"target_files":["path.sol"]}\n' + "Prioritize hub contracts, privileged entrypoints, pool/oracle/accounting logic. " + "List 3-5 files in priority order. Do not invent paths.\n\n" + + graph_digest(ranked, graph) + ) + obj = load_json(infer( + api, + [{"role": "system", "content": SYSTEM}, {"role": "user", "content": prompt}], + TRIAGE_TOKENS, + budget, + )) + targets = obj.get("target_files") + if not isinstance(targets, list): + return [] + return [str(x) for x in targets if isinstance(x, str)] + + +def deep_prompt(batch: list[dict[str, Any]], lookup: dict[str, dict[str, Any]]) -> str: + header = ( + "Deep-audit the sources below end-to-end. Find every distinct high/critical bug. " + + HUNT + " " + "Return strict JSON only:\n" + '{"findings":[{"title":"Contract.function - specific bug","file":"exact/path",' + '"contract":"Contract","function":"fn","line":123,"severity":"high|critical",' + '"mechanism":"pre -> attack -> broken invariant","impact":"specific harm",' + '"description":"2-4 sentences naming file, contract, function, mechanism, impact"}]}\n' + "Up to 6 findings. Each must name a real function from the source. " + "If none, return {\"findings\":[]}.\n" + ) + parts = [header] + room = DEEP_CHARS - len(header) + for row in batch: + block = ( + f"\n\n===== FILE: {row['rel']} =====\n" + f"Contracts: {', '.join(row['contracts'][:6])}\n" + f"Hot: {', '.join(hot_functions(str(row['text']))[:5])}\n" + f"{row['text']}\n" + ) + neighbors = import_neighbors(row, lookup, IMPORT_CHARS) + if neighbors: + block += f"\n===== IMPORT CONTEXT =====\n{neighbors}\n" + if len(block) > room: + block = block[: max(0, room)] + "\n/* truncated */\n" + if room <= 0: + break + parts.append(block) + room -= len(block) + return "".join(parts) + + +def deep_audit( + api: str | None, + batch: list[dict[str, Any]], + lookup: dict[str, dict[str, Any]], + budget: CallBudget, +) -> list[dict[str, Any]]: + if not batch or not budget.can_call(): + return [] + obj = load_json(infer( + api, + [{"role": "system", "content": SYSTEM}, {"role": "user", "content": deep_prompt(batch, lookup)}], + DEEP_TOKENS, + budget, + )) + items = obj.get("findings") or obj.get("vulnerabilities") or [] + return [x for x in items if isinstance(x, dict)] if isinstance(items, list) else [] + + +if __name__ == "__main__": + import json + import sys + + print(json.dumps(agent_main(sys.argv[1] if len(sys.argv) > 1 else None), indent=2)) diff --git a/submissions/sn60__bitsec/miner/jimcody1995-20260709-01/agent_manifest.json b/submissions/sn60__bitsec/miner/jimcody1995-20260709-01/agent_manifest.json new file mode 100644 index 0000000..439727b --- /dev/null +++ b/submissions/sn60__bitsec/miner/jimcody1995-20260709-01/agent_manifest.json @@ -0,0 +1,5 @@ +{ + "schema_version": 1, + "runtime": "python", + "entrypoint": "agent.py" +} diff --git a/submissions/sn60__bitsec/miner/jimcody1995-20260709-01/helpers/__init__.py b/submissions/sn60__bitsec/miner/jimcody1995-20260709-01/helpers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/submissions/sn60__bitsec/miner/jimcody1995-20260709-01/helpers/discovery.py b/submissions/sn60__bitsec/miner/jimcody1995-20260709-01/helpers/discovery.py new file mode 100644 index 0000000..a6285ef --- /dev/null +++ b/submissions/sn60__bitsec/miner/jimcody1995-20260709-01/helpers/discovery.py @@ -0,0 +1,265 @@ +from __future__ import annotations + +import json +import re +from collections import defaultdict +from pathlib import Path +from typing import Any + +EXT = (".sol", ".vy", ".rs") +SKIP_GLOBAL = frozenset({ + ".git", ".github", "artifacts", "broadcast", "cache", "coverage", "dist", "docs", + "example", "examples", "interfaces", "lib", "mock", "mocks", "node_modules", "out", + "script", "scripts", "test", "tests", "vendor", "vendors", "target", +}) +SKIP_IN_SRC = frozenset({"test", "tests", "mock", "mocks"}) + +RE_FUNC_SOL = re.compile( + r"\bfunction\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(([^)]*)\)\s*([^{};]*)(?:;|\{)", + re.MULTILINE, +) +RE_FUNC_VY = re.compile( + r"^\s*def\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(([^)]*)\)\s*(?:->\s*([^:]+))?:", + re.MULTILINE, +) +RE_FUNC_RS = re.compile(r"\bfn\s+([A-Za-z_][A-Za-z0-9_]*)\s*[(<]") +RE_CONTRACT = re.compile( + r"\b(?:abstract\s+contract|contract|library|interface|module|struct|trait)\s+([A-Za-z_][A-Za-z0-9_]*)", + re.MULTILINE, +) +RE_IMPORT = re.compile(r'^\s*(?:import|use)\b[^;\n]*?["\']?([A-Za-z0-9_./]+)["\']?', re.MULTILINE) +RE_STATE = re.compile( + r"^\s*(?:mapping\s*\([^;]+|[A-Za-z_][A-Za-z0-9_<>,\\[\\]. ]+)\s+" + r"(?:public|private|internal|constant|immutable|override|\s)*" + r"([A-Za-z_][A-Za-z0-9_]*)\s*(?:=|;)", + re.MULTILINE, +) +RE_RISK = re.compile( + r"\b(delegatecall|selfdestruct|tx\.origin|assembly|unchecked|\.call\s*\{|" + r"onlyOwner|onlyRole|upgradeTo|initialize|withdraw|redeem|borrow|liquidat|" + r"transferFrom|ecrecover|permit|oracle|flash|swap|slippage|reentr|" + r"slot0|latestRoundData|add_liquidity|remove_liquidity|get_dy|virtual_price)\b", + re.IGNORECASE, +) +RE_EXTERNAL_FN = re.compile( + r"\bfunction\s+([A-Za-z_][A-Za-z0-9_]*)\s*\([^)]*\)\s+" + r"(?:public|external)\b[^;{]*", + re.MULTILINE | re.IGNORECASE, +) + +MAX_FILES = 70 +MAX_BYTES = 260_000 +DIGEST_CHARS = 14_000 + +PATH_HINTS = ( + "vault", "pool", "router", "bridge", "proxy", "oracle", "govern", "treasury", + "manager", "market", "lend", "borrow", "collateral", "controller", "strategy", + "auction", "token", "staking", "reward", "factory", "escrow", "swap", "stable", + "liquidity", "liquidat", +) + + +def should_skip_dir(parts: tuple[str, ...]) -> bool: + if not parts: + return False + in_src = "src" in {p.lower() for p in parts} + for part in parts: + low = part.lower() + if in_src: + if low in SKIP_IN_SRC: + return True + elif low in SKIP_GLOBAL: + return True + return False + + +def read_text(path: Path) -> str: + try: + return path.read_text(encoding="utf-8", errors="ignore") + except OSError: + return "" + + +def parse_functions(text: str, suffix: str) -> list[dict[str, str]]: + out: list[dict[str, str]] = [] + if suffix == ".vy": + for m in RE_FUNC_VY.finditer(text): + ret = f" -> {m.group(3).strip()}" if m.group(3) else "" + out.append({"name": m.group(1), "sig": f"{m.group(1)}({m.group(2).strip()}){ret}".strip()}) + elif suffix == ".rs": + for m in RE_FUNC_RS.finditer(text): + out.append({"name": m.group(1), "sig": m.group(1)}) + else: + for m in RE_FUNC_SOL.finditer(text): + tail = " ".join(m.group(3).split()) + out.append({"name": m.group(1), "sig": f"{m.group(1)}({m.group(2).strip()}) {tail}".strip()}) + return out + + +def hot_functions(text: str) -> list[str]: + hits: list[str] = [] + for m in RE_EXTERNAL_FN.finditer(text): + sig = " ".join(m.group(0).split()) + if RE_RISK.search(sig): + hits.append(sig[:150]) + elif len(hits) < 6: + hits.append(sig[:150]) + if len(hits) >= 10: + break + return hits + + +def risk_score(rel: str, text: str, graph: dict[str, set[str]]) -> int: + name_low, text_low = rel.lower(), text.lower() + score = min(text_low.count("function ") + text_low.count("\ndef ") + text_low.count("\nfn "), 34) + score += min(len(graph.get(rel, set())), 8) * 4 + for hint in PATH_HINTS: + if hint in name_low: + score += 9 + elif hint in text_low: + score += 2 + score += min(len(RE_RISK.findall(text)), 20) * 3 + if any(tok in text_low for tok in ("external", "public", "@external", "pub fn")): + score += 5 + if "initializer" in text_low or "upgrade" in text_low: + score += 5 + return score + + +def state_names(text: str) -> list[str]: + seen: list[str] = [] + for name in RE_STATE.findall(text): + if name not in seen and len(name) < 42: + seen.append(name) + return seen[:14] + + +def risk_snippets(text: str) -> list[str]: + lines: list[str] = [] + for num, line in enumerate(text.splitlines(), start=1): + if RE_RISK.search(line): + compact = " ".join(line.strip().split()) + if compact: + lines.append(f"{num}: {compact[:160]}") + if len(lines) >= 14: + break + return lines + + +def build_catalog(root: Path) -> list[dict[str, Any]]: + rows: list[dict[str, Any]] = [] + for path in sorted(root.rglob("*")): + if not path.is_file() or path.suffix.lower() not in EXT: + continue + try: + rel_path = path.relative_to(root) + if should_skip_dir(tuple(rel_path.parts[:-1])): + continue + if path.stat().st_size > MAX_BYTES: + continue + except OSError: + continue + text = read_text(path) + suffix = path.suffix.lower() + if suffix == ".rs": + has_code = "fn " in text or "pub fn" in text + else: + has_code = any(tok in text for tok in ("function", "contract ", "library ", "\ndef ")) + if not has_code: + continue + rel = rel_path.as_posix() + contracts = RE_CONTRACT.findall(text) + if not contracts: + contracts = [path.stem] + rows.append({ + "rel": rel, + "text": text, + "suffix": suffix, + "contracts": contracts, + "functions": parse_functions(text, suffix), + "imports": RE_IMPORT.findall(text), + }) + return rows[:MAX_FILES] + + +def suffix_index(catalog: list[dict[str, Any]]) -> dict[str, dict[str, Any]]: + out: dict[str, dict[str, Any]] = {} + for row in catalog: + rel = str(row["rel"]) + out[rel] = row + out[Path(rel).name] = row + for part in Path(rel).parts: + out[part] = row + return out + + +def import_graph( + catalog: list[dict[str, Any]], + lookup: dict[str, dict[str, Any]], +) -> dict[str, set[str]]: + graph: dict[str, set[str]] = defaultdict(set) + for row in catalog: + rel = str(row["rel"]) + for imp in row["imports"]: + base = imp.rsplit("/", 1)[-1] + peer = lookup.get(base) or lookup.get(imp) + if peer and peer["rel"] != rel: + graph[rel].add(str(peer["rel"])) + graph[str(peer["rel"])].add(rel) + return graph + + +def rank_catalog( + catalog: list[dict[str, Any]], + graph: dict[str, set[str]], +) -> list[dict[str, Any]]: + for row in catalog: + row["score"] = risk_score(str(row["rel"]), str(row["text"]), graph) + return sorted(catalog, key=lambda r: (-int(r["score"]), str(r["rel"]))) + + +def graph_digest(ranked: list[dict[str, Any]], graph: dict[str, set[str]]) -> str: + chunks: list[str] = [] + for row in ranked[:14]: + rel = str(row["rel"]) + chunks.append(json.dumps({ + "file": rel, + "score": row["score"], + "neighbors": sorted(graph.get(rel, set()))[:4], + "contracts": row["contracts"][:6], + "hot_functions": hot_functions(str(row["text"]))[:6], + "functions": [f["sig"][:130] for f in row["functions"][:18]], + "risk_lines": risk_snippets(str(row["text"])), + }, separators=(",", ":"))) + return "\n".join(chunks)[:DIGEST_CHARS] + + +def resolve_targets(targets: list[str], ranked: list[dict[str, Any]]) -> list[dict[str, Any]]: + by_rel = {r["rel"]: r for r in ranked} + ordered: list[dict[str, Any]] = [] + for target in targets: + for rel, row in by_rel.items(): + if target == rel or rel.endswith(target) or target.endswith(rel): + if row not in ordered: + ordered.append(row) + break + for row in ranked: + if row not in ordered: + ordered.append(row) + return ordered + + +def import_neighbors( + row: dict[str, Any], + lookup: dict[str, dict[str, Any]], + limit: int, +) -> str: + blocks: list[str] = [] + for imp in row["imports"]: + key = imp.rsplit("/", 1)[-1] + other = lookup.get(key) or lookup.get(imp) + if other and other["rel"] != row["rel"]: + blocks.append(f"// import {other['rel']}\n{str(other['text'])[:limit]}") + if len(blocks) >= 2: + break + return "\n\n".join(blocks) diff --git a/submissions/sn60__bitsec/miner/jimcody1995-20260709-01/helpers/findings.py b/submissions/sn60__bitsec/miner/jimcody1995-20260709-01/helpers/findings.py new file mode 100644 index 0000000..ef1398b --- /dev/null +++ b/submissions/sn60__bitsec/miner/jimcody1995-20260709-01/helpers/findings.py @@ -0,0 +1,110 @@ +from __future__ import annotations + +import re +from typing import Any + + +def line_number(text: str, needle: str) -> int | None: + if not needle: + return None + idx = text.find(needle) + return None if idx < 0 else text.count("\n", 0, idx) + 1 + + +def format_finding(raw: dict[str, Any], by_rel: dict[str, dict[str, Any]]) -> dict[str, Any] | None: + file_hint = str(raw.get("file") or raw.get("path") or "").strip() + if not file_hint: + return None + row = None + for rel, candidate in by_rel.items(): + if file_hint == rel or rel.endswith(file_hint) or file_hint.endswith(rel): + row, file_hint = candidate, rel + break + if row is None: + return None + severity = str(raw.get("severity") or "").lower().strip() + if severity not in {"high", "critical"}: + return None + function = str(raw.get("function") or "").strip().strip("`() ") + if "." in function: + function = function.split(".")[-1] + valid = {f["name"] for f in row["functions"]} + if function and function not in valid: + function = "" + contract = str(raw.get("contract") or "").strip().strip("`") + if not contract and row["contracts"]: + contract = str(row["contracts"][0]) + mechanism = str(raw.get("mechanism") or "").strip() + impact = str(raw.get("impact") or "").strip() + description = str(raw.get("description") or "").strip() + title = str(raw.get("title") or "").strip() + if len(mechanism) < 20 and len(description) < 100: + return None + loc = ".".join(x for x in (contract, function) if x) + if not title: + title = f"{loc or file_hint} - high-impact vulnerability" + elif loc and loc.lower() not in title.lower(): + title = f"{loc} - {title}" + where = f"In `{file_hint}`" + if contract: + where += f", contract `{contract}`" + if function: + where += f", function `{function}()`" + rebuilt = where + ". " + if mechanism: + rebuilt += "Mechanism: " + mechanism.rstrip(".") + ". " + if impact: + rebuilt += "Impact: " + impact.rstrip(".") + ". " + if description: + rebuilt += description + description = " ".join(rebuilt.split()) + if len(description) < 100: + return None + basename = file_hint.rsplit("/", 1)[-1] + loc_bits = [f"`{file_hint}`"] + if basename != file_hint: + loc_bits.append(f"`{basename}`") + if function: + loc_bits.append(f"`{function}()`") + hint = " Affected location: " + ", ".join(loc_bits) + "." + if hint.strip() not in description: + description = description.rstrip() + hint + line = raw.get("line") + if not isinstance(line, int) and function: + line = line_number(str(row["text"]), f"function {function}") + return { + "title": title[:220], + "description": description[:3000], + "severity": severity, + "file": file_hint, + "function": function, + "line": line if isinstance(line, int) else None, + "type": str(raw.get("type") or "logic"), + "confidence": 0.91 if severity == "critical" else 0.85, + } + + +def collapse_findings(items: list[dict[str, Any]], cap: int = 8) -> list[dict[str, Any]]: + seen: set[tuple[str, str, str]] = set() + out: list[dict[str, Any]] = [] + for item in sorted( + items, + key=lambda f: ( + f.get("severity") == "critical", + float(f.get("confidence") or 0), + len(str(f.get("description"))), + ), + reverse=True, + ): + key = ( + str(item.get("file") or "").lower(), + str(item.get("function") or "").lower(), + str(item.get("title") or "").lower()[:110], + ) + if key in seen: + continue + seen.add(key) + out.append(item) + if len(out) >= cap: + break + return out diff --git a/submissions/sn60__bitsec/miner/jimcody1995-20260709-01/helpers/llm.py b/submissions/sn60__bitsec/miner/jimcody1995-20260709-01/helpers/llm.py new file mode 100644 index 0000000..8b89590 --- /dev/null +++ b/submissions/sn60__bitsec/miner/jimcody1995-20260709-01/helpers/llm.py @@ -0,0 +1,118 @@ +from __future__ import annotations + +import json +import os +import re +import time +import urllib.error +import urllib.request +from typing import Any + +HTTP_WAIT = 145 +MAX_CALLS = 3 + + +class CallBudget: + def __init__(self) -> None: + self.used = 0 + + def can_call(self) -> bool: + return self.used < MAX_CALLS + + def mark(self) -> None: + self.used += 1 + + +def infer( + api: str | None, + msgs: list[dict[str, str]], + token_cap: int, + budget: CallBudget, +) -> str: + if not budget.can_call(): + return "" + endpoint = (api or os.environ.get("INFERENCE_API") or "").rstrip("/") + if not endpoint: + return "" + payload = json.dumps({ + "messages": msgs, + "max_tokens": token_cap, + }).encode("utf-8") + headers = { + "Content-Type": "application/json", + "x-inference-api-key": os.environ.get("INFERENCE_API_KEY", ""), + } + last: Exception | None = None + for attempt in range(2): + try: + req = urllib.request.Request(endpoint + "/inference", data=payload, method="POST", headers=headers) + with urllib.request.urlopen(req, timeout=HTTP_WAIT) as resp: + budget.mark() + return pull_text(json.loads(resp.read().decode("utf-8", "replace"))) + except urllib.error.HTTPError as exc: + if exc.code == 429: + return "" + last = exc + except (OSError, ValueError, TimeoutError) as exc: + last = exc + if attempt < 1: + time.sleep(1.0) + return "" + + +def pull_text(payload: dict[str, Any]) -> str: + choices = payload.get("choices") + if not isinstance(choices, list) or not choices: + return "" + msg = choices[0].get("message") if isinstance(choices[0], dict) else None + if not isinstance(msg, dict): + return "" + content = msg.get("content") + if isinstance(content, str): + return content + if isinstance(content, list): + return "".join(str(part.get("text") or "") for part in content if isinstance(part, dict)) + return "" + + +def load_json(text: str) -> dict[str, Any]: + stripped = text.strip() + if not stripped: + return {} + if stripped.startswith("```"): + stripped = re.sub(r"^```[a-zA-Z]*\s*", "", stripped) + stripped = re.sub(r"\s*```$", "", stripped) + try: + obj = json.loads(stripped) + return obj if isinstance(obj, dict) else {} + except json.JSONDecodeError: + pass + start = stripped.find("{") + if start < 0: + return {} + depth = 0 + in_str = False + esc = False + for idx in range(start, len(stripped)): + ch = stripped[idx] + if in_str: + if esc: + esc = False + elif ch == "\\": + esc = True + elif ch == '"': + in_str = False + continue + if ch == '"': + in_str = True + elif ch == "{": + depth += 1 + elif ch == "}": + depth -= 1 + if depth == 0: + try: + obj = json.loads(stripped[start : idx + 1]) + return obj if isinstance(obj, dict) else {} + except json.JSONDecodeError: + return {} + return {} diff --git a/submissions/sn60__bitsec/miner/jimcody1995-20260709-01/submission.json b/submissions/sn60__bitsec/miner/jimcody1995-20260709-01/submission.json new file mode 100644 index 0000000..c34e92b --- /dev/null +++ b/submissions/sn60__bitsec/miner/jimcody1995-20260709-01/submission.json @@ -0,0 +1,10 @@ +{ + "schema_version": 2, + "subnet_pack": "sn60__bitsec", + "mode": "miner", + "submission_id": "jimcody1995-20260709-01", + "created_at": "2026-07-09T17:40:00+00:00", + "author": "jimcody1995", + "title": "Depth-first graph-ranked miner (replica-stable)", + "notes": "July 2026 rules: 3 calls, 150k input cap, 2/3 replica pass scoring. Graph triage plus two depth-first deep audits via helpers/." +}