@ted-galago/wave-cli 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +226 -2
- package/dist/index.cjs +2992 -131
- package/dist/index.js +2989 -128
- package/package.json +2 -1
- package/scripts/benchmark-cli.mjs +626 -0
- package/scripts/verify-dev-api.mjs +341 -26
package/README.md
CHANGED
|
@@ -35,6 +35,27 @@ printf '%s' '{"token":"token-value","baseUrl":"https://api.example.com","organiz
|
|
|
35
35
|
| wave --auth-json-stdin tasks list --page 1 --per 10
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
+
## Benchmark Wave vs Obsidian CLI
|
|
39
|
+
|
|
40
|
+
Run the side-by-side benchmark harness:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npm run benchmark:cli
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Useful options:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm run benchmark:cli -- --runs 20 --warmup 3 --query "meeting notes"
|
|
50
|
+
npm run benchmark:cli -- --obsidian-bin /Applications/Obsidian.app/Contents/MacOS/obsidian-cli
|
|
51
|
+
npm run benchmark:cli -- --json-out /tmp/cli-benchmark.json
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Notes:
|
|
55
|
+
|
|
56
|
+
- Wave scenarios expect JSON envelopes for domain operations.
|
|
57
|
+
- Obsidian scenarios require the CLI to be registered and the Obsidian app available.
|
|
58
|
+
|
|
38
59
|
## Runtime Contract
|
|
39
60
|
|
|
40
61
|
Required (from flags, stdin, or env):
|
|
@@ -82,9 +103,36 @@ wave foundation annual-objectives create --data-json '{"annual_objective":{"stra
|
|
|
82
103
|
wave foundation quarterly-objectives create --data-json '{"quarterly_objective":{"strategic_objective_id":"7","annual_objective_id":"8","name":"Quarterly Goal"}}'
|
|
83
104
|
wave lists create --data-json '{"name":"Weekly List"}'
|
|
84
105
|
wave list-items create --data-json '{"list_id":"123","summary":"Follow up"}'
|
|
85
|
-
wave todos create --data-json '{"todo_group_id":"55","name":"Send update"}'
|
|
86
|
-
wave knowledge create --data-json '{"
|
|
106
|
+
wave todos create --data-json '{"todo_group_id":"55","name":"Send update","status":"open"}'
|
|
107
|
+
wave knowledge create --data-json '{"content":{"name":"Runbook","content_type":"process","status":"draft","member_id":"67"}}'
|
|
108
|
+
wave notes create-member --target-member-id 67 --name "1:1 Note" --body "Strong progress"
|
|
109
|
+
wave notes create-manager --actor-member-id 67 --target-member-id 68 --name "Manager Note" --body "Coaching plan"
|
|
110
|
+
wave notes create-team --actor-member-id 67 --team-id 9 --name "Team Note" --body "Team context"
|
|
111
|
+
wave notes create-project --actor-member-id 67 --project-id 80 --name "Project Note" --body "Project context"
|
|
112
|
+
wave notes create-customer --actor-member-id 67 --customer-id 30 --name "Customer Note" --body "Customer context"
|
|
113
|
+
wave notes create-contact --actor-member-id 67 --contact-id 31 --name "Contact Note" --body "Contact context"
|
|
114
|
+
wave notes list --contentable-type Member --contentable-id 67 --member-id 67 --page 1 --per 20
|
|
115
|
+
wave notes show --id 1001
|
|
116
|
+
wave notes update --id 1001 --name "Updated Note" --body "Updated body" --status published
|
|
117
|
+
wave notes destroy --id 1001
|
|
118
|
+
wave markdown-tree root --tree-view
|
|
119
|
+
wave markdown-tree resolve --tool-key projects --node-key tasks --parent-id 123
|
|
120
|
+
wave markdown-tree children --tool-key directory --node-key members --record-id 67
|
|
121
|
+
wave markdown-tree subtree --tool-key knowledge --node-key knowledge --content-type processes --depth 2
|
|
122
|
+
wave find "Ted"
|
|
123
|
+
wave open "Ted Martinez"
|
|
124
|
+
wave ls --path "directory/Members/Ted Martinez"
|
|
125
|
+
wave cat --path "directory/Members/Ted Martinez/Member Profile"
|
|
126
|
+
wave tree --path "knowledge/Processes" --depth 2
|
|
87
127
|
wave pulse update --id 12 --data-json '{"status":"on_track"}'
|
|
128
|
+
wave subtasks list --task-id 123 --page 1 --per 20
|
|
129
|
+
wave milestones list --rock-id 234 --page 1 --per 20
|
|
130
|
+
wave subitems list --list-item-id 345 --page 1 --per 20
|
|
131
|
+
wave subtodos list --todo-id 456 --page 1 --per 20
|
|
132
|
+
wave subissues list --issue-id 567 --page 1 --per 20
|
|
133
|
+
wave talking-points list --meeting-id 678 --page 1 --per 20
|
|
134
|
+
wave subtasks create --data-json '{"subtask":{"task_id":"123","member_id":"67","name":"Subtask name","description":"Subtask description"}}'
|
|
135
|
+
wave subissues destroy --id 999
|
|
88
136
|
```
|
|
89
137
|
|
|
90
138
|
All commands require organization context via `--organization-id` or `WAVE_ORGANIZATION_ID`.
|
|
@@ -98,10 +146,186 @@ These child resources enforce parent IDs at CLI validation time:
|
|
|
98
146
|
- `issues.create` requires `issue_group_id`
|
|
99
147
|
- `todos.create` requires `todo_group_id`
|
|
100
148
|
- `rocks.create` requires `rock_collection_id`
|
|
149
|
+
- `kpis.create` requires `smart_kpi_view_id`
|
|
101
150
|
- `scorecards.create` requires `measurable_group_id`
|
|
151
|
+
- `subtasks.create` requires `task_id`
|
|
152
|
+
- `milestones.create` requires `rock_id`
|
|
153
|
+
- `subitems.create` requires `list_item_id`
|
|
154
|
+
- `subtodos.create` requires `todo_id`
|
|
155
|
+
- `subissues.create` requires `issue_id`
|
|
156
|
+
- `talking-points.create` requires `meeting_id`
|
|
102
157
|
|
|
103
158
|
If a required parent field is missing, CLI returns JSON error with exit code `2`.
|
|
104
159
|
|
|
160
|
+
`kpis.create` contract notes:
|
|
161
|
+
|
|
162
|
+
- `smart_kpi.name` must be one of the backend enum values.
|
|
163
|
+
- If payload uses free-text `smart_kpi.name` with `measurable_group_id`, CLI routes to `create_measurable` (`scorecards.create`) instead of `create_smart_kpi`.
|
|
164
|
+
|
|
165
|
+
`meetings.create` contract notes:
|
|
166
|
+
|
|
167
|
+
- `meeting.type` is required and must be `TeamMeeting` or `OneOnOneMeeting`.
|
|
168
|
+
- Required fields: `member_id`, `date`, `start_time`.
|
|
169
|
+
- `meeting.repeats` defaults to `never` if omitted.
|
|
170
|
+
- For `TeamMeeting`, `teams_ids` is required.
|
|
171
|
+
|
|
172
|
+
`organizations.update` contract notes:
|
|
173
|
+
|
|
174
|
+
- `organization.workspace_name` is normalized to `organization.organization_detail_attributes.workspace_name`.
|
|
175
|
+
|
|
176
|
+
`organizations.meta-profile.update` contract notes:
|
|
177
|
+
|
|
178
|
+
- Payload must be shaped as `organization_meta_profile.profile.<section>.<field>`.
|
|
179
|
+
- Legacy shorthand `organization_meta_profile.title` is normalized to `profile.company_identity.one_sentence_summary`.
|
|
180
|
+
|
|
181
|
+
`organizations.key-metric-meta-profile.update` contract notes:
|
|
182
|
+
|
|
183
|
+
- Payload must be shaped as `key_metric_meta_profile.profile.<section>.<field>`.
|
|
184
|
+
- Legacy shorthand `key_metric_meta_profile.annual_revenue` is normalized to `profile.financial.revenue`.
|
|
185
|
+
|
|
186
|
+
`knowledge.create` contract notes:
|
|
187
|
+
|
|
188
|
+
- `content.content_type` must be one of `company`, `policy`, `process`.
|
|
189
|
+
- `content.status` must be `draft` or `published`.
|
|
190
|
+
- `content.member_id` is required.
|
|
191
|
+
- `content.type` is not required for create.
|
|
192
|
+
|
|
193
|
+
`news.create` contract notes:
|
|
194
|
+
|
|
195
|
+
- Requires `headline.member_id`, `headline.status`, and `headline.headline_type`.
|
|
196
|
+
- `headline.status` must be `active` or `completed`.
|
|
197
|
+
- `headline.headline_type` must be `team` or `org_wide`.
|
|
198
|
+
|
|
199
|
+
`questions.create/update` contract notes:
|
|
200
|
+
|
|
201
|
+
- Use `question.name` (legacy `summary` is normalized to `name`).
|
|
202
|
+
- `questions.create` requires `question.member_id` and `question.name`.
|
|
203
|
+
- `question.status`, when provided, must be `asked` or `answered`.
|
|
204
|
+
|
|
205
|
+
`pulse.create` contract notes:
|
|
206
|
+
|
|
207
|
+
- Requires `health_update.health_updatable_id`, `health_update.health_updatable_type`, `health_update.member_id`, and `health_update.status`.
|
|
208
|
+
- Legacy `updatable_id`/`updatable_type` are normalized to `health_updatable_id`/`health_updatable_type`.
|
|
209
|
+
- `health_update.status` must be `on_track`, `at_risk`, or `off_track`.
|
|
210
|
+
|
|
211
|
+
`surveys.create/update` contract notes:
|
|
212
|
+
|
|
213
|
+
- Use `survey.name` and `survey.recipient_type` (`title` is normalized to `name`).
|
|
214
|
+
- `survey.recipient_type` must be `member`, `team`, or `org_wide`.
|
|
215
|
+
- Valid `survey.name` values:
|
|
216
|
+
- `employee_net_promoter_score`
|
|
217
|
+
- `continuous_performance_review`
|
|
218
|
+
- `core_value_alignment`
|
|
219
|
+
- `engagement`
|
|
220
|
+
- `wellness_and_mental_health`
|
|
221
|
+
- `workspace_culture`
|
|
222
|
+
- `peer_review`
|
|
223
|
+
- `manager_review`
|
|
224
|
+
- `onboarding`
|
|
225
|
+
|
|
226
|
+
`feedbacks.create/update` contract notes:
|
|
227
|
+
|
|
228
|
+
- Use `feedback.name` (`title` is normalized to `name`).
|
|
229
|
+
- `feedbacks.create` requires `feedback.name`, `feedback.quarter`, `feedback.year`.
|
|
230
|
+
- `feedback.quarter` must be `q1`, `q2`, `q3`, or `q4`.
|
|
231
|
+
|
|
232
|
+
`accountability.create/update` contract notes:
|
|
233
|
+
|
|
234
|
+
- Use `responsibility.name` (`summary` is normalized to `name`).
|
|
235
|
+
- `accountability.create` requires `responsibility.name` and `responsibility.member_id`.
|
|
236
|
+
|
|
237
|
+
## Markdown Tree Traversal
|
|
238
|
+
|
|
239
|
+
Thin GraphQL adapter over backend markdown-tree services.
|
|
240
|
+
CLI does not re-implement traversal/scope rules.
|
|
241
|
+
|
|
242
|
+
Commands:
|
|
243
|
+
|
|
244
|
+
- `wave markdown-tree root [--tree-view]`
|
|
245
|
+
- `wave markdown-tree resolve --tool-key <k> --node-key <k> [--parent-id <id>] [--record-id <id>] [--member-id <id>] [--team-id <id>] [--content-type <t>] [--tree-view]`
|
|
246
|
+
- `wave markdown-tree children --tool-key <k> --node-key <k> [--parent-id <id>] [--record-id <id>] [--member-id <id>] [--team-id <id>] [--content-type <t>] [--tree-view]`
|
|
247
|
+
- `wave markdown-tree subtree --tool-key <k> --node-key <k> --depth <n> [--parent-id <id>] [--record-id <id>] [--member-id <id>] [--team-id <id>] [--content-type <t>] [--tree-view]`
|
|
248
|
+
|
|
249
|
+
GraphQL mapping:
|
|
250
|
+
|
|
251
|
+
- `root` -> `markdownTreeRoot`
|
|
252
|
+
- `resolve` -> `markdownTreeNode`
|
|
253
|
+
- `children` -> `markdownTreeChildren`
|
|
254
|
+
- `subtree` -> `markdownTreeSubtree`
|
|
255
|
+
|
|
256
|
+
Backend error codes are surfaced explicitly from GraphQL `errors[].extensions.code`:
|
|
257
|
+
|
|
258
|
+
- `UNAUTHORIZED`
|
|
259
|
+
- `NOT_FOUND`
|
|
260
|
+
- `INVALID_SCOPE`
|
|
261
|
+
- `UNSUPPORTED_BRANCH`
|
|
262
|
+
|
|
263
|
+
## Navigation Shell
|
|
264
|
+
|
|
265
|
+
Primary agent-facing discovery/navigation commands:
|
|
266
|
+
|
|
267
|
+
- `wave find "<query>" [--under <path>] [--limit <n>]`
|
|
268
|
+
- `wave open "<name>" [--under <path>] [--tree-view]`
|
|
269
|
+
- `wave ls [query] --path <path>` or `wave ls [query] --tool-key ... --node-key ...`
|
|
270
|
+
- `wave cat --path <path>` or `wave cat --tool-key ... --node-key ...`
|
|
271
|
+
- `wave tree --depth <n> --path <path>` or `wave tree --depth <n> --tool-key ... --node-key ...`
|
|
272
|
+
|
|
273
|
+
These wrap backend-owned markdown-tree primitives:
|
|
274
|
+
|
|
275
|
+
- `find` -> `markdownTreeFind`
|
|
276
|
+
- `open` -> `markdownTreeFind` + `markdownTreeNode`
|
|
277
|
+
- `ls` -> `markdownTreeChildren`
|
|
278
|
+
- `cat` -> `markdownTreeNode`
|
|
279
|
+
- `tree` -> `markdownTreeSubtree`
|
|
280
|
+
|
|
281
|
+
Discovery, ranking, canonical paths, and narrowing are backend-owned.
|
|
282
|
+
|
|
283
|
+
Ambiguity contract:
|
|
284
|
+
|
|
285
|
+
- no silent bad guesses
|
|
286
|
+
- returns `error.code = "ambiguous_match"` with ranked candidates in `error.details.candidates`
|
|
287
|
+
|
|
288
|
+
## Notes Contract
|
|
289
|
+
|
|
290
|
+
The `notes` command uses exact GraphQL operation names:
|
|
291
|
+
|
|
292
|
+
- `CreateContent`
|
|
293
|
+
- `UpdateContent`
|
|
294
|
+
- `DestroyContent`
|
|
295
|
+
- `ContentShow`
|
|
296
|
+
- `ContentsIndex`
|
|
297
|
+
|
|
298
|
+
Placement rules enforced by command shape:
|
|
299
|
+
|
|
300
|
+
- `notes create-member`
|
|
301
|
+
- `contentable_type: "Member"`
|
|
302
|
+
- `contentable_id: TARGET_MEMBER_ID`
|
|
303
|
+
- `member_id: TARGET_MEMBER_ID`
|
|
304
|
+
- `focus_member_id: null`
|
|
305
|
+
- `focus_team_id: null`
|
|
306
|
+
- `notes create-manager`
|
|
307
|
+
- `contentable_type: "Member"`
|
|
308
|
+
- `contentable_id: ACTOR_MEMBER_ID`
|
|
309
|
+
- `member_id: ACTOR_MEMBER_ID`
|
|
310
|
+
- `focus_member_id: TARGET_MEMBER_ID`
|
|
311
|
+
- `notes create-team`
|
|
312
|
+
- `contentable_type: "Team"`
|
|
313
|
+
- `contentable_id: TEAM_ID`
|
|
314
|
+
- `member_id: ACTOR_MEMBER_ID`
|
|
315
|
+
- `focus_team_id: TEAM_ID`
|
|
316
|
+
- `notes create-project`
|
|
317
|
+
- `contentable_type: "Project"`
|
|
318
|
+
- `contentable_id: PROJECT_ID`
|
|
319
|
+
- `member_id: ACTOR_MEMBER_ID`
|
|
320
|
+
- `notes create-customer`
|
|
321
|
+
- `contentable_type: "Customer"`
|
|
322
|
+
- `contentable_id: CUSTOMER_ID`
|
|
323
|
+
- `member_id: ACTOR_MEMBER_ID`
|
|
324
|
+
- `notes create-contact`
|
|
325
|
+
- `contentable_type: "Contact"`
|
|
326
|
+
- `contentable_id: CONTACT_ID`
|
|
327
|
+
- `member_id: ACTOR_MEMBER_ID`
|
|
328
|
+
|
|
105
329
|
## JSON Envelope
|
|
106
330
|
|
|
107
331
|
Success:
|