Files
openworker/tests/test_devsecops_team.py
Rohit C Prasad 19e10f0e76 Shipping lineup: remove Chat, ship Code disabled, gate unshipped personas
Manifests carry ships/group; release builds hide ships:false coworkers (OPENWORKER_UNSHIPPED=1 restores them).
Persona detail serves bundle media; staffing gate reads the registry, not the filtered list.
2026-08-20 17:59:48 -07:00

81 lines
3.2 KiB
Python

"""The DevSecOps team bundle (eighteenth pass) — lead + three worker variants.
The team is worker-VARIANT manifests over the solo security personas' bundles:
prompts talk to a lead, tool bundles and skills carry over. Doctrine locks under
test: the capability firebreak (the lead carries no shell/git), workers never
surface in the picker, skills ship inside each bundle (OPE-58 shape), and the
secrets-are-radioactive rule appears in every prompt that can meet a secret.
"""
from __future__ import annotations
from pathlib import Path
from coworker.personas.registry import PersonaRegistry
ROSTER = ("appsec-worker", "secrets-worker", "posture-worker")
def _reg(tmp_path) -> PersonaRegistry:
return PersonaRegistry(state_path=tmp_path / "personas.json")
def test_bundle_registers_with_team_traits(tmp_path):
reg = _reg(tmp_path)
lead = reg.get("devsecops-lead")
assert lead.manifest.team == "lead"
for pid in ROSTER:
assert reg.get(pid).manifest.team == "worker"
def test_lead_carries_no_execution_tools(tmp_path):
# The capability firebreak: leads coordinate; scanning/fixing needs shell+git,
# which only the workers carry.
reg = _reg(tmp_path)
assert "shell" not in reg.get("devsecops-lead").tools
assert "git" not in reg.get("devsecops-lead").tools
for pid in ROSTER:
assert {"shell", "git"} <= set(reg.get(pid).tools)
def test_workers_never_surface_lead_does(tmp_path, monkeypatch):
monkeypatch.setenv("OPENWORKER_UNSHIPPED", "1") # teams are ships:false — internal builds
reg = _reg(tmp_path)
ids = [e["name"] for e in reg.sidebar()]
assert "devsecops-lead" in ids
assert not any(pid in ids for pid in ROSTER)
def test_worker_bundles_ship_their_skills(tmp_path):
# OPE-58 bundle shape: the manifest's skills: list names folders that live in a
# sibling skills/ dir — self-contained, no reach into the solo personas.
reg = _reg(tmp_path)
for pid in ROSTER:
m = reg.get(pid).manifest
assert m.skills, pid
skills_dir = Path(m.source).parent / "skills"
for skill in m.skills:
assert (skills_dir / skill / "SKILL.md").is_file(), f"{pid}: {skill}"
def test_prompts_carry_the_load_bearing_rules(tmp_path):
reg = _reg(tmp_path)
lead_prompt = reg.get("devsecops-lead").manifest.system_prompt
# Falsifiable-claims criteria convention + evidence-based review + the one-time
# board chip are the lead-contract deltas of the sixteenth/seventeenth passes.
assert "FALSIFIABLE" in lead_prompt
assert "(board:)" in lead_prompt
assert "evidence" in lead_prompt.lower()
for pid in ("appsec-worker", "secrets-worker"):
prompt = reg.get(pid).manifest.system_prompt
assert "never print a discovered secret's value" in prompt.lower()
# Workers talk to the lead, never the end user.
for pid in ROSTER:
assert "ask_user" in reg.get(pid).manifest.system_prompt # the "never use" line
def test_posture_worker_is_read_only_on_cloud(tmp_path):
prompt = _reg(tmp_path).get("posture-worker").manifest.system_prompt
assert "read-only" in prompt
assert "terraform apply" in prompt # the never-apply rule is written down