chore(agnosticism): close the audit residue — B6/B8/B10 + three MAJORs (#587)

Thread the deployer's product name through the X reply + feature-spotlight
prompts (B6 leftover; release/video paths shipped in #570); make the
docs-site repo/URL config (ROBOCO_DOCS_SITE_*, defaults unchanged) instead
of a roboco-website hardcode (B8); de-assert our repo from the Main PM
prompt (B10); derive PR labels from the real target branch instead of
literal to-master/to-slave; drop the stale headcount from base.md; and
make the bash-guard's Makefile check require an actual quality/gate/lint/
test target before denying raw package-manager commands (no more
false-remediation loop on Go/Rust Makefiles).

Co-authored-by: Renn F <rennf93@users.noreply.github.com>
This commit is contained in:
Renzo F
2026-07-19 17:52:17 +02:00
committed by GitHub
co-authored by Renn F
parent 29f7082030
commit 5b27a443e9
15 changed files with 234 additions and 76 deletions
+29
View File
@@ -8,6 +8,7 @@ from uuid import uuid4
import pytest
import pytest_asyncio
from roboco.config import settings
from roboco.db.tables import AgentTable, ProjectTable, TaskTable
from roboco.models import AgentRole, AgentStatus, Team
from roboco.models.base import (
@@ -24,6 +25,7 @@ from roboco.services.base import (
from roboco.services.docs import (
DocsService,
WriteDocInput,
_refused_doc_types,
get_docs_service,
)
from sqlalchemy import select
@@ -183,6 +185,33 @@ async def test_write_doc_user_facing_refused(docs_setup: dict) -> None:
assert "docs.roboco.tech" in str(exc_info.value)
def test_refused_doc_types_uses_configured_docs_site(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""A deployer's own docs-site slug/URL (ROBOCO_DOCS_SITE_*) reaches the
refusal message instead of RoboCo's own docs site."""
monkeypatch.setattr(settings, "docs_site_project_slug", "acme-docs")
monkeypatch.setattr(settings, "docs_site_public_url", "docs.acme.example")
message = _refused_doc_types()["user_facing"]
assert "acme-docs" in message
assert "docs.acme.example" in message
assert "roboco-website" not in message
assert "docs.roboco.tech" not in message
def test_refused_doc_types_falls_back_when_unset(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""An empty docs-site slug/URL degrades to a generic message, never a
bare empty string spliced into the refusal text."""
monkeypatch.setattr(settings, "docs_site_project_slug", "")
monkeypatch.setattr(settings, "docs_site_public_url", "")
message = _refused_doc_types()["user_facing"]
assert "your docs-site project" in message
assert "roboco-website" not in message
assert "docs.roboco.tech" not in message
@pytest.mark.asyncio
async def test_write_doc_path_traversal_in_filename(docs_setup: dict) -> None:
svc = docs_setup["svc"]
@@ -68,10 +68,14 @@ def test_main_pm_prompt_covers_both_monorepo_and_multirepo() -> None:
assert "not" in prompt and "a separate repo" in prompt
def test_main_pm_prompt_names_prompter_monorepo_case() -> None:
"""The concrete Prompter case (all cells = one repo) is stated."""
def test_main_pm_prompt_frames_monorepo_as_per_deployment_fact() -> None:
"""The monorepo case is illustrated generically, not asserted as a fact
about a specific repo the Main PM is told to confirm the shape from
each cell's ``project_slug``, never assume one deployment's config
(this repo's own `rennf93/roboco`) applies to every Product."""
prompt = _composed_prompt_for(AgentRole.MAIN_PM)
assert "github.com/rennf93/roboco" in prompt
assert "per-deployment fact you confirm from each cell's" in prompt
assert "github.com/rennf93/roboco" not in prompt
# --------------------------------------------------------------------------
+36
View File
@@ -14,6 +14,7 @@ from roboco.foundation.policy.pr_labels import (
def test_root_master_megatask_main_pm() -> None:
# submit_root on a MegaTask root-subtask: root->master, main_pm, batch member.
labels = derive_pr_labels(
base_branch="master",
is_root_pr=True,
task_team=Team.MAIN_PM,
batch_id=uuid4(),
@@ -24,6 +25,7 @@ def test_root_master_megatask_main_pm() -> None:
def test_root_master_main_pm_no_batch() -> None:
labels = derive_pr_labels(
base_branch="master",
is_root_pr=True,
task_team=Team.MAIN_PM,
batch_id=None,
@@ -35,6 +37,7 @@ def test_root_master_main_pm_no_batch() -> None:
def test_cell_to_root_assembled() -> None:
# submit_up: cell->root PR, base is the integration branch (not default).
labels = derive_pr_labels(
base_branch="slave",
is_root_pr=False,
task_team=Team.BACKEND,
batch_id=None,
@@ -45,6 +48,7 @@ def test_cell_to_root_assembled() -> None:
def test_leaf_dev_pr() -> None:
labels = derive_pr_labels(
base_branch="slave",
is_root_pr=False,
task_team=Team.FRONTEND,
batch_id=None,
@@ -56,6 +60,7 @@ def test_leaf_dev_pr() -> None:
def test_freeform_pr_no_task() -> None:
# task_id None: no team, no batch — just the tree + root flags.
labels = derive_pr_labels(
base_branch="slave",
is_root_pr=False,
task_team=None,
batch_id=None,
@@ -66,6 +71,7 @@ def test_freeform_pr_no_task() -> None:
def test_freeform_root_pr_no_task() -> None:
labels = derive_pr_labels(
base_branch="master",
is_root_pr=True,
task_team=None,
batch_id=None,
@@ -77,6 +83,7 @@ def test_freeform_root_pr_no_task() -> None:
def test_accepts_string_team_value() -> None:
# callers pass ORM enum members OR their .value strings (mirrors batch.py).
labels = derive_pr_labels(
base_branch="slave",
is_root_pr=False,
task_team="main_pm",
batch_id=None,
@@ -92,9 +99,38 @@ def test_conventions_pr_labels_static() -> None:
def test_no_duplicates() -> None:
# a shape that could repeat a label still yields a unique list.
labels = derive_pr_labels(
base_branch="master",
is_root_pr=True,
task_team=Team.MAIN_PM,
batch_id=uuid4(),
has_children=True,
)
assert len(labels) == len(set(labels))
def test_label_reflects_real_base_branch_not_is_root_pr() -> None:
"""The ``to {base}`` label is driven entirely by the PR's actual target,
not derived from ``is_root_pr`` a non-root PR whose real base happens to
be "master" (or any project-specific env-ladder rung) must say so, not
hardcode "to slave" just because it isn't a root PR."""
labels = derive_pr_labels(
base_branch="main",
is_root_pr=False,
task_team=Team.BACKEND,
batch_id=None,
has_children=False,
)
assert labels[0] == "to main"
def test_label_reflects_project_specific_env_ladder_rung() -> None:
# A root PR targeting a project's own env-ladder head rung, not literal
# "master" — the deployer's real prod-branch name flows through verbatim.
labels = derive_pr_labels(
base_branch="production",
is_root_pr=True,
task_team=Team.MAIN_PM,
batch_id=None,
has_children=True,
)
assert labels == ["to production", "root", "main-pm"]
@@ -2,11 +2,13 @@
CEO item: force agents to the Makefile. The existing hook deliberately allowed
bare ``uv run`` (workspace .venv, cwd-relative); this guard overrides that by
CEO direction when a ``Makefile`` is present, denying raw package-manager /
test-runner commands and remediating to the make targets. Skipped when no
Makefile exists so Makefile-less projects aren't blocked. On the grok path
(``ROBOCO_GUARD_SKIP_PM=1``) a deny cancels the whole run, so it nudges (exit 0)
instead.
CEO direction when a ``Makefile`` is present AND declares at least one of the
quality/gate/lint/test targets, denying raw package-manager / test-runner
commands and remediating to the make targets. Skipped when no Makefile exists,
or when one exists but declares none of those targets (a Go/Rust Makefile with
only build/run existence alone would remediate into a dead end). On the grok
path (``ROBOCO_GUARD_SKIP_PM=1``) a deny cancels the whole run, so it nudges
(exit 0) instead.
"""
from __future__ import annotations
@@ -79,6 +81,24 @@ def test_skips_deny_without_makefile(tmp_path: Path) -> None:
assert rc != _DENIED
def test_skips_deny_when_makefile_lacks_remediation_targets(tmp_path: Path) -> None:
"""A Go/Rust-style Makefile with only build/run targets — existence alone
must not deny+remediate to a `make quality`/`gate`/`lint`/`test` that
doesn't exist (the false-remediation dead-end loop the content check
closes)."""
(tmp_path / "Makefile").write_text("build:\n\tgo build ./...\nrun:\n\tgo run .\n")
rc, _ = _run_hook("uv run pytest", tmp_path)
assert rc != _DENIED
def test_denies_when_makefile_has_only_one_remediation_target(tmp_path: Path) -> None:
"""Just one of quality/gate/lint/test is enough to arm the deny — the
guard doesn't require all four."""
(tmp_path / "Makefile").write_text("lint:\n\truff check .\n")
rc, _ = _run_hook("uv run pytest", tmp_path)
assert rc == _DENIED
def test_grok_path_nudges_not_denies() -> None:
"""ROBOCO_GUARD_SKIP_PM=1 (grok) -> exit 0 nudge, not run-canceling exit 2."""
rc, err = _run_hook("uv run pytest", REPO_ROOT, {"ROBOCO_GUARD_SKIP_PM": "1"})