Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -106,9 +106,10 @@ produces a result no main-conference reviewer will believe.
budget it was sized against, and give a one-line reason the size is
appropriate. If you deliberately use a small model, the reason must be a
research reason, not "it was easier / faster to train".
4. **Reviewer blocker.** A headline run on a stale or sub-~8B backbone while
large GPUs sit underused is a hard blocker, the same as a self-written
training loop. Fix the backbone before claiming the run stage complete.
4. **Headline boundary.** A stale backbone may remain a compatibility baseline,
but it cannot carry the paper's main empirical claim when a relevant current
generation is available. Parameter count alone is not the rule: verify model
generation, architecture, task capability, context support, and release date.

## 🔥 Hardware saturation contract (run stage)

Expand Down
1 change: 0 additions & 1 deletion argus_skill/core/secret_guard.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -46,7 +46,6 @@
),
r"\1 <REDACTED:secret>\2",
),
(re.compile(r"\bsk-[A-Za-z0-9_\-]{16,}"), "<REDACTED:openai-key>"),
(re.compile(r"gh[pousr]_[A-Za-z0-9]{20,}"), "<REDACTED:github-token>"),
(re.compile(r"xox[baprs]-[A-Za-z0-9\-]{10,}"), "<REDACTED:slack-token>"),
(re.compile(r"AKIA[0-9A-Z]{16}"), "<REDACTED:aws-key>"),
Expand Down
27 changes: 24 additions & 3 deletions argus_skill/life/supervisor/_planning_cycle_enqueue.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -74,6 +74,13 @@ def _research_stage_ready_for_close(
or str(pipeline.get("current_stage") or "").strip() != "research"
):
return False
selection = evidence_root / "research" / "IDEA_SELECTION.json"
positioning = evidence_root / "paper" / "novelty_audit.md"
grounding = evidence_root / "research" / "LITERATURE_GROUNDING.json"
if not selection.is_file() or not (
positioning.is_file() or grounding.is_file()
):
return False
definition = load_vertical("research", project_root=state_root)
return not vertical_stage_completion_issues(
definition,
Expand DownExpand Up@@ -313,12 +320,27 @@ def _pc_build_pending_items(self, state: _PlanCycleState) -> Any | None:
state_reader = getattr(self, "_artifact_root", None)
state_root = state_reader() if callable(state_reader) else Path(context_root)
auto_close_research = (
len(planned_tasks) == 1
and _research_stage_ready_for_close(
_research_stage_ready_for_close(
state_root=Path(state_root),
evidence_root=Path(context_root).resolve(),
)
)
if auto_close_research:
try:
from ...skills.stage_machine import advance_stage

advance_stage(
state_root,
target_stage="plan",
reason="selected research target and positioning are complete",
advanced_by="manager:auto_completion",
evidence_root=Path(context_root).resolve(),
)
# The tasks were authored under the old research-stage context.
# Replan immediately so they cannot become stale closeout work in plan.
return PLAN_RETRY
except Exception: # noqa: BLE001 - normal Manager planning remains available
log.debug("automatic research stage advance failed", exc_info=True)
for task in planned_tasks:
task = replace(task, context_refs=[], execution_workdir="")
sanitized_title = _sanitize_planner_task_text(task.title)
Expand DownExpand Up@@ -379,7 +401,6 @@ def _pc_build_pending_items(self, state: _PlanCycleState) -> Any | None:
canonical_scope == PLANNER_SCOPE_FINAL_SUBMISSION
or getattr(task, "stage_repair", False)
or _stage_closing_forced()
or auto_close_research
)
canonical_require_review = (
canonical_stage_closing or _independent_review_forced()
Expand Down
4 changes: 4 additions & 0 deletions argus_skill/verticals/research/library_preparation.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,6 +21,10 @@ def prepare_skill_libraries(context: VerticalLibraryContext) -> None:

if resolve_research_target_level(context.workdir) == "exploratory":
return
if context.stage in {"plan", "benchmark", "run"}:
context.required_skill_paths.append(
"engineer/training-infrastructure-guide.md"
)
from .idea_portfolio import (
QUORUM_COUNT,
SELECTION_POLICY,
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -82,8 +82,11 @@ human cohort, or systems measurement.
0. **Build the project research platform.** The Engineer may create the
project-local environment, data/model bindings, evaluator, runner, telemetry,
and teardown tooling needed by the research question. Run the real entrypoint
on the smallest faithful case and retain its native output. Platform failures
route back to Engineer repair and are not evidence about the scientific idea.
on the smallest faithful case and retain its native output, but label that run
plumbing-only. Before claim-bearing execution, query the live model catalog and
move to the current-generation backbone selected in the plan; a cached or familiar
previous-generation model cannot become headline evidence by inertia. Platform
failures route back to Engineer repair and are not evidence about the scientific idea.
1. **Smoke the real path.** Run the smallest faithful end-to-end public-data or
official-evaluator check that catches wiring errors.
2. **Execute the preregistered comparison.** Keep data, metric, compute, and
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -156,6 +156,7 @@ Return JSON:

## Infrastructure validity
Flag infrastructure only when it invalidates the comparison, measurement, or
claim. Do not reject a custom runtime, small model, CPU path, or unbatched
execution merely because a larger/faster setup was available; those choices may
be the research subject or a controlled design decision.
claim. A small or older model is acceptable when model scale is the research
subject or when it is explicitly labeled plumbing/compatibility evidence. Do not
accept it as headline evidence when the plan requires a current-generation
backbone and relevant current models are available.
37 changes: 37 additions & 0 deletions argus_skill/verticals/research/stages.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -131,6 +131,24 @@ def _checklist(*items: ChecklistItem) -> tuple[ChecklistItem, ...]:
),
),
"plan": _checklist(
ChecklistItem(
id="plan.backbone",
statement=(
"For model-backed experiments, select the headline backbone from a "
"current open model generation after checking the live model catalog, "
"release dates, architecture, context support, and relevant leaderboard "
"or official evaluations. Record exact org/model id, release date, "
"parameter count, attention/KV architecture, and why it tests this claim. "
"Previous-generation models may be plumbing or compatibility baselines, "
"never the primary publication evidence merely because they are cached, "
"familiar, or easy to fit. Read `argus_builtin_skills/engineer/"
"training-infrastructure-guide.md` before locking the plan."
),
evidence_hint=(
"research/INFRA_CHOICE.md + research/EXPERIMENT_PLAN.md model table "
"with dated current-generation comparison"
),
),
ChecklistItem(
id="plan.experiment",
statement=(
Expand DownExpand Up@@ -193,6 +211,15 @@ def _checklist(*items: ChecklistItem) -> tuple[ChecklistItem, ...]:
),
),
"benchmark": _checklist(
ChecklistItem(
id="benchmark.backbone",
statement=(
"The real benchmark path loads the current-generation headline model "
"locked in plan.backbone. Legacy/small-model plumbing remains labeled "
"non-headline and cannot substitute for the current model run."
),
evidence_hint="run manifest model revision + research/INFRA_CHOICE.md",
),
ChecklistItem(
id="benchmark.environment_preflight",
statement=(
Expand DownExpand Up@@ -266,6 +293,16 @@ def _checklist(*items: ChecklistItem) -> tuple[ChecklistItem, ...]:
),
),
"run": _checklist(
ChecklistItem(
id="run.backbone",
statement=(
"Headline result artifacts identify and actually execute the planned "
"current-generation backbone. If the live catalog has materially moved "
"since planning, refresh the choice before expensive reruns. Older-model "
"results remain compatibility evidence, not the paper's main result."
),
evidence_hint="experiment manifests + model revision/release metadata",
),
ChecklistItem(
id="run.environment_preflight",
statement=(
Expand Down
27 changes: 26 additions & 1 deletion tests/life/test_research_stage_auto_close.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,10 +22,15 @@ def test_research_stage_ready_when_deterministic_blockers_are_empty(
"argus_skill.verticals._base.vertical_stage_completion_issues",
lambda *_args, **_kwargs: (),
)
evidence_root = tmp_path / "workdir"
(evidence_root / "research").mkdir(parents=True)
(evidence_root / "paper").mkdir()
(evidence_root / "research" / "IDEA_SELECTION.json").write_text("{}")
(evidence_root / "paper" / "novelty_audit.md").write_text("positioned\n")

assert module._research_stage_ready_for_close(
state_root=tmp_path / "state",
evidence_root=tmp_path / "workdir",
evidence_root=evidence_root,
)


Expand All@@ -45,6 +50,26 @@ def test_research_stage_does_not_close_with_blockers(
"argus_skill.verticals._base.vertical_stage_completion_issues",
lambda *_args, **_kwargs: ("selection incomplete",),
)
evidence_root = tmp_path / "workdir"
(evidence_root / "research").mkdir(parents=True)
(evidence_root / "paper").mkdir()
(evidence_root / "research" / "IDEA_SELECTION.json").write_text("{}")
(evidence_root / "paper" / "novelty_audit.md").write_text("positioned\n")

assert not module._research_stage_ready_for_close(
state_root=tmp_path / "state",
evidence_root=evidence_root,
)


def test_research_stage_does_not_close_without_core_artifacts(
tmp_path: Path,
monkeypatch,
) -> None:
monkeypatch.setattr(
"argus_skill.core.pipeline_state.read_pipeline_state",
lambda _root: {"vertical": "research", "current_stage": "research"},
)

assert not module._research_stage_ready_for_close(
state_root=tmp_path / "state",
Expand Down
28 changes: 28 additions & 0 deletions tests/skills/test_research_idea_portfolio.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -497,6 +497,34 @@ def test_research_library_hook_forms_quorum_pipeline(
assert len(task_board.snapshot(Path(events[0]["team_root"]))) == 24


def test_research_library_requires_training_guide_after_selection(
tmp_path: Path,
monkeypatch,
) -> None:
_pipeline(tmp_path)
monkeypatch.setenv("ARGUS_SKILL_VENUE_RESEARCH", "0")
monkeypatch.setenv("ARGUS_SKILL_IDEA_SEARCH", "0")
required: list[str] = []

prepare_skill_libraries(
VerticalLibraryContext(
workdir=tmp_path,
stage="plan",
objective="design current-model experiments",
direction="locked",
workflow_mode="staged",
paper_mission=True,
team_task_id=None,
runner=None,
model=None,
emit=lambda _event: None,
required_skill_paths=required,
)
)
assert "engineer/training-infrastructure-guide.md" in required
assert "engineer/training-infrastructure-guide.md" in required


def test_research_library_hook_never_recurses_inside_team_task(
tmp_path: Path,
monkeypatch,
Expand Down
19 changes: 19 additions & 0 deletions tests/skills/test_research_protocol_quality.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -161,6 +161,25 @@ def test_research_selector_prioritizes_frontier_ambition_over_local_ease() -> No
)


def test_research_plan_and_run_require_current_generation_backbone() -> None:
plan = {item.id: item.statement for item in STAGE_CHECKLISTS["plan"]}
benchmark = {item.id: item.statement for item in STAGE_CHECKLISTS["benchmark"]}
run = {item.id: item.statement for item in STAGE_CHECKLISTS["run"]}
runner = _skill("engineer/research-experiment-runner.md")
results_review = _skill("reviewer/experiment-results-review.md")

assert "current open model generation" in plan["plan.backbone"]
assert "live model catalog" in plan["plan.backbone"]
assert "never the primary publication evidence" in plan["plan.backbone"]
assert "current-generation headline model" in benchmark["benchmark.backbone"]
assert "actually execute" in run["run.backbone"]
assert "plumbing-only" in runner
assert "cannot become headline evidence by inertia" in runner
assert "Do not accept it as headline evidence" in " ".join(
results_review.split()
)


def test_literature_grounding_advises_ai_and_foundation_balance() -> None:
discovery = " ".join(_skill("engineer/idea-discovery.md").split())
pipeline = " ".join(_skill("engineer/auto-research-pipeline.md").split())
Expand Down
Loading