From 2ccb6d72c8ac5c800c76179f3097ce58729654da Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Mon, 6 Apr 2026 06:01:40 -0400 Subject: [PATCH 01/13] =?UTF-8?q?add=20go=20module=20for=20fa=C3=A7ade=20s?= =?UTF-8?q?caffold?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 go.mod diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..0bd9399 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module github.com/socioprophet/prophet-cli + +go 1.22 + +require github.com/spf13/cobra v1.8.1 From c2a237ca8f177218c3bd01f51d22b50da384af5a Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Mon, 6 Apr 2026 06:06:25 -0400 Subject: [PATCH 02/13] add contributing guide --- CONTRIBUTING.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..4e06ee3 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,14 @@ +# Contributing + +This repository is a façade-only CLI in phase 1. + +Please: +- keep changes small and reviewable +- prefer deterministic command semantics +- keep bootstrap logic delegated to `sourceos-bootstrap` +- preserve explicit docs for boundaries and non-goals + +Do not: +- invent boot or enrollment semantics here +- add hidden side effects to wrapper commands +- auto-enable project MCP servers in untrusted workspaces From 0484c447b18b5abdce06efd43d83e37247ce657c Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Mon, 6 Apr 2026 06:07:18 -0400 Subject: [PATCH 03/13] add security policy note --- SECURITY.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..d4371ad --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,9 @@ +# Security Policy + +This repository must not contain: +- enrollment tokens +- private signing keys +- token-door secrets +- hidden bootstrap business logic + +Phase 1 rule: keep sensitive semantics in their owning repositories and expose only façade wrappers here. From fcb426deae5e62c1411feb2693589c9b956b016b Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Mon, 6 Apr 2026 08:13:18 -0400 Subject: [PATCH 04/13] add gitignore --- .gitignore | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..54855d3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +/bin/ +/dist/ +/.cache/ +*.log +*.out +coverage.out +.DS_Store From 45b5f3515785a2190990b958eb75de5b1a203d17 Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Mon, 6 Apr 2026 09:16:20 -0400 Subject: [PATCH 05/13] add prophet CLI entrypoint --- cmd/prophet/main.go | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 cmd/prophet/main.go diff --git a/cmd/prophet/main.go b/cmd/prophet/main.go new file mode 100644 index 0000000..fa162a7 --- /dev/null +++ b/cmd/prophet/main.go @@ -0,0 +1,7 @@ +package main + +import "github.com/socioprophet/prophet-cli/internal/cmd" + +func main() { + cmd.Execute() +} From a6f9b07df9cd8134195f074deefa7a7d4698b4c4 Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Mon, 6 Apr 2026 10:13:38 -0400 Subject: [PATCH 06/13] add Cobra root scaffold --- internal/cmd/root.go | 72 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 internal/cmd/root.go diff --git a/internal/cmd/root.go b/internal/cmd/root.go new file mode 100644 index 0000000..48ea90c --- /dev/null +++ b/internal/cmd/root.go @@ -0,0 +1,72 @@ +package cmd + +import ( + "encoding/json" + "fmt" + "os" + "strings" + + "github.com/spf13/cobra" +) + +type GlobalFlags struct { + Profile string + Space string + Output string + Query string + Quiet bool + Debug bool + NoPager bool +} + +var flags GlobalFlags + +func Execute() { + if err := NewRootCommand().Execute(); err != nil { + os.Exit(1) + } +} + +func NewRootCommand() *cobra.Command { + root := &cobra.Command{Use: "prophet", Short: "Prophet facade CLI", SilenceUsage: true} + root.PersistentFlags().StringVar(&flags.Profile, "profile", "", "named profile") + root.PersistentFlags().StringVar(&flags.Space, "space", "", "execution space") + root.PersistentFlags().StringVarP(&flags.Output, "output", "o", "text", "output format") + root.PersistentFlags().StringVar(&flags.Query, "query", "", "query expression") + root.PersistentFlags().BoolVarP(&flags.Quiet, "quiet", "q", false, "suppress non-essential output") + root.PersistentFlags().BoolVar(&flags.Debug, "debug", false, "enable debug output") + root.PersistentFlags().BoolVar(&flags.NoPager, "no-pager", false, "disable pager") + root.AddCommand( + newBootstrapCmd(), + newA2ACmd(), + newPlaceholderCmd("ask", "Agent assist: explain or inspect without mutating state"), + newPlaceholderCmd("plan", "Agent assist: generate a plan over deterministic tools"), + newPlaceholderCmd("agent", "Agent execute facade"), + newPlaceholderCmd("mcp", "MCP boundary facade"), + ) + return root +} + +func emit(v any) error { + switch strings.ToLower(flags.Output) { + case "none": + return nil + case "json", "yaml", "table", "tsv": + enc := json.NewEncoder(os.Stdout) + enc.SetIndent("", " ") + return enc.Encode(v) + default: + b, err := json.MarshalIndent(v, "", " ") + if err != nil { + return err + } + fmt.Println(string(b)) + return nil + } +} + +func newPlaceholderCmd(name, summary string) *cobra.Command { + return &cobra.Command{Use: name, Short: summary, RunE: func(cmd *cobra.Command, args []string) error { + return emit(map[string]any{"command": name, "summary": summary, "status": "scaffold"}) + }} +} From ffd978ad04cfabc19e8486743500efd8adfaa81d Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Mon, 6 Apr 2026 10:27:46 -0400 Subject: [PATCH 07/13] =?UTF-8?q?add=20bootstrap=20fa=C3=A7ade=20command?= =?UTF-8?q?=20scaffold?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/cmd/bootstrap.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 internal/cmd/bootstrap.go diff --git a/internal/cmd/bootstrap.go b/internal/cmd/bootstrap.go new file mode 100644 index 0000000..59acfbf --- /dev/null +++ b/internal/cmd/bootstrap.go @@ -0,0 +1,28 @@ +package cmd + +import "github.com/spf13/cobra" + +func newBootstrapCmd() *cobra.Command { + cmd := &cobra.Command{Use: "bootstrap", Short: "Bootstrap facade commands"} + cmd.AddCommand( + newBootstrapLeaf("doctor", "diagnose host prerequisites"), + newBootstrapLeaf("login", "prepare authenticated bootstrap session"), + newBootstrapLeaf("build", "submit or describe a bootstrap build request"), + newBootstrapLeaf("fetch", "fetch release artifacts"), + newBootstrapLeaf("write", "prepare install or recovery media"), + newBootstrapLeaf("info", "show bootstrap engine information"), + &cobra.Command{Use: "validate ", Short: "Validate a frozen object through the bootstrap engine", Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { + return emit(map[string]any{"command": "prophet bootstrap validate", "kind": args[0], "path": args[1], "delegated_to": "sourceos-bootstrap", "status": "scaffold"}) + }}, + &cobra.Command{Use: "verify ", Short: "Verify a frozen object or artifact through the bootstrap engine", Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { + return emit(map[string]any{"command": "prophet bootstrap verify", "kind": args[0], "path": args[1], "delegated_to": "sourceos-bootstrap", "status": "scaffold"}) + }}, + ) + return cmd +} + +func newBootstrapLeaf(name, summary string) *cobra.Command { + return &cobra.Command{Use: name, Short: summary, RunE: func(cmd *cobra.Command, args []string) error { + return emit(map[string]any{"command": "prophet bootstrap " + name, "summary": summary, "delegated_to": "sourceos-bootstrap", "status": "scaffold"}) + }} +} From 1bfd9b698af30692be64a4df9caaa9a2a4baedd7 Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Tue, 7 Apr 2026 00:05:11 -0400 Subject: [PATCH 08/13] add bootstrap delegation documentation --- docs/BOOTSTRAP_DELEGATION.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 docs/BOOTSTRAP_DELEGATION.md diff --git a/docs/BOOTSTRAP_DELEGATION.md b/docs/BOOTSTRAP_DELEGATION.md new file mode 100644 index 0000000..1dfd85c --- /dev/null +++ b/docs/BOOTSTRAP_DELEGATION.md @@ -0,0 +1,18 @@ +# Bootstrap delegation + +`prophet-cli` is a façade. Bootstrap actions delegate to the installed `sourceos-bootstrap` engine. + +## Delegated commands +- `prophet bootstrap doctor` +- `prophet bootstrap login` +- `prophet bootstrap build` +- `prophet bootstrap fetch` +- `prophet bootstrap write` +- `prophet bootstrap info` +- `prophet bootstrap validate ` +- `prophet bootstrap verify ` + +## Rules +- do not implement bootstrap business logic here +- do not claim ownership of ReleaseSet, BootReleaseSet, ConfigSource, or TokenDoor semantics here +- wrapper commands should remain transparent about delegation From 34ab8e1743b7e3fc1412cdff4bd038958b2be079 Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Tue, 7 Apr 2026 01:37:10 -0400 Subject: [PATCH 09/13] add agent hybrid model documentation --- docs/AGENT_HYBRID_MODEL.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 docs/AGENT_HYBRID_MODEL.md diff --git a/docs/AGENT_HYBRID_MODEL.md b/docs/AGENT_HYBRID_MODEL.md new file mode 100644 index 0000000..9548a62 --- /dev/null +++ b/docs/AGENT_HYBRID_MODEL.md @@ -0,0 +1,22 @@ +# Agent hybrid model + +The repository follows a hybrid model with three surfaces: + +1. deterministic CLI +2. agent assist +3. agent execute + +## Deterministic CLI +The deterministic CLI is the canonical, documented surface. + +## Agent assist +Read-mostly planning and explanation over deterministic tools. + +## Agent execute +Approval-gated execution that still resolves to deterministic tools. + +## Guardrails +- no bootstrap business logic in this repo +- no silent plugin installation +- no automatic project MCP loading in untrusted workspaces +- no competing command language that bypasses deterministic verbs From da5c6ad172b1150932bbb06c276eee7e84f2acbc Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Tue, 7 Apr 2026 01:40:47 -0400 Subject: [PATCH 10/13] add command surface documentation --- docs/COMMANDS.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 docs/COMMANDS.md diff --git a/docs/COMMANDS.md b/docs/COMMANDS.md new file mode 100644 index 0000000..0b1fc85 --- /dev/null +++ b/docs/COMMANDS.md @@ -0,0 +1,25 @@ +# Commands + +## Deterministic façade commands + +### Bootstrap +- `prophet bootstrap doctor` +- `prophet bootstrap login` +- `prophet bootstrap build` +- `prophet bootstrap fetch` +- `prophet bootstrap write` +- `prophet bootstrap info` +- `prophet bootstrap validate ` +- `prophet bootstrap verify ` + +### Workflow +- `prophet a2a run` + +## Hybrid overlay placeholders +- `prophet ask` +- `prophet plan` +- `prophet agent` +- `prophet mcp` + +## Notes +These commands are scaffolds in phase 1. The deterministic verbs and delegation boundaries are more important than implementing broad business logic too early. From 6ab7e935216ca025124bb814228604946992d685 Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Tue, 7 Apr 2026 02:20:10 -0400 Subject: [PATCH 11/13] add root command tests --- internal/cmd/root_test.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 internal/cmd/root_test.go diff --git a/internal/cmd/root_test.go b/internal/cmd/root_test.go new file mode 100644 index 0000000..1b617b2 --- /dev/null +++ b/internal/cmd/root_test.go @@ -0,0 +1,25 @@ +package cmd + +import "testing" + +func TestRootCommandHasExpectedTopLevelCommands(t *testing.T) { + root := NewRootCommand() + want := map[string]bool{ + "bootstrap": false, + "a2a": false, + "ask": false, + "plan": false, + "agent": false, + "mcp": false, + } + for _, c := range root.Commands() { + if _, ok := want[c.Name()]; ok { + want[c.Name()] = true + } + } + for name, seen := range want { + if !seen { + t.Fatalf("missing top-level command: %s", name) + } + } +} From ffe2fdb8a2a5010d9b671c3dc97fbfe3067b75a9 Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Tue, 7 Apr 2026 02:21:45 -0400 Subject: [PATCH 12/13] add A2A workflow tests --- internal/a2a/workflow_test.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 internal/a2a/workflow_test.go diff --git a/internal/a2a/workflow_test.go b/internal/a2a/workflow_test.go new file mode 100644 index 0000000..8c0f2b4 --- /dev/null +++ b/internal/a2a/workflow_test.go @@ -0,0 +1,19 @@ +package a2a + +import "testing" + +func TestDefaultWorkflowHasExpectedPhases(t *testing.T) { + wf := Default("demo/repo", "DEMO", false) + if wf.Repo != "demo/repo" { + t.Fatalf("unexpected repo: %s", wf.Repo) + } + if len(wf.Phases) != 6 { + t.Fatalf("expected 6 phases, got %d", len(wf.Phases)) + } + if wf.Phases[0].Name != "propose" { + t.Fatalf("unexpected first phase: %s", wf.Phases[0].Name) + } + if wf.Phases[len(wf.Phases)-1].Name != "done" { + t.Fatalf("unexpected last phase: %s", wf.Phases[len(wf.Phases)-1].Name) + } +} From 4e980c1c600dffdc5a512533b4004c38086276ec Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Tue, 7 Apr 2026 02:32:48 -0400 Subject: [PATCH 13/13] add Go CI workflow --- .github/workflows/ci.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..ce510cb --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,21 @@ +name: ci + +on: + push: + branches: [ main, sourceos/rev2-1-facade-seed, scaffold3 ] + pull_request: + +jobs: + go: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version: '1.22' + - name: Download modules + run: go mod tidy + - name: Test + run: go test ./... + - name: Vet + run: go vet ./...