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
23 changes: 20 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# prophet-cli

Façade repo for Prophet command surface and SourceOS bootstrap delegation.
Façade repo for Prophet command surface and SourceOS / AgentPlane bootstrap delegation.

`prophet` is the stable operator-facing command. It does not duplicate implementation logic that belongs in SourceOS or AgentTerm repositories.
`prophet` is the stable operator-facing command. It does not duplicate implementation logic that belongs in SourceOS, AgentTerm, or AgentPlane repositories.

## Delegation model

Expand All @@ -14,6 +14,7 @@ Façade repo for Prophet command surface and SourceOS bootstrap delegation.
| `prophet sourceos agent-machine ...` | `sourceosctl agent-machine ...` | `SourceOS-Linux/sourceos-devtools` |
| `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` |

## Examples

Expand All @@ -34,6 +35,11 @@ prophet sourceos office plan --artifact-type slide-deck --format pptx --title "D
prophet sourceos office generate --dry-run --artifact-type document --format docx --title "Demo Report"
prophet sourceos office convert ./example.docx --to pdf --dry-run
prophet sourceos agent-term office create-deck '!prophet-workspace' --workroom workroom-demo-0001 --title 'Demo Briefing Deck'
prophet agentplane doctor
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
```

## Install path
Expand All @@ -49,6 +55,14 @@ brew install agent-term

`prophet-cli` only provides the `prophet` facade. The delegated binaries must also be installed or available on `PATH`.

For AgentPlane governed-runner commands, install or expose the AgentPlane-owned `sp-run` delegate from `SocioProphet/agentplane`:

```bash
python3 -m pip install -e /path/to/agentplane
sp-run doctor
prophet agentplane doctor
```

## Boundary

This repo does not own:
Expand All @@ -64,7 +78,10 @@ This repo does not own:
- LibreOffice, Collabora, ONLYOFFICE, Microsoft Graph, or Google Workspace adapters;
- AgentTerm event log semantics;
- AgentPlane evidence contracts;
- Agent Registry grants;
- AgentPlane governed-runner implementation;
- Agent Registry grants or authority state;
- Homebrew formulae.

Those remain in their owning repositories.

`prophet agentplane ...` is a facade over `sp-run ...`; the implementation remains in `SocioProphet/agentplane`.
13 changes: 10 additions & 3 deletions src/prophet_cli/cli.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""Prophet facade CLI.

The `prophet` command is a stable operator-facing facade. It delegates local
SourceOS implementation work to the owning CLIs instead of duplicating engine
logic here.
SourceOS and AgentPlane implementation work to the owning CLIs instead of
duplicating engine logic here.
"""

from __future__ import annotations
Expand All @@ -19,6 +19,7 @@
DELEGATES = {
"sourceosctl": "Install sourceos-devtools from SocioProphet/homebrew-prophet or run it from SourceOS-Linux/sourceos-devtools.",
"agent-term": "Install agent-term from SocioProphet/homebrew-prophet or run it from SourceOS-Linux/agent-term.",
"sp-run": "Install AgentPlane so the sp-run delegate is available on PATH, or run it from SocioProphet/agentplane.",
}


Expand Down Expand Up @@ -66,6 +67,9 @@ 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")

return parser


Expand All @@ -87,9 +91,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":
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:]))
81 changes: 81 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,76 @@ def fake_run(cmd, check=False):
assert calls == [["/usr/bin/agent-term", "office", "inspect", "!prophet-workspace", "/tmp/demo.pptx"]]


def test_agentplane_doctor_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(["agentplane", "doctor"])

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


def test_agentplane_preflight_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(["agentplane", "preflight", "contract.json"])

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


def test_agentplane_admit_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([
"agentplane",
"admit",
"contract.json",
"--preflight",
"preflight.json",
"--authority-state",
"authority.json",
])

assert rc == 0
assert calls == [[
"/usr/bin/sp-run",
"admit",
"contract.json",
"--preflight",
"preflight.json",
"--authority-state",
"authority.json",
]]


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

Expand All @@ -127,3 +197,14 @@ def test_missing_delegate_returns_127(monkeypatch, capsys):
assert rc == 127
assert "required delegate not found: sourceosctl" in captured.err
assert "sourceos-devtools" in captured.err


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

rc = main(["agentplane", "doctor"])

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