@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 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 '{"title":"Runbook","content":"..."}'
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: