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
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Façade repo for Prophet command surface and SourceOS / AgentPlane bootstrap del
| `prophet sourceos office ...` | `sourceosctl office ...` | `SourceOS-Linux/sourceos-devtools` |
| `prophet sourceos agent-term ...` | `agent-term ...` | `SourceOS-Linux/agent-term` |
| `prophet agentplane ...` | `sp-run ...` | `SocioProphet/agentplane` |
| `prophet governed-runner ...` | `sp-run ...` | `SocioProphet/agentplane` |

## Examples

Expand All @@ -40,6 +41,11 @@ prophet agentplane preflight ./governed-run-contract.json
prophet agentplane admit ./governed-run-contract.json --preflight ./preflight-receipt.json --authority-state ./agent-authority-current-state.json --projected-cost-usd 0.25
prophet agentplane dossier ./.socioprophet/runs/governed-run-alpha-001
prophet agentplane validate-dossier ./run-dossier.json
prophet governed-runner doctor
prophet governed-runner preflight ./governed-run-contract.json
prophet governed-runner admit ./governed-run-contract.json --preflight ./preflight-receipt.json --authority-state ./agent-authority-current-state.json --projected-cost-usd 0.25
prophet governed-runner dossier ./.socioprophet/runs/governed-run-alpha-001
prophet governed-runner validate-dossier ./run-dossier.json
```

## Install path
Expand All @@ -61,6 +67,7 @@ For AgentPlane governed-runner commands, install or expose the AgentPlane-owned
python3 -m pip install -e /path/to/agentplane
sp-run doctor
prophet agentplane doctor
prophet governed-runner doctor
```

## Boundary
Expand All @@ -84,4 +91,4 @@ This repo does not own:

Those remain in their owning repositories.

`prophet agentplane ...` is a facade over `sp-run ...`; the implementation remains in `SocioProphet/agentplane`.
`prophet agentplane ...` and `prophet governed-runner ...` are facades over `sp-run ...`; the implementation remains in `SocioProphet/agentplane`.
13 changes: 9 additions & 4 deletions src/prophet_cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ def _delegate(binary: str, args: Sequence[str]) -> int:
return int(completed.returncode)


def _add_sp_run_delegate(sub: argparse._SubParsersAction, name: str, help_text: str) -> None:
parser = sub.add_parser(name, help=help_text)
parser.add_argument("args", nargs=argparse.REMAINDER, help="Arguments passed to sp-run")


def build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
prog="prophet",
Expand Down Expand Up @@ -67,8 +72,8 @@ def build_parser() -> argparse.ArgumentParser:
agent_term = sourceos_sub.add_parser("agent-term", help="Delegate AgentTerm commands")
agent_term.add_argument("args", nargs=argparse.REMAINDER, help="Arguments passed to agent-term")

agentplane = sub.add_parser("agentplane", help="Delegate AgentPlane governed-runner commands")
agentplane.add_argument("args", nargs=argparse.REMAINDER, help="Arguments passed to sp-run")
_add_sp_run_delegate(sub, "agentplane", "Delegate AgentPlane governed-runner commands")
_add_sp_run_delegate(sub, "governed-runner", "Delegate governed-runner commands")

return parser

Expand All @@ -91,12 +96,12 @@ def main(argv: list[str] | None = None) -> int:
if args.sourceos_command == "agent-term":
return _delegate("agent-term", list(args.args))

if args.command == "agentplane":
if args.command in {"agentplane", "governed-runner"}:
return _delegate("sp-run", list(args.args))

parser.error("unknown command")
return 2


if __name__ == "__main__":
raise SystemExit(main(sys.argv[1:]))
raise SystemExit(main(sys.argv[1:]))
67 changes: 66 additions & 1 deletion tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,60 @@ def fake_run(cmd, check=False):
]]


def test_governed_runner_alias_delegates_to_sp_run(monkeypatch):
calls: list[list[str]] = []

monkeypatch.setattr("shutil.which", lambda binary: f"/usr/bin/{binary}")

def fake_run(cmd, check=False):
calls.append(cmd)
assert check is False
return Completed(0)

monkeypatch.setattr(subprocess, "run", fake_run)

rc = main(["governed-runner", "doctor"])

assert rc == 0
assert calls == [["/usr/bin/sp-run", "doctor"]]


def test_governed_runner_dossier_delegates_to_sp_run(monkeypatch):
calls: list[list[str]] = []

monkeypatch.setattr("shutil.which", lambda binary: f"/usr/bin/{binary}")

def fake_run(cmd, check=False):
calls.append(cmd)
assert check is False
return Completed(0)

monkeypatch.setattr(subprocess, "run", fake_run)

rc = main(["governed-runner", "dossier", ".socioprophet/runs/demo"])

assert rc == 0
assert calls == [["/usr/bin/sp-run", "dossier", ".socioprophet/runs/demo"]]


def test_governed_runner_validate_dossier_delegates_to_sp_run(monkeypatch):
calls: list[list[str]] = []

monkeypatch.setattr("shutil.which", lambda binary: f"/usr/bin/{binary}")

def fake_run(cmd, check=False):
calls.append(cmd)
assert check is False
return Completed(0)

monkeypatch.setattr(subprocess, "run", fake_run)

rc = main(["governed-runner", "validate-dossier", "run-dossier.json"])

assert rc == 0
assert calls == [["/usr/bin/sp-run", "validate-dossier", "run-dossier.json"]]


def test_missing_delegate_returns_127(monkeypatch, capsys):
monkeypatch.setattr("shutil.which", lambda binary: None)

Expand All @@ -207,4 +261,15 @@ def test_missing_sp_run_delegate_returns_127(monkeypatch, capsys):
captured = capsys.readouterr()
assert rc == 127
assert "required delegate not found: sp-run" in captured.err
assert "AgentPlane" in captured.err
assert "AgentPlane" in captured.err


def test_missing_sp_run_for_governed_runner_alias_returns_127(monkeypatch, capsys):
monkeypatch.setattr("shutil.which", lambda binary: None)

rc = main(["governed-runner", "doctor"])

captured = capsys.readouterr()
assert rc == 127
assert "required delegate not found: sp-run" in captured.err
assert "AgentPlane" in captured.err
Loading