native macOS codings agent orchestrator
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #89 from onevcat/onevpaw/issue-64-cli-open-output-contract

docs(cli): define JSON contract for prowl open

authored by

Wei Wang and committed by
GitHub
1b97b9fd aed4051c

+192
+192
doc-onevcat/contracts/cli/open.md
··· 1 + # CLI Contract: `prowl open` 2 + 3 + Status: draft truth source for `#64`. 4 + 5 + This file defines the **JSON output contract** for the path-opening entry points: 6 + 7 + - `prowl` 8 + - `prowl <cwd>` 9 + - `prowl open <cwd>` 10 + - any of the above with `--json` 11 + 12 + The goal is to give later implementation tasks a stable machine-facing contract. 13 + 14 + ## Contract goals 15 + 16 + - Bare `prowl <cwd>` and explicit `prowl open <cwd>` must share the same JSON shape. 17 + - Success output must tell an agent **what Prowl actually focused or opened**. 18 + - Path fields must be normalized to **absolute paths** after CLI parsing. 19 + - Success output must be stable enough for scripts; human-oriented prose belongs to non-JSON mode. 20 + 21 + ## Success payload 22 + 23 + ```json 24 + { 25 + "ok": true, 26 + "command": "open", 27 + "schema_version": "prowl.cli.open.v1", 28 + "data": { 29 + "invocation": "implicit-open", 30 + "requested_path": "/Users/onevcat/Projects/Prowl/supacode", 31 + "resolved_path": "/Users/onevcat/Projects/Prowl/supacode", 32 + "resolution": "inside-root", 33 + "app_launched": false, 34 + "brought_to_front": true, 35 + "created_tab": true, 36 + "target": { 37 + "worktree": { 38 + "id": "Prowl:/Users/onevcat/Projects/Prowl", 39 + "name": "Prowl", 40 + "path": "/Users/onevcat/Projects/Prowl", 41 + "root_path": "/Users/onevcat/Projects/Prowl", 42 + "kind": "git" 43 + }, 44 + "tab": { 45 + "id": "0E2A7C03-9C01-4BC1-9327-6C1C7B629A52", 46 + "title": "supacode", 47 + "cwd": "/Users/onevcat/Projects/Prowl/supacode" 48 + }, 49 + "pane": { 50 + "id": "0FB4DDB4-A797-4315-A00E-8AAFB32BFC95", 51 + "title": "supacode", 52 + "cwd": "/Users/onevcat/Projects/Prowl/supacode" 53 + } 54 + } 55 + } 56 + } 57 + ``` 58 + 59 + ## Required top-level fields 60 + 61 + - `ok`: boolean, must be `true` on success. 62 + - `command`: string, must be `"open"` even when the user invoked bare `prowl <cwd>`. 63 + - `schema_version`: string, currently `"prowl.cli.open.v1"`. 64 + - `data`: object. 65 + 66 + ## `data` fields 67 + 68 + - `invocation`: string. 69 + - `"bare"` for `prowl` 70 + - `"implicit-open"` for `prowl <cwd>` 71 + - `"open-subcommand"` for `prowl open <cwd>` 72 + - `requested_path`: string or `null`. 73 + - `null` only for bare `prowl` with no explicit path. 74 + - otherwise the absolute path after resolving `.` / `..` / `~` / `file://`. 75 + - `resolved_path`: string or `null`. 76 + - `null` only when `requested_path` is `null`. 77 + - must be the path Prowl actually targeted after normalization. 78 + - `resolution`: string enum. 79 + - `"no-argument"`: bare `prowl` 80 + - `"exact-root"`: requested path matched an already-open root exactly 81 + - `"inside-root"`: requested path was inside an already-open root, so Prowl focused that root and opened a tab at the exact subpath 82 + - `"new-root"`: requested path was not yet managed and Prowl opened it as a new root 83 + - `app_launched`: boolean. 84 + - `true` only when the command had to start Prowl. 85 + - `brought_to_front`: boolean. 86 + - must be `true` on success. 87 + - `created_tab`: boolean. 88 + - `true` when the operation created a new tab as part of satisfying the request. 89 + - `false` when Prowl only focused an existing target. 90 + - `target`: object describing the final focused target. 91 + 92 + ## `target` shape 93 + 94 + ### `target.worktree` 95 + 96 + - `id`: string 97 + - `name`: string 98 + - `path`: string, absolute worktree/plain-folder path 99 + - `root_path`: string, absolute repository root or plain-folder root 100 + - `kind`: `"git"` | `"plain"` 101 + 102 + ### `target.tab` 103 + 104 + - `id`: string, UUID text form 105 + - `title`: string 106 + - `cwd`: string or `null` 107 + 108 + ### `target.pane` 109 + 110 + - `id`: string, UUID text form 111 + - `title`: string 112 + - `cwd`: string or `null` 113 + 114 + ## Error payload 115 + 116 + ```json 117 + { 118 + "ok": false, 119 + "command": "open", 120 + "schema_version": "prowl.cli.open.v1", 121 + "error": { 122 + "code": "PATH_NOT_FOUND", 123 + "message": "No directory exists at '/Users/onevcat/Projects/Missing'", 124 + "details": { 125 + "requested_path": "/Users/onevcat/Projects/Missing" 126 + } 127 + } 128 + } 129 + ``` 130 + 131 + ## Required error fields 132 + 133 + - `ok`: boolean, must be `false`. 134 + - `command`: string, must be `"open"`. 135 + - `schema_version`: string, must be `"prowl.cli.open.v1"`. 136 + - `error.code`: stable machine-readable string. 137 + - `error.message`: human-readable string. 138 + - `error.details`: optional object with structured context. 139 + 140 + ## Error codes for v1 141 + 142 + - `INVALID_ARGUMENT` 143 + - `PATH_NOT_FOUND` 144 + - `PATH_NOT_DIRECTORY` 145 + - `PATH_NOT_ALLOWED` 146 + - `LAUNCH_FAILED` 147 + - `OPEN_FAILED` 148 + 149 + ## Notes 150 + 151 + - Success JSON should report the **resolved target**, not only the input path. 152 + - `target.tab.cwd` and `target.pane.cwd` should be the exact directory the user lands in when available. 153 + - `created_tab` may be `false` for `exact-root` and `true` for `inside-root`; `new-root` may do either depending on implementation, so callers must trust the boolean instead of inferring it. 154 + - `prowl` without arguments still returns `command: "open"`; it is the app-entry form of the same capability. 155 + 156 + ## Example: exact-root focus 157 + 158 + ```json 159 + { 160 + "ok": true, 161 + "command": "open", 162 + "schema_version": "prowl.cli.open.v1", 163 + "data": { 164 + "invocation": "open-subcommand", 165 + "requested_path": "/Users/onevcat/Projects/Prowl", 166 + "resolved_path": "/Users/onevcat/Projects/Prowl", 167 + "resolution": "exact-root", 168 + "app_launched": false, 169 + "brought_to_front": true, 170 + "created_tab": false, 171 + "target": { 172 + "worktree": { 173 + "id": "Prowl:/Users/onevcat/Projects/Prowl", 174 + "name": "Prowl", 175 + "path": "/Users/onevcat/Projects/Prowl", 176 + "root_path": "/Users/onevcat/Projects/Prowl", 177 + "kind": "git" 178 + }, 179 + "tab": { 180 + "id": "95A6DF8D-4E7E-4A67-895B-0EAF7DB6D7A8", 181 + "title": "Prowl 1", 182 + "cwd": "/Users/onevcat/Projects/Prowl" 183 + }, 184 + "pane": { 185 + "id": "7C38206E-1C9D-4740-A6B0-675C3BC93B47", 186 + "title": "Prowl", 187 + "cwd": "/Users/onevcat/Projects/Prowl" 188 + } 189 + } 190 + } 191 + } 192 + ```