@allocator-one/harness-cli 1.13.0 → 1.14.0

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/spec/openapi.json CHANGED
@@ -71,7 +71,7 @@
71
71
  "patch": {
72
72
  "callbacks": {},
73
73
  "deprecated": false,
74
- "description": "Requires the `harness:write` scope AND Harness administrator standing in the organization the credential is bound to — this is a settings write, gated exactly as the settings UI is. Name, type, and colour. A state belonging to another team answers 404.",
74
+ "description": "Requires the `harness:write` scope AND Harness administrator standing in the organization the credential is bound to — this is a settings write, gated exactly as the settings UI is. Name, type, purpose, and colour. Purpose may be cleared with null; duplicate requires a canceled state and may be assigned once per team. A state belonging to another team answers 404.",
75
75
  "parameters": [
76
76
  {
77
77
  "description": "Team key, e.g. ALL",
@@ -105,6 +105,14 @@
105
105
  "maxLength": 255,
106
106
  "type": "string"
107
107
  },
108
+ "purpose": {
109
+ "enum": [
110
+ null,
111
+ "duplicate"
112
+ ],
113
+ "nullable": true,
114
+ "type": "string"
115
+ },
108
116
  "type": {
109
117
  "enum": [
110
118
  "backlog",
@@ -451,6 +459,9 @@
451
459
  "200": {
452
460
  "description": "Success"
453
461
  },
462
+ "206": {
463
+ "description": "Requested video byte range, with Content-Range and Content-Length"
464
+ },
454
465
  "400": {
455
466
  "description": "Bad request"
456
467
  },
@@ -463,9 +474,6 @@
463
474
  "404": {
464
475
  "description": "Not found"
465
476
  },
466
- "206": {
467
- "description": "Requested video byte range, with Content-Range and Content-Length"
468
- },
469
477
  "416": {
470
478
  "description": "Unsatisfiable range; Content-Range contains the actual file size"
471
479
  },
@@ -665,7 +673,7 @@
665
673
  "get": {
666
674
  "callbacks": {},
667
675
  "deprecated": false,
668
- "description": "Requires the `harness:read` scope. The payload always carries `blocked` and `blocked_by` (identifiers of open blockers); `include` embeds relations (direction-aware), children, and recent comments in one response.",
676
+ "description": "Requires the `harness:read` scope. The payload always carries `blocked` and `blocked_by` (identifiers of unresolved blockers: only a completed blocker resolves), `blockers` (each with `identifier`, `state_type` and `archived`, so a cancelled or archived blocker is visible as such), and `held` and `held_by` (the identifier of the issue whose `hold` label holds this one: itself or its nearest held ancestor, or null), `waiting_on_condition` and `conditions` (its wait conditions, see `/conditions`), and `execution` (the issue's latest plan step run: status, executor, attempt, retries and continues used, last outcome code and plan room URL, or null); `include` embeds relations (direction-aware), children, and recent comments in one response.",
669
677
  "parameters": [
670
678
  {
671
679
  "description": "Issue identifier, e.g. ALL-4901 or CLI-12 (issues minted before team-prefixed numbering carry IO-)",
@@ -1152,11 +1160,51 @@
1152
1160
  "tags": []
1153
1161
  }
1154
1162
  },
1163
+ "/api/v1/teams/{team_key}/issues/claim-next": {
1164
+ "post": {
1165
+ "callbacks": {},
1166
+ "deprecated": false,
1167
+ "description": "Requires the `harness:write` scope. Claims the team's most important ready issue that nobody holds — urgent, high, medium, low, then none; oldest first, then by id — assigning the caller and moving it to the team's first started-type state in one transaction. Concurrent callers receive distinct issues. Returns the issue, or `data: null` when nothing is claimable (a normal outcome, not an error).",
1168
+ "parameters": [
1169
+ {
1170
+ "description": "Team key, e.g. ALL",
1171
+ "in": "path",
1172
+ "name": "team_key",
1173
+ "required": true,
1174
+ "schema": {
1175
+ "type": "string"
1176
+ }
1177
+ }
1178
+ ],
1179
+ "responses": {
1180
+ "200": {
1181
+ "description": "Success"
1182
+ },
1183
+ "400": {
1184
+ "description": "The team has no started-type workflow state"
1185
+ },
1186
+ "401": {
1187
+ "description": "Missing or invalid token"
1188
+ },
1189
+ "403": {
1190
+ "description": "Token not permitted (org-scoped, non-admin, or missing scope)"
1191
+ },
1192
+ "404": {
1193
+ "description": "Not found"
1194
+ },
1195
+ "422": {
1196
+ "description": "Validation error"
1197
+ }
1198
+ },
1199
+ "summary": "Claim the next ready issue",
1200
+ "tags": []
1201
+ }
1202
+ },
1155
1203
  "/api/v1/issues/{identifier}/state": {
1156
1204
  "put": {
1157
1205
  "callbacks": {},
1158
1206
  "deprecated": false,
1159
- "description": "Requires the `harness:write` scope.",
1207
+ "description": "Requires the `harness:write` scope. Moves the issue to `state_id`, a state of its own team. Like close, the response's `unblocked` lists identifiers of issues that became ready because the move completed this one (its dependents with no other open blocker, and its parent once no open child is left), read after the move committed; any other move reports none.",
1160
1208
  "parameters": [
1161
1209
  {
1162
1210
  "description": "Issue identifier, e.g. ALL-4901 or CLI-12 (issues minted before team-prefixed numbering carry IO-)",
@@ -1328,7 +1376,7 @@
1328
1376
  "get": {
1329
1377
  "callbacks": {},
1330
1378
  "deprecated": false,
1331
- "description": "Requires the `harness:read` scope. The newest mixed page of comments, issue-state events, and assignee changes, returned oldest-first. `has_more` means older entries exist. Pass the opaque `next_cursor` back as `before`; cursors are bound to the issue and viewer and expire after 24 hours.",
1379
+ "description": "Requires the `harness:read` scope. The newest mixed page of comments, issue-state events, and assignee changes, returned oldest-first. With `include=condition_events`, wait-condition events (`condition_event`) join them. `has_more` means older entries exist. Pass the opaque `next_cursor` back as `before`; cursors are bound to the issue, the viewer and `include`, and expire after 24 hours.",
1332
1380
  "parameters": [
1333
1381
  {
1334
1382
  "description": "Issue identifier, e.g. ALL-4901 or CLI-12 (issues minted before team-prefixed numbering carry IO-)",
@@ -1358,6 +1406,18 @@
1358
1406
  "minimum": 1,
1359
1407
  "type": "integer"
1360
1408
  }
1409
+ },
1410
+ {
1411
+ "description": "`condition_events` adds wait-condition events to the timeline",
1412
+ "in": "query",
1413
+ "name": "include",
1414
+ "required": false,
1415
+ "schema": {
1416
+ "enum": [
1417
+ "condition_events"
1418
+ ],
1419
+ "type": "string"
1420
+ }
1361
1421
  }
1362
1422
  ],
1363
1423
  "responses": {
@@ -1750,6 +1810,114 @@
1750
1810
  "to_assignee"
1751
1811
  ],
1752
1812
  "type": "object"
1813
+ },
1814
+ {
1815
+ "additionalProperties": false,
1816
+ "properties": {
1817
+ "action": {
1818
+ "enum": [
1819
+ "added",
1820
+ "changed",
1821
+ "removed",
1822
+ "satisfied",
1823
+ "unsatisfied"
1824
+ ],
1825
+ "type": "string"
1826
+ },
1827
+ "actor": {
1828
+ "properties": {
1829
+ "kind": {
1830
+ "enum": [
1831
+ "system",
1832
+ "user",
1833
+ "deleted_user",
1834
+ "unknown"
1835
+ ],
1836
+ "type": "string"
1837
+ },
1838
+ "name": {
1839
+ "nullable": true,
1840
+ "type": "string"
1841
+ }
1842
+ },
1843
+ "required": [
1844
+ "kind",
1845
+ "name"
1846
+ ],
1847
+ "type": "object"
1848
+ },
1849
+ "condition": {
1850
+ "additionalProperties": false,
1851
+ "properties": {
1852
+ "kind": {
1853
+ "enum": [
1854
+ "not_before",
1855
+ "gate",
1856
+ "event"
1857
+ ],
1858
+ "type": "string"
1859
+ },
1860
+ "label": {
1861
+ "nullable": true,
1862
+ "type": "string"
1863
+ },
1864
+ "not_before": {
1865
+ "format": "date-time",
1866
+ "nullable": true,
1867
+ "type": "string"
1868
+ }
1869
+ },
1870
+ "required": [
1871
+ "kind",
1872
+ "label",
1873
+ "not_before"
1874
+ ],
1875
+ "type": "object"
1876
+ },
1877
+ "id": {
1878
+ "type": "string"
1879
+ },
1880
+ "kind": {
1881
+ "enum": [
1882
+ "condition_event"
1883
+ ],
1884
+ "type": "string"
1885
+ },
1886
+ "occurred_at": {
1887
+ "format": "date-time",
1888
+ "type": "string"
1889
+ },
1890
+ "provenance": {
1891
+ "properties": {
1892
+ "kind": {
1893
+ "enum": [
1894
+ "live",
1895
+ "import",
1896
+ "backfill"
1897
+ ],
1898
+ "type": "string"
1899
+ },
1900
+ "witnessed": {
1901
+ "type": "boolean"
1902
+ }
1903
+ },
1904
+ "required": [
1905
+ "kind",
1906
+ "witnessed"
1907
+ ],
1908
+ "type": "object"
1909
+ }
1910
+ },
1911
+ "required": [
1912
+ "id",
1913
+ "kind",
1914
+ "occurred_at",
1915
+ "action",
1916
+ "actor",
1917
+ "provenance",
1918
+ "condition"
1919
+ ],
1920
+ "type": "object"
1753
1921
  }
1754
1922
  ]
1755
1923
  },
@@ -1983,7 +2151,7 @@
1983
2151
  "post": {
1984
2152
  "callbacks": {},
1985
2153
  "deprecated": false,
1986
- "description": "Requires the `harness:write` scope. Atomic compare-and-swap: assigns the caller and moves the issue to the team's first started-type state. Idempotent for the current claimant.",
2154
+ "description": "Requires the `harness:write` scope. Atomic compare-and-swap: assigns the caller and moves the issue to the team's first started-type state, after re-checking readiness inside the transaction. Idempotent for the current claimant.",
1987
2155
  "parameters": [
1988
2156
  {
1989
2157
  "description": "Issue identifier, e.g. ALL-4901 or CLI-12 (issues minted before team-prefixed numbering carry IO-)",
@@ -2012,7 +2180,7 @@
2012
2180
  "description": "Not found"
2013
2181
  },
2014
2182
  "409": {
2015
- "description": "Already claimed by someone else"
2183
+ "description": "The issue is not claimable. `error` is `conflict` and `reason` names why: `claimed_by_other`, `archived`, `agent_step`, `closed`, `blocked`, `held`, `plan_not_released`, `not_in_plan_revision`, `edited_since_release`, `open_children`, `waiting_on_condition` or `duplicate`."
2016
2184
  },
2017
2185
  "422": {
2018
2186
  "description": "Validation error"
@@ -2208,6 +2376,15 @@
2208
2376
  "maxLength": 255,
2209
2377
  "type": "string"
2210
2378
  },
2379
+ "purpose": {
2380
+ "description": "Optional semantic role independent of the display name. Duplicate requires a canceled state and may be assigned to only one state per team.",
2381
+ "enum": [
2382
+ null,
2383
+ "duplicate"
2384
+ ],
2385
+ "nullable": true,
2386
+ "type": "string"
2387
+ },
2211
2388
  "type": {
2212
2389
  "description": "The state's semantics, independent of its display name.",
2213
2390
  "enum": [
@@ -2335,7 +2512,7 @@
2335
2512
  "post": {
2336
2513
  "callbacks": {},
2337
2514
  "deprecated": false,
2338
- "description": "Requires the `harness:write` scope. Moves the issue to the team's first completed-type state (canceled-type with `cancel`). With `duplicate_of`, atomically records a duplicate relation, moves to the team's duplicate-purpose state, and posts `reason`; `cancel` and `duplicate_of` are mutually exclusive. The response's `unblocked` lists identifiers of issues that became ready because this one closed.",
2515
+ "description": "Requires the `harness:write` scope. Moves the issue to the team's first completed-type state (canceled-type with `cancel`). With `duplicate_of`, atomically records a duplicate relation, moves to the team's duplicate-purpose state, and posts `reason`; `cancel` and `duplicate_of` are mutually exclusive. A duplicate's outgoing blocking edges move to the canonical issue. The response's `unblocked` lists identifiers of issues that became ready because this one closed (its dependents and, once no open child is left, its parent; only completing releases them: a cancelled issue still blocks), read after the close committed, and `still_blocking` lists the dependents a cancelled or duplicate-closed issue still blocks.",
2339
2516
  "parameters": [
2340
2517
  {
2341
2518
  "description": "Issue identifier, e.g. ALL-4901 or CLI-12 (issues minted before team-prefixed numbering carry IO-)",
@@ -2825,6 +3002,55 @@
2825
3002
  "tags": []
2826
3003
  }
2827
3004
  },
3005
+ "/api/v1/issues/next": {
3006
+ "get": {
3007
+ "callbacks": {},
3008
+ "deprecated": false,
3009
+ "description": "Requires the `harness:read` scope. The organization's ready issues in the order claim-next takes them: urgent, high, medium, low, then none; oldest first, then by id. Like the ready list, it includes ready issues someone already holds. There is no pagination. The read behind `harness prime`; for paginated, filterable listings use `GET /api/v1/issues` instead.",
3010
+ "parameters": [
3011
+ {
3012
+ "description": "Only this team's issues (team key)",
3013
+ "in": "query",
3014
+ "name": "team",
3015
+ "required": false,
3016
+ "schema": {
3017
+ "type": "string"
3018
+ }
3019
+ },
3020
+ {
3021
+ "description": "Maximum results (default 10, capped at 50)",
3022
+ "in": "query",
3023
+ "name": "limit",
3024
+ "required": false,
3025
+ "schema": {
3026
+ "type": "integer"
3027
+ }
3028
+ }
3029
+ ],
3030
+ "responses": {
3031
+ "200": {
3032
+ "description": "Success"
3033
+ },
3034
+ "400": {
3035
+ "description": "Bad request"
3036
+ },
3037
+ "401": {
3038
+ "description": "Missing or invalid token"
3039
+ },
3040
+ "403": {
3041
+ "description": "Token not permitted (org-scoped, non-admin, or missing scope)"
3042
+ },
3043
+ "404": {
3044
+ "description": "Not found"
3045
+ },
3046
+ "422": {
3047
+ "description": "Validation error"
3048
+ }
3049
+ },
3050
+ "summary": "List the most important ready issues",
3051
+ "tags": []
3052
+ }
3053
+ },
2828
3054
  "/api/v1/issues/{identifier}/comments/{comment_id}": {
2829
3055
  "delete": {
2830
3056
  "callbacks": {},
@@ -3128,7 +3354,7 @@
3128
3354
  "get": {
3129
3355
  "callbacks": {},
3130
3356
  "deprecated": false,
3131
- "description": "Requires the `model-keys:read` scope. The org's model-provider API keys as a provider => key map (e.g. anthropic, openai, google, openrouter), for tools that dispatch model calls, such as rcl. Which providers are offered is server configuration; the response is never cached. Login tokens carry the scope automatically; aone_ tokens need it minted explicitly.",
3357
+ "description": "Requires the `model-keys:read` scope. The org's provider API keys as a provider => key map (anthropic, openai, google, openrouter, brave, perplexity), for tools that dispatch model calls or research, such as rcl and the harness CLI. Which providers are offered is server configuration; the response is never cached. Login tokens carry the scope automatically; aone_ tokens need it minted explicitly.",
3132
3358
  "parameters": [],
3133
3359
  "responses": {
3134
3360
  "200": {
@@ -3951,6 +4177,3693 @@
3951
4177
  "summary": "Revoke the presented login token",
3952
4178
  "tags": []
3953
4179
  }
4180
+ },
4181
+ "/api/v1/issues/{identifier}/conditions": {
4182
+ "get": {
4183
+ "callbacks": {},
4184
+ "deprecated": false,
4185
+ "description": "Requires the `harness:read` scope. Oldest first. The issue is ready only when every condition is satisfied: a `not_before` instant once the server clock reaches it, a `gate` once a person with staff standing ticks it.",
4186
+ "parameters": [
4187
+ {
4188
+ "description": "Issue identifier, e.g. ALL-4901 or CLI-12 (issues minted before team-prefixed numbering carry IO-)",
4189
+ "in": "path",
4190
+ "name": "identifier",
4191
+ "required": true,
4192
+ "schema": {
4193
+ "type": "string"
4194
+ }
4195
+ }
4196
+ ],
4197
+ "responses": {
4198
+ "200": {
4199
+ "content": {
4200
+ "application/json": {
4201
+ "schema": {
4202
+ "properties": {
4203
+ "data": {
4204
+ "items": {
4205
+ "additionalProperties": false,
4206
+ "properties": {
4207
+ "id": {
4208
+ "format": "uuid",
4209
+ "type": "string"
4210
+ },
4211
+ "inserted_at": {
4212
+ "format": "date-time",
4213
+ "type": "string"
4214
+ },
4215
+ "issue_id": {
4216
+ "format": "uuid",
4217
+ "type": "string"
4218
+ },
4219
+ "kind": {
4220
+ "enum": [
4221
+ "not_before",
4222
+ "gate",
4223
+ "event"
4224
+ ],
4225
+ "type": "string"
4226
+ },
4227
+ "label": {
4228
+ "description": "A gate's label; null for other kinds",
4229
+ "nullable": true,
4230
+ "type": "string"
4231
+ },
4232
+ "not_before": {
4233
+ "description": "A `not_before` condition's instant; null for other kinds",
4234
+ "format": "date-time",
4235
+ "nullable": true,
4236
+ "type": "string"
4237
+ },
4238
+ "satisfied": {
4239
+ "type": "boolean"
4240
+ },
4241
+ "satisfied_at": {
4242
+ "format": "date-time",
4243
+ "nullable": true,
4244
+ "type": "string"
4245
+ },
4246
+ "satisfied_by": {
4247
+ "description": "Who ticked a gate; null otherwise",
4248
+ "nullable": true,
4249
+ "properties": {
4250
+ "email": {
4251
+ "nullable": true,
4252
+ "type": "string"
4253
+ },
4254
+ "id": {
4255
+ "format": "uuid",
4256
+ "nullable": true,
4257
+ "type": "string"
4258
+ },
4259
+ "name": {
4260
+ "nullable": true,
4261
+ "type": "string"
4262
+ }
4263
+ },
4264
+ "required": [
4265
+ "id",
4266
+ "name",
4267
+ "email"
4268
+ ],
4269
+ "type": "object"
4270
+ },
4271
+ "updated_at": {
4272
+ "format": "date-time",
4273
+ "type": "string"
4274
+ }
4275
+ },
4276
+ "required": [
4277
+ "id",
4278
+ "issue_id",
4279
+ "kind",
4280
+ "label",
4281
+ "not_before",
4282
+ "satisfied",
4283
+ "satisfied_at",
4284
+ "satisfied_by",
4285
+ "inserted_at",
4286
+ "updated_at"
4287
+ ],
4288
+ "type": "object"
4289
+ },
4290
+ "type": "array"
4291
+ }
4292
+ },
4293
+ "required": [
4294
+ "data"
4295
+ ],
4296
+ "type": "object"
4297
+ }
4298
+ }
4299
+ },
4300
+ "description": "Success"
4301
+ },
4302
+ "400": {
4303
+ "description": "Bad request"
4304
+ },
4305
+ "401": {
4306
+ "description": "Missing or invalid token"
4307
+ },
4308
+ "403": {
4309
+ "description": "Token not permitted (org-scoped, non-admin, or missing scope)"
4310
+ },
4311
+ "404": {
4312
+ "description": "Not found"
4313
+ },
4314
+ "422": {
4315
+ "description": "Validation error"
4316
+ }
4317
+ },
4318
+ "summary": "List an issue's wait conditions",
4319
+ "tags": []
4320
+ },
4321
+ "post": {
4322
+ "callbacks": {},
4323
+ "deprecated": false,
4324
+ "description": "Requires the `harness:write` scope. A `not_before` instant already passed is satisfied at once; a future one is satisfied when the server clock reaches it. A `gate` starts unsatisfied. `event` conditions cannot be created yet.",
4325
+ "parameters": [
4326
+ {
4327
+ "description": "Issue identifier, e.g. ALL-4901 or CLI-12 (issues minted before team-prefixed numbering carry IO-)",
4328
+ "in": "path",
4329
+ "name": "identifier",
4330
+ "required": true,
4331
+ "schema": {
4332
+ "type": "string"
4333
+ }
4334
+ }
4335
+ ],
4336
+ "requestBody": {
4337
+ "content": {
4338
+ "application/json": {
4339
+ "schema": {
4340
+ "properties": {
4341
+ "kind": {
4342
+ "enum": [
4343
+ "not_before",
4344
+ "gate"
4345
+ ],
4346
+ "type": "string"
4347
+ },
4348
+ "label": {
4349
+ "description": "Required for `gate`: what the gate waits for",
4350
+ "maxLength": 200,
4351
+ "type": "string"
4352
+ },
4353
+ "not_before": {
4354
+ "description": "Required for `not_before`: an ISO 8601 instant, stored in UTC to the second",
4355
+ "format": "date-time",
4356
+ "type": "string"
4357
+ }
4358
+ },
4359
+ "required": [
4360
+ "kind"
4361
+ ],
4362
+ "type": "object"
4363
+ }
4364
+ }
4365
+ },
4366
+ "required": true
4367
+ },
4368
+ "responses": {
4369
+ "200": {
4370
+ "description": "Success"
4371
+ },
4372
+ "201": {
4373
+ "content": {
4374
+ "application/json": {
4375
+ "schema": {
4376
+ "properties": {
4377
+ "data": {
4378
+ "additionalProperties": false,
4379
+ "properties": {
4380
+ "id": {
4381
+ "format": "uuid",
4382
+ "type": "string"
4383
+ },
4384
+ "inserted_at": {
4385
+ "format": "date-time",
4386
+ "type": "string"
4387
+ },
4388
+ "issue_id": {
4389
+ "format": "uuid",
4390
+ "type": "string"
4391
+ },
4392
+ "kind": {
4393
+ "enum": [
4394
+ "not_before",
4395
+ "gate",
4396
+ "event"
4397
+ ],
4398
+ "type": "string"
4399
+ },
4400
+ "label": {
4401
+ "description": "A gate's label; null for other kinds",
4402
+ "nullable": true,
4403
+ "type": "string"
4404
+ },
4405
+ "not_before": {
4406
+ "description": "A `not_before` condition's instant; null for other kinds",
4407
+ "format": "date-time",
4408
+ "nullable": true,
4409
+ "type": "string"
4410
+ },
4411
+ "satisfied": {
4412
+ "type": "boolean"
4413
+ },
4414
+ "satisfied_at": {
4415
+ "format": "date-time",
4416
+ "nullable": true,
4417
+ "type": "string"
4418
+ },
4419
+ "satisfied_by": {
4420
+ "description": "Who ticked a gate; null otherwise",
4421
+ "nullable": true,
4422
+ "properties": {
4423
+ "email": {
4424
+ "nullable": true,
4425
+ "type": "string"
4426
+ },
4427
+ "id": {
4428
+ "format": "uuid",
4429
+ "nullable": true,
4430
+ "type": "string"
4431
+ },
4432
+ "name": {
4433
+ "nullable": true,
4434
+ "type": "string"
4435
+ }
4436
+ },
4437
+ "required": [
4438
+ "id",
4439
+ "name",
4440
+ "email"
4441
+ ],
4442
+ "type": "object"
4443
+ },
4444
+ "updated_at": {
4445
+ "format": "date-time",
4446
+ "type": "string"
4447
+ }
4448
+ },
4449
+ "required": [
4450
+ "id",
4451
+ "issue_id",
4452
+ "kind",
4453
+ "label",
4454
+ "not_before",
4455
+ "satisfied",
4456
+ "satisfied_at",
4457
+ "satisfied_by",
4458
+ "inserted_at",
4459
+ "updated_at"
4460
+ ],
4461
+ "type": "object"
4462
+ }
4463
+ },
4464
+ "required": [
4465
+ "data"
4466
+ ],
4467
+ "type": "object"
4468
+ }
4469
+ }
4470
+ },
4471
+ "description": "Success"
4472
+ },
4473
+ "400": {
4474
+ "description": "Bad request"
4475
+ },
4476
+ "401": {
4477
+ "description": "Missing or invalid token"
4478
+ },
4479
+ "403": {
4480
+ "description": "Token not permitted (org-scoped, non-admin, or missing scope)"
4481
+ },
4482
+ "404": {
4483
+ "description": "Not found"
4484
+ },
4485
+ "422": {
4486
+ "description": "Validation error"
4487
+ }
4488
+ },
4489
+ "summary": "Add a wait condition",
4490
+ "tags": []
4491
+ }
4492
+ },
4493
+ "/api/v1/issues/{identifier}/conditions/{id}": {
4494
+ "delete": {
4495
+ "callbacks": {},
4496
+ "deprecated": false,
4497
+ "description": "Requires the `harness:write` scope.",
4498
+ "parameters": [
4499
+ {
4500
+ "description": "Issue identifier, e.g. ALL-4901 or CLI-12 (issues minted before team-prefixed numbering carry IO-)",
4501
+ "in": "path",
4502
+ "name": "identifier",
4503
+ "required": true,
4504
+ "schema": {
4505
+ "type": "string"
4506
+ }
4507
+ },
4508
+ {
4509
+ "description": "Resource id",
4510
+ "in": "path",
4511
+ "name": "id",
4512
+ "required": true,
4513
+ "schema": {
4514
+ "type": "string"
4515
+ }
4516
+ }
4517
+ ],
4518
+ "responses": {
4519
+ "200": {
4520
+ "description": "Success"
4521
+ },
4522
+ "400": {
4523
+ "description": "Bad request"
4524
+ },
4525
+ "401": {
4526
+ "description": "Missing or invalid token"
4527
+ },
4528
+ "403": {
4529
+ "description": "Token not permitted (org-scoped, non-admin, or missing scope)"
4530
+ },
4531
+ "404": {
4532
+ "description": "Not found"
4533
+ },
4534
+ "422": {
4535
+ "description": "Validation error"
4536
+ }
4537
+ },
4538
+ "summary": "Remove a wait condition",
4539
+ "tags": []
4540
+ },
4541
+ "patch": {
4542
+ "callbacks": {},
4543
+ "deprecated": false,
4544
+ "description": "Requires the `harness:write` scope. Changes a gate's `label` or a `not_before` instant; the kind never changes. A moved instant is re-evaluated: a future one is unsatisfied until the clock reaches it.",
4545
+ "parameters": [
4546
+ {
4547
+ "description": "Issue identifier, e.g. ALL-4901 or CLI-12 (issues minted before team-prefixed numbering carry IO-)",
4548
+ "in": "path",
4549
+ "name": "identifier",
4550
+ "required": true,
4551
+ "schema": {
4552
+ "type": "string"
4553
+ }
4554
+ },
4555
+ {
4556
+ "description": "Resource id",
4557
+ "in": "path",
4558
+ "name": "id",
4559
+ "required": true,
4560
+ "schema": {
4561
+ "type": "string"
4562
+ }
4563
+ }
4564
+ ],
4565
+ "requestBody": {
4566
+ "content": {
4567
+ "application/json": {
4568
+ "schema": {
4569
+ "properties": {
4570
+ "label": {
4571
+ "description": "A gate's new label",
4572
+ "maxLength": 200,
4573
+ "type": "string"
4574
+ },
4575
+ "not_before": {
4576
+ "description": "A `not_before` condition's new instant",
4577
+ "format": "date-time",
4578
+ "type": "string"
4579
+ }
4580
+ },
4581
+ "type": "object"
4582
+ }
4583
+ }
4584
+ },
4585
+ "required": true
4586
+ },
4587
+ "responses": {
4588
+ "200": {
4589
+ "content": {
4590
+ "application/json": {
4591
+ "schema": {
4592
+ "properties": {
4593
+ "data": {
4594
+ "additionalProperties": false,
4595
+ "properties": {
4596
+ "id": {
4597
+ "format": "uuid",
4598
+ "type": "string"
4599
+ },
4600
+ "inserted_at": {
4601
+ "format": "date-time",
4602
+ "type": "string"
4603
+ },
4604
+ "issue_id": {
4605
+ "format": "uuid",
4606
+ "type": "string"
4607
+ },
4608
+ "kind": {
4609
+ "enum": [
4610
+ "not_before",
4611
+ "gate",
4612
+ "event"
4613
+ ],
4614
+ "type": "string"
4615
+ },
4616
+ "label": {
4617
+ "description": "A gate's label; null for other kinds",
4618
+ "nullable": true,
4619
+ "type": "string"
4620
+ },
4621
+ "not_before": {
4622
+ "description": "A `not_before` condition's instant; null for other kinds",
4623
+ "format": "date-time",
4624
+ "nullable": true,
4625
+ "type": "string"
4626
+ },
4627
+ "satisfied": {
4628
+ "type": "boolean"
4629
+ },
4630
+ "satisfied_at": {
4631
+ "format": "date-time",
4632
+ "nullable": true,
4633
+ "type": "string"
4634
+ },
4635
+ "satisfied_by": {
4636
+ "description": "Who ticked a gate; null otherwise",
4637
+ "nullable": true,
4638
+ "properties": {
4639
+ "email": {
4640
+ "nullable": true,
4641
+ "type": "string"
4642
+ },
4643
+ "id": {
4644
+ "format": "uuid",
4645
+ "nullable": true,
4646
+ "type": "string"
4647
+ },
4648
+ "name": {
4649
+ "nullable": true,
4650
+ "type": "string"
4651
+ }
4652
+ },
4653
+ "required": [
4654
+ "id",
4655
+ "name",
4656
+ "email"
4657
+ ],
4658
+ "type": "object"
4659
+ },
4660
+ "updated_at": {
4661
+ "format": "date-time",
4662
+ "type": "string"
4663
+ }
4664
+ },
4665
+ "required": [
4666
+ "id",
4667
+ "issue_id",
4668
+ "kind",
4669
+ "label",
4670
+ "not_before",
4671
+ "satisfied",
4672
+ "satisfied_at",
4673
+ "satisfied_by",
4674
+ "inserted_at",
4675
+ "updated_at"
4676
+ ],
4677
+ "type": "object"
4678
+ }
4679
+ },
4680
+ "required": [
4681
+ "data"
4682
+ ],
4683
+ "type": "object"
4684
+ }
4685
+ }
4686
+ },
4687
+ "description": "Success"
4688
+ },
4689
+ "400": {
4690
+ "description": "Bad request"
4691
+ },
4692
+ "401": {
4693
+ "description": "Missing or invalid token"
4694
+ },
4695
+ "403": {
4696
+ "description": "Token not permitted (org-scoped, non-admin, or missing scope)"
4697
+ },
4698
+ "404": {
4699
+ "description": "Not found"
4700
+ },
4701
+ "422": {
4702
+ "description": "Validation error"
4703
+ }
4704
+ },
4705
+ "summary": "Edit a wait condition",
4706
+ "tags": []
4707
+ }
4708
+ },
4709
+ "/api/v1/issues/{identifier}/conditions/{id}/satisfaction": {
4710
+ "put": {
4711
+ "callbacks": {},
4712
+ "deprecated": false,
4713
+ "description": "Requires the `harness:write` scope. Satisfies (`true`) or un-satisfies (`false`) a `gate` as the credential's user, who must have staff standing in the organization. Repeating the current state changes nothing. Other kinds answer 422.",
4714
+ "parameters": [
4715
+ {
4716
+ "description": "Issue identifier, e.g. ALL-4901 or CLI-12 (issues minted before team-prefixed numbering carry IO-)",
4717
+ "in": "path",
4718
+ "name": "identifier",
4719
+ "required": true,
4720
+ "schema": {
4721
+ "type": "string"
4722
+ }
4723
+ },
4724
+ {
4725
+ "description": "Resource id",
4726
+ "in": "path",
4727
+ "name": "id",
4728
+ "required": true,
4729
+ "schema": {
4730
+ "type": "string"
4731
+ }
4732
+ }
4733
+ ],
4734
+ "requestBody": {
4735
+ "content": {
4736
+ "application/json": {
4737
+ "schema": {
4738
+ "properties": {
4739
+ "satisfied": {
4740
+ "type": "boolean"
4741
+ }
4742
+ },
4743
+ "required": [
4744
+ "satisfied"
4745
+ ],
4746
+ "type": "object"
4747
+ }
4748
+ }
4749
+ },
4750
+ "required": true
4751
+ },
4752
+ "responses": {
4753
+ "200": {
4754
+ "content": {
4755
+ "application/json": {
4756
+ "schema": {
4757
+ "properties": {
4758
+ "data": {
4759
+ "additionalProperties": false,
4760
+ "properties": {
4761
+ "id": {
4762
+ "format": "uuid",
4763
+ "type": "string"
4764
+ },
4765
+ "inserted_at": {
4766
+ "format": "date-time",
4767
+ "type": "string"
4768
+ },
4769
+ "issue_id": {
4770
+ "format": "uuid",
4771
+ "type": "string"
4772
+ },
4773
+ "kind": {
4774
+ "enum": [
4775
+ "not_before",
4776
+ "gate",
4777
+ "event"
4778
+ ],
4779
+ "type": "string"
4780
+ },
4781
+ "label": {
4782
+ "description": "A gate's label; null for other kinds",
4783
+ "nullable": true,
4784
+ "type": "string"
4785
+ },
4786
+ "not_before": {
4787
+ "description": "A `not_before` condition's instant; null for other kinds",
4788
+ "format": "date-time",
4789
+ "nullable": true,
4790
+ "type": "string"
4791
+ },
4792
+ "satisfied": {
4793
+ "type": "boolean"
4794
+ },
4795
+ "satisfied_at": {
4796
+ "format": "date-time",
4797
+ "nullable": true,
4798
+ "type": "string"
4799
+ },
4800
+ "satisfied_by": {
4801
+ "description": "Who ticked a gate; null otherwise",
4802
+ "nullable": true,
4803
+ "properties": {
4804
+ "email": {
4805
+ "nullable": true,
4806
+ "type": "string"
4807
+ },
4808
+ "id": {
4809
+ "format": "uuid",
4810
+ "nullable": true,
4811
+ "type": "string"
4812
+ },
4813
+ "name": {
4814
+ "nullable": true,
4815
+ "type": "string"
4816
+ }
4817
+ },
4818
+ "required": [
4819
+ "id",
4820
+ "name",
4821
+ "email"
4822
+ ],
4823
+ "type": "object"
4824
+ },
4825
+ "updated_at": {
4826
+ "format": "date-time",
4827
+ "type": "string"
4828
+ }
4829
+ },
4830
+ "required": [
4831
+ "id",
4832
+ "issue_id",
4833
+ "kind",
4834
+ "label",
4835
+ "not_before",
4836
+ "satisfied",
4837
+ "satisfied_at",
4838
+ "satisfied_by",
4839
+ "inserted_at",
4840
+ "updated_at"
4841
+ ],
4842
+ "type": "object"
4843
+ }
4844
+ },
4845
+ "required": [
4846
+ "data"
4847
+ ],
4848
+ "type": "object"
4849
+ }
4850
+ }
4851
+ },
4852
+ "description": "Success"
4853
+ },
4854
+ "400": {
4855
+ "description": "Bad request"
4856
+ },
4857
+ "401": {
4858
+ "description": "Missing or invalid token"
4859
+ },
4860
+ "403": {
4861
+ "description": "Token not permitted (org-scoped, non-admin, or missing scope)"
4862
+ },
4863
+ "404": {
4864
+ "description": "Not found"
4865
+ },
4866
+ "422": {
4867
+ "description": "Validation error"
4868
+ }
4869
+ },
4870
+ "summary": "Tick or untick a gate",
4871
+ "tags": []
4872
+ }
4873
+ },
4874
+ "/api/v1/teams/{team_key}/plans": {
4875
+ "post": {
4876
+ "callbacks": {},
4877
+ "deprecated": false,
4878
+ "description": "Requires the `harness:write` scope. Creates a whole plan in one transaction, or nothing: the root issue in this team, every step (Operator steps in the organization's Operator team, a person's in `team` or this team), their parents, `blocked_by` edges and wait conditions, and the plan, created `held`. Steps refer to each other by `key`. An invalid plan answers 422 `invalid_plan` with every violation, each naming the step's `key` and its `index` in `steps` (both null for the root and the plan). A plan has at most 100 steps, its root included. An optional Idempotency-Key works as for issue creation: an identical replay returns the plan with 200 and Idempotency-Replayed: true, and a key reused for a different request answers 409.",
4879
+ "parameters": [
4880
+ {
4881
+ "description": "Team key, e.g. ALL",
4882
+ "in": "path",
4883
+ "name": "team_key",
4884
+ "required": true,
4885
+ "schema": {
4886
+ "type": "string"
4887
+ }
4888
+ },
4889
+ {
4890
+ "description": "Credential-scoped printable-ASCII key for retrying this plan creation",
4891
+ "in": "header",
4892
+ "name": "Idempotency-Key",
4893
+ "required": false,
4894
+ "schema": {
4895
+ "maxLength": 200,
4896
+ "minLength": 1,
4897
+ "pattern": "^[!-~](?:[ -~]*[!-~])?(?![\\s\\S])",
4898
+ "type": "string"
4899
+ }
4900
+ }
4901
+ ],
4902
+ "requestBody": {
4903
+ "content": {
4904
+ "application/json": {
4905
+ "schema": {
4906
+ "additionalProperties": false,
4907
+ "properties": {
4908
+ "acceptance_criteria": {
4909
+ "type": "string"
4910
+ },
4911
+ "actor": {
4912
+ "description": "Display name to attribute the write to (e.g. an agent). Defaults to the token name for API tokens and to the signed-in user for login tokens. Display-only, never an access-control input.",
4913
+ "type": "string"
4914
+ },
4915
+ "assignee": {
4916
+ "description": "\"me\" for the token owner, a user id, an email address, or an exact display name; not for Operator steps",
4917
+ "type": "string"
4918
+ },
4919
+ "description": {
4920
+ "description": "An Operator step's description is its instruction",
4921
+ "type": "string"
4922
+ },
4923
+ "design": {
4924
+ "type": "string"
4925
+ },
4926
+ "due_date": {
4927
+ "format": "date",
4928
+ "type": "string"
4929
+ },
4930
+ "estimate": {
4931
+ "type": "number"
4932
+ },
4933
+ "label_ids": {
4934
+ "description": "Workspace labels, or labels of the issue's team",
4935
+ "items": {
4936
+ "format": "uuid",
4937
+ "type": "string"
4938
+ },
4939
+ "maxItems": 50,
4940
+ "type": "array"
4941
+ },
4942
+ "notes": {
4943
+ "type": "string"
4944
+ },
4945
+ "parent": {
4946
+ "description": "An existing issue to file the root under, e.g. ALL-4223",
4947
+ "type": "string"
4948
+ },
4949
+ "priority": {
4950
+ "description": "0 none, 1 urgent, 2 high, 3 medium, 4 low",
4951
+ "type": "integer"
4952
+ },
4953
+ "retry_budget": {
4954
+ "description": "Retries per failed Operator step (default 2)",
4955
+ "minimum": 0,
4956
+ "type": "integer"
4957
+ },
4958
+ "spend_budget_cents": {
4959
+ "description": "The plan's spend budget; a plan with Operator steps needs one to be released",
4960
+ "minimum": 0,
4961
+ "nullable": true,
4962
+ "type": "integer"
4963
+ },
4964
+ "steps": {
4965
+ "items": {
4966
+ "additionalProperties": false,
4967
+ "properties": {
4968
+ "acceptance_criteria": {
4969
+ "type": "string"
4970
+ },
4971
+ "assignee": {
4972
+ "description": "\"me\" for the token owner, a user id, an email address, or an exact display name; not for Operator steps",
4973
+ "type": "string"
4974
+ },
4975
+ "blocked_by": {
4976
+ "description": "Keys of the steps it waits for",
4977
+ "items": {
4978
+ "type": "string"
4979
+ },
4980
+ "type": "array"
4981
+ },
4982
+ "conditions": {
4983
+ "items": {
4984
+ "additionalProperties": false,
4985
+ "properties": {
4986
+ "event": {
4987
+ "description": "For `event`: an allowlisted system event",
4988
+ "type": "string"
4989
+ },
4990
+ "kind": {
4991
+ "enum": [
4992
+ "not_before",
4993
+ "gate",
4994
+ "event"
4995
+ ],
4996
+ "type": "string"
4997
+ },
4998
+ "label": {
4999
+ "description": "For `gate`",
5000
+ "maxLength": 200,
5001
+ "type": "string"
5002
+ },
5003
+ "not_before": {
5004
+ "description": "For `not_before`",
5005
+ "format": "date-time",
5006
+ "type": "string"
5007
+ },
5008
+ "subject_id": {
5009
+ "description": "For `event`: a record you can read",
5010
+ "format": "uuid",
5011
+ "type": "string"
5012
+ },
5013
+ "target_id": {
5014
+ "description": "For `event` kinds with a target",
5015
+ "format": "uuid",
5016
+ "type": "string"
5017
+ }
5018
+ },
5019
+ "required": [
5020
+ "kind"
5021
+ ],
5022
+ "type": "object"
5023
+ },
5024
+ "maxItems": 20,
5025
+ "type": "array"
5026
+ },
5027
+ "description": {
5028
+ "description": "An Operator step's description is its instruction",
5029
+ "type": "string"
5030
+ },
5031
+ "design": {
5032
+ "type": "string"
5033
+ },
5034
+ "due_date": {
5035
+ "format": "date",
5036
+ "type": "string"
5037
+ },
5038
+ "estimate": {
5039
+ "type": "number"
5040
+ },
5041
+ "executor": {
5042
+ "description": "Defaults to none (a person)",
5043
+ "enum": [
5044
+ "none",
5045
+ "operator"
5046
+ ],
5047
+ "type": "string"
5048
+ },
5049
+ "key": {
5050
+ "description": "Unique in the plan",
5051
+ "maxLength": 100,
5052
+ "minLength": 1,
5053
+ "type": "string"
5054
+ },
5055
+ "label_ids": {
5056
+ "description": "Workspace labels, or labels of the issue's team",
5057
+ "items": {
5058
+ "format": "uuid",
5059
+ "type": "string"
5060
+ },
5061
+ "maxItems": 50,
5062
+ "type": "array"
5063
+ },
5064
+ "notes": {
5065
+ "type": "string"
5066
+ },
5067
+ "parent": {
5068
+ "description": "The key of the step that contains this one; the root when absent",
5069
+ "type": "string"
5070
+ },
5071
+ "priority": {
5072
+ "description": "0 none, 1 urgent, 2 high, 3 medium, 4 low",
5073
+ "type": "integer"
5074
+ },
5075
+ "team": {
5076
+ "description": "Team key for a person's step (the request's team when absent); Operator steps go to Operator",
5077
+ "type": "string"
5078
+ },
5079
+ "title": {
5080
+ "type": "string"
5081
+ }
5082
+ },
5083
+ "required": [
5084
+ "key",
5085
+ "title"
5086
+ ],
5087
+ "type": "object"
5088
+ },
5089
+ "maxItems": 99,
5090
+ "minItems": 1,
5091
+ "type": "array"
5092
+ },
5093
+ "title": {
5094
+ "type": "string"
5095
+ }
5096
+ },
5097
+ "required": [
5098
+ "title",
5099
+ "steps"
5100
+ ],
5101
+ "type": "object"
5102
+ }
5103
+ }
5104
+ },
5105
+ "required": true
5106
+ },
5107
+ "responses": {
5108
+ "200": {
5109
+ "content": {
5110
+ "application/json": {
5111
+ "schema": {
5112
+ "properties": {
5113
+ "data": {
5114
+ "properties": {
5115
+ "created_by": {
5116
+ "nullable": true,
5117
+ "properties": {
5118
+ "email": {
5119
+ "nullable": true,
5120
+ "type": "string"
5121
+ },
5122
+ "id": {
5123
+ "format": "uuid",
5124
+ "nullable": true,
5125
+ "type": "string"
5126
+ },
5127
+ "name": {
5128
+ "nullable": true,
5129
+ "type": "string"
5130
+ }
5131
+ },
5132
+ "required": [
5133
+ "id",
5134
+ "name",
5135
+ "email"
5136
+ ],
5137
+ "type": "object"
5138
+ },
5139
+ "edges": {
5140
+ "items": {
5141
+ "properties": {
5142
+ "from": {
5143
+ "type": "string"
5144
+ },
5145
+ "to": {
5146
+ "type": "string"
5147
+ }
5148
+ },
5149
+ "required": [
5150
+ "from",
5151
+ "to"
5152
+ ],
5153
+ "type": "object"
5154
+ },
5155
+ "type": "array"
5156
+ },
5157
+ "estimate": {
5158
+ "nullable": true,
5159
+ "properties": {
5160
+ "ceiling_cents": {
5161
+ "type": "integer"
5162
+ },
5163
+ "minimum_budget_cents": {
5164
+ "type": "integer"
5165
+ },
5166
+ "per_attempt_reservation_cents": {
5167
+ "type": "integer"
5168
+ },
5169
+ "step_cap_cents": {
5170
+ "type": "integer"
5171
+ }
5172
+ },
5173
+ "type": "object"
5174
+ },
5175
+ "held_steps": {
5176
+ "description": "Steps an edit holds",
5177
+ "items": {
5178
+ "type": "string"
5179
+ },
5180
+ "type": "array"
5181
+ },
5182
+ "id": {
5183
+ "format": "uuid",
5184
+ "type": "string"
5185
+ },
5186
+ "inserted_at": {
5187
+ "format": "date-time",
5188
+ "type": "string"
5189
+ },
5190
+ "released_at": {
5191
+ "format": "date-time",
5192
+ "nullable": true,
5193
+ "type": "string"
5194
+ },
5195
+ "released_by": {
5196
+ "nullable": true,
5197
+ "properties": {
5198
+ "email": {
5199
+ "nullable": true,
5200
+ "type": "string"
5201
+ },
5202
+ "id": {
5203
+ "format": "uuid",
5204
+ "nullable": true,
5205
+ "type": "string"
5206
+ },
5207
+ "name": {
5208
+ "nullable": true,
5209
+ "type": "string"
5210
+ }
5211
+ },
5212
+ "required": [
5213
+ "id",
5214
+ "name",
5215
+ "email"
5216
+ ],
5217
+ "type": "object"
5218
+ },
5219
+ "retry_budget": {
5220
+ "type": "integer"
5221
+ },
5222
+ "revision": {
5223
+ "nullable": true,
5224
+ "properties": {
5225
+ "checksum": {
5226
+ "description": "SHA-256 of the frozen steps",
5227
+ "type": "string"
5228
+ },
5229
+ "id": {
5230
+ "format": "uuid",
5231
+ "type": "string"
5232
+ },
5233
+ "inserted_at": {
5234
+ "format": "date-time",
5235
+ "type": "string"
5236
+ },
5237
+ "number": {
5238
+ "type": "integer"
5239
+ }
5240
+ },
5241
+ "required": [
5242
+ "id",
5243
+ "number",
5244
+ "checksum",
5245
+ "inserted_at"
5246
+ ],
5247
+ "type": "object"
5248
+ },
5249
+ "root": {
5250
+ "nullable": true,
5251
+ "properties": {
5252
+ "id": {
5253
+ "type": "string"
5254
+ },
5255
+ "identifier": {
5256
+ "type": "string"
5257
+ },
5258
+ "title": {
5259
+ "type": "string"
5260
+ }
5261
+ },
5262
+ "type": "object"
5263
+ },
5264
+ "spend_budget_cents": {
5265
+ "nullable": true,
5266
+ "type": "integer"
5267
+ },
5268
+ "status": {
5269
+ "enum": [
5270
+ "held",
5271
+ "released",
5272
+ "running",
5273
+ "completed",
5274
+ "needs_attention"
5275
+ ],
5276
+ "type": "string"
5277
+ },
5278
+ "steps": {
5279
+ "items": {
5280
+ "properties": {
5281
+ "archived": {
5282
+ "type": "boolean"
5283
+ },
5284
+ "conditions": {
5285
+ "items": {
5286
+ "additionalProperties": false,
5287
+ "properties": {
5288
+ "id": {
5289
+ "format": "uuid",
5290
+ "type": "string"
5291
+ },
5292
+ "inserted_at": {
5293
+ "format": "date-time",
5294
+ "type": "string"
5295
+ },
5296
+ "issue_id": {
5297
+ "format": "uuid",
5298
+ "type": "string"
5299
+ },
5300
+ "kind": {
5301
+ "enum": [
5302
+ "not_before",
5303
+ "gate",
5304
+ "event"
5305
+ ],
5306
+ "type": "string"
5307
+ },
5308
+ "label": {
5309
+ "description": "A gate's label; null for other kinds",
5310
+ "nullable": true,
5311
+ "type": "string"
5312
+ },
5313
+ "not_before": {
5314
+ "description": "A `not_before` condition's instant; null for other kinds",
5315
+ "format": "date-time",
5316
+ "nullable": true,
5317
+ "type": "string"
5318
+ },
5319
+ "satisfied": {
5320
+ "type": "boolean"
5321
+ },
5322
+ "satisfied_at": {
5323
+ "format": "date-time",
5324
+ "nullable": true,
5325
+ "type": "string"
5326
+ },
5327
+ "satisfied_by": {
5328
+ "description": "Who ticked a gate; null otherwise",
5329
+ "nullable": true,
5330
+ "properties": {
5331
+ "email": {
5332
+ "nullable": true,
5333
+ "type": "string"
5334
+ },
5335
+ "id": {
5336
+ "format": "uuid",
5337
+ "nullable": true,
5338
+ "type": "string"
5339
+ },
5340
+ "name": {
5341
+ "nullable": true,
5342
+ "type": "string"
5343
+ }
5344
+ },
5345
+ "required": [
5346
+ "id",
5347
+ "name",
5348
+ "email"
5349
+ ],
5350
+ "type": "object"
5351
+ },
5352
+ "updated_at": {
5353
+ "format": "date-time",
5354
+ "type": "string"
5355
+ }
5356
+ },
5357
+ "required": [
5358
+ "id",
5359
+ "issue_id",
5360
+ "kind",
5361
+ "label",
5362
+ "not_before",
5363
+ "satisfied",
5364
+ "satisfied_at",
5365
+ "satisfied_by",
5366
+ "inserted_at",
5367
+ "updated_at"
5368
+ ],
5369
+ "type": "object"
5370
+ },
5371
+ "type": "array"
5372
+ },
5373
+ "container": {
5374
+ "description": "Has sub-steps; completes when they all complete",
5375
+ "type": "boolean"
5376
+ },
5377
+ "executor": {
5378
+ "enum": [
5379
+ "none",
5380
+ "operator"
5381
+ ],
5382
+ "type": "string"
5383
+ },
5384
+ "held": {
5385
+ "type": "boolean"
5386
+ },
5387
+ "identifier": {
5388
+ "type": "string"
5389
+ },
5390
+ "in_revision": {
5391
+ "type": "boolean"
5392
+ },
5393
+ "issue_id": {
5394
+ "format": "uuid",
5395
+ "type": "string"
5396
+ },
5397
+ "key": {
5398
+ "nullable": true,
5399
+ "type": "string"
5400
+ },
5401
+ "parent": {
5402
+ "description": "The containing step's identifier; null for the root",
5403
+ "nullable": true,
5404
+ "type": "string"
5405
+ },
5406
+ "ready": {
5407
+ "type": "boolean"
5408
+ },
5409
+ "state": {
5410
+ "properties": {
5411
+ "id": {
5412
+ "type": "string"
5413
+ },
5414
+ "name": {
5415
+ "type": "string"
5416
+ },
5417
+ "type": {
5418
+ "type": "string"
5419
+ }
5420
+ },
5421
+ "type": "object"
5422
+ },
5423
+ "team": {
5424
+ "properties": {
5425
+ "id": {
5426
+ "type": "string"
5427
+ },
5428
+ "key": {
5429
+ "type": "string"
5430
+ },
5431
+ "name": {
5432
+ "type": "string"
5433
+ }
5434
+ },
5435
+ "type": "object"
5436
+ },
5437
+ "title": {
5438
+ "type": "string"
5439
+ }
5440
+ },
5441
+ "required": [
5442
+ "issue_id",
5443
+ "identifier",
5444
+ "key",
5445
+ "title",
5446
+ "parent",
5447
+ "executor",
5448
+ "container",
5449
+ "state",
5450
+ "ready",
5451
+ "held",
5452
+ "conditions"
5453
+ ],
5454
+ "type": "object"
5455
+ },
5456
+ "type": "array"
5457
+ },
5458
+ "updated_at": {
5459
+ "format": "date-time",
5460
+ "type": "string"
5461
+ }
5462
+ },
5463
+ "required": [
5464
+ "id",
5465
+ "status",
5466
+ "root",
5467
+ "retry_budget",
5468
+ "spend_budget_cents",
5469
+ "revision",
5470
+ "held_steps",
5471
+ "steps",
5472
+ "edges"
5473
+ ],
5474
+ "type": "object"
5475
+ }
5476
+ },
5477
+ "required": [
5478
+ "data"
5479
+ ],
5480
+ "type": "object"
5481
+ }
5482
+ }
5483
+ },
5484
+ "description": "Idempotent replay",
5485
+ "headers": {
5486
+ "Idempotency-Replayed": {
5487
+ "description": "True when the response replays an earlier plan creation",
5488
+ "required": true,
5489
+ "schema": {
5490
+ "enum": [
5491
+ "true"
5492
+ ],
5493
+ "type": "string"
5494
+ },
5495
+ "style": "simple"
5496
+ }
5497
+ }
5498
+ },
5499
+ "201": {
5500
+ "content": {
5501
+ "application/json": {
5502
+ "schema": {
5503
+ "properties": {
5504
+ "data": {
5505
+ "properties": {
5506
+ "created_by": {
5507
+ "nullable": true,
5508
+ "properties": {
5509
+ "email": {
5510
+ "nullable": true,
5511
+ "type": "string"
5512
+ },
5513
+ "id": {
5514
+ "format": "uuid",
5515
+ "nullable": true,
5516
+ "type": "string"
5517
+ },
5518
+ "name": {
5519
+ "nullable": true,
5520
+ "type": "string"
5521
+ }
5522
+ },
5523
+ "required": [
5524
+ "id",
5525
+ "name",
5526
+ "email"
5527
+ ],
5528
+ "type": "object"
5529
+ },
5530
+ "edges": {
5531
+ "items": {
5532
+ "properties": {
5533
+ "from": {
5534
+ "type": "string"
5535
+ },
5536
+ "to": {
5537
+ "type": "string"
5538
+ }
5539
+ },
5540
+ "required": [
5541
+ "from",
5542
+ "to"
5543
+ ],
5544
+ "type": "object"
5545
+ },
5546
+ "type": "array"
5547
+ },
5548
+ "estimate": {
5549
+ "nullable": true,
5550
+ "properties": {
5551
+ "ceiling_cents": {
5552
+ "type": "integer"
5553
+ },
5554
+ "minimum_budget_cents": {
5555
+ "type": "integer"
5556
+ },
5557
+ "per_attempt_reservation_cents": {
5558
+ "type": "integer"
5559
+ },
5560
+ "step_cap_cents": {
5561
+ "type": "integer"
5562
+ }
5563
+ },
5564
+ "type": "object"
5565
+ },
5566
+ "held_steps": {
5567
+ "description": "Steps an edit holds",
5568
+ "items": {
5569
+ "type": "string"
5570
+ },
5571
+ "type": "array"
5572
+ },
5573
+ "id": {
5574
+ "format": "uuid",
5575
+ "type": "string"
5576
+ },
5577
+ "inserted_at": {
5578
+ "format": "date-time",
5579
+ "type": "string"
5580
+ },
5581
+ "released_at": {
5582
+ "format": "date-time",
5583
+ "nullable": true,
5584
+ "type": "string"
5585
+ },
5586
+ "released_by": {
5587
+ "nullable": true,
5588
+ "properties": {
5589
+ "email": {
5590
+ "nullable": true,
5591
+ "type": "string"
5592
+ },
5593
+ "id": {
5594
+ "format": "uuid",
5595
+ "nullable": true,
5596
+ "type": "string"
5597
+ },
5598
+ "name": {
5599
+ "nullable": true,
5600
+ "type": "string"
5601
+ }
5602
+ },
5603
+ "required": [
5604
+ "id",
5605
+ "name",
5606
+ "email"
5607
+ ],
5608
+ "type": "object"
5609
+ },
5610
+ "retry_budget": {
5611
+ "type": "integer"
5612
+ },
5613
+ "revision": {
5614
+ "nullable": true,
5615
+ "properties": {
5616
+ "checksum": {
5617
+ "description": "SHA-256 of the frozen steps",
5618
+ "type": "string"
5619
+ },
5620
+ "id": {
5621
+ "format": "uuid",
5622
+ "type": "string"
5623
+ },
5624
+ "inserted_at": {
5625
+ "format": "date-time",
5626
+ "type": "string"
5627
+ },
5628
+ "number": {
5629
+ "type": "integer"
5630
+ }
5631
+ },
5632
+ "required": [
5633
+ "id",
5634
+ "number",
5635
+ "checksum",
5636
+ "inserted_at"
5637
+ ],
5638
+ "type": "object"
5639
+ },
5640
+ "root": {
5641
+ "nullable": true,
5642
+ "properties": {
5643
+ "id": {
5644
+ "type": "string"
5645
+ },
5646
+ "identifier": {
5647
+ "type": "string"
5648
+ },
5649
+ "title": {
5650
+ "type": "string"
5651
+ }
5652
+ },
5653
+ "type": "object"
5654
+ },
5655
+ "spend_budget_cents": {
5656
+ "nullable": true,
5657
+ "type": "integer"
5658
+ },
5659
+ "status": {
5660
+ "enum": [
5661
+ "held",
5662
+ "released",
5663
+ "running",
5664
+ "completed",
5665
+ "needs_attention"
5666
+ ],
5667
+ "type": "string"
5668
+ },
5669
+ "steps": {
5670
+ "items": {
5671
+ "properties": {
5672
+ "archived": {
5673
+ "type": "boolean"
5674
+ },
5675
+ "conditions": {
5676
+ "items": {
5677
+ "additionalProperties": false,
5678
+ "properties": {
5679
+ "id": {
5680
+ "format": "uuid",
5681
+ "type": "string"
5682
+ },
5683
+ "inserted_at": {
5684
+ "format": "date-time",
5685
+ "type": "string"
5686
+ },
5687
+ "issue_id": {
5688
+ "format": "uuid",
5689
+ "type": "string"
5690
+ },
5691
+ "kind": {
5692
+ "enum": [
5693
+ "not_before",
5694
+ "gate",
5695
+ "event"
5696
+ ],
5697
+ "type": "string"
5698
+ },
5699
+ "label": {
5700
+ "description": "A gate's label; null for other kinds",
5701
+ "nullable": true,
5702
+ "type": "string"
5703
+ },
5704
+ "not_before": {
5705
+ "description": "A `not_before` condition's instant; null for other kinds",
5706
+ "format": "date-time",
5707
+ "nullable": true,
5708
+ "type": "string"
5709
+ },
5710
+ "satisfied": {
5711
+ "type": "boolean"
5712
+ },
5713
+ "satisfied_at": {
5714
+ "format": "date-time",
5715
+ "nullable": true,
5716
+ "type": "string"
5717
+ },
5718
+ "satisfied_by": {
5719
+ "description": "Who ticked a gate; null otherwise",
5720
+ "nullable": true,
5721
+ "properties": {
5722
+ "email": {
5723
+ "nullable": true,
5724
+ "type": "string"
5725
+ },
5726
+ "id": {
5727
+ "format": "uuid",
5728
+ "nullable": true,
5729
+ "type": "string"
5730
+ },
5731
+ "name": {
5732
+ "nullable": true,
5733
+ "type": "string"
5734
+ }
5735
+ },
5736
+ "required": [
5737
+ "id",
5738
+ "name",
5739
+ "email"
5740
+ ],
5741
+ "type": "object"
5742
+ },
5743
+ "updated_at": {
5744
+ "format": "date-time",
5745
+ "type": "string"
5746
+ }
5747
+ },
5748
+ "required": [
5749
+ "id",
5750
+ "issue_id",
5751
+ "kind",
5752
+ "label",
5753
+ "not_before",
5754
+ "satisfied",
5755
+ "satisfied_at",
5756
+ "satisfied_by",
5757
+ "inserted_at",
5758
+ "updated_at"
5759
+ ],
5760
+ "type": "object"
5761
+ },
5762
+ "type": "array"
5763
+ },
5764
+ "container": {
5765
+ "description": "Has sub-steps; completes when they all complete",
5766
+ "type": "boolean"
5767
+ },
5768
+ "executor": {
5769
+ "enum": [
5770
+ "none",
5771
+ "operator"
5772
+ ],
5773
+ "type": "string"
5774
+ },
5775
+ "held": {
5776
+ "type": "boolean"
5777
+ },
5778
+ "identifier": {
5779
+ "type": "string"
5780
+ },
5781
+ "in_revision": {
5782
+ "type": "boolean"
5783
+ },
5784
+ "issue_id": {
5785
+ "format": "uuid",
5786
+ "type": "string"
5787
+ },
5788
+ "key": {
5789
+ "nullable": true,
5790
+ "type": "string"
5791
+ },
5792
+ "parent": {
5793
+ "description": "The containing step's identifier; null for the root",
5794
+ "nullable": true,
5795
+ "type": "string"
5796
+ },
5797
+ "ready": {
5798
+ "type": "boolean"
5799
+ },
5800
+ "state": {
5801
+ "properties": {
5802
+ "id": {
5803
+ "type": "string"
5804
+ },
5805
+ "name": {
5806
+ "type": "string"
5807
+ },
5808
+ "type": {
5809
+ "type": "string"
5810
+ }
5811
+ },
5812
+ "type": "object"
5813
+ },
5814
+ "team": {
5815
+ "properties": {
5816
+ "id": {
5817
+ "type": "string"
5818
+ },
5819
+ "key": {
5820
+ "type": "string"
5821
+ },
5822
+ "name": {
5823
+ "type": "string"
5824
+ }
5825
+ },
5826
+ "type": "object"
5827
+ },
5828
+ "title": {
5829
+ "type": "string"
5830
+ }
5831
+ },
5832
+ "required": [
5833
+ "issue_id",
5834
+ "identifier",
5835
+ "key",
5836
+ "title",
5837
+ "parent",
5838
+ "executor",
5839
+ "container",
5840
+ "state",
5841
+ "ready",
5842
+ "held",
5843
+ "conditions"
5844
+ ],
5845
+ "type": "object"
5846
+ },
5847
+ "type": "array"
5848
+ },
5849
+ "updated_at": {
5850
+ "format": "date-time",
5851
+ "type": "string"
5852
+ }
5853
+ },
5854
+ "required": [
5855
+ "id",
5856
+ "status",
5857
+ "root",
5858
+ "retry_budget",
5859
+ "spend_budget_cents",
5860
+ "revision",
5861
+ "held_steps",
5862
+ "steps",
5863
+ "edges"
5864
+ ],
5865
+ "type": "object"
5866
+ }
5867
+ },
5868
+ "required": [
5869
+ "data"
5870
+ ],
5871
+ "type": "object"
5872
+ }
5873
+ }
5874
+ },
5875
+ "description": "Plan created"
5876
+ },
5877
+ "400": {
5878
+ "description": "Bad request"
5879
+ },
5880
+ "401": {
5881
+ "description": "Missing or invalid token"
5882
+ },
5883
+ "403": {
5884
+ "description": "Token not permitted (org-scoped, non-admin, or missing scope)"
5885
+ },
5886
+ "404": {
5887
+ "description": "Not found"
5888
+ },
5889
+ "409": {
5890
+ "description": "Idempotency key reused for a different request"
5891
+ },
5892
+ "422": {
5893
+ "content": {
5894
+ "application/json": {
5895
+ "schema": {
5896
+ "properties": {
5897
+ "error": {
5898
+ "enum": [
5899
+ "invalid_plan"
5900
+ ],
5901
+ "type": "string"
5902
+ },
5903
+ "message": {
5904
+ "type": "string"
5905
+ },
5906
+ "request_id": {
5907
+ "nullable": true,
5908
+ "type": "string"
5909
+ },
5910
+ "violations": {
5911
+ "items": {
5912
+ "properties": {
5913
+ "code": {
5914
+ "description": "Machine-readable reason, e.g. dependency_cycle",
5915
+ "type": "string"
5916
+ },
5917
+ "field": {
5918
+ "nullable": true,
5919
+ "type": "string"
5920
+ },
5921
+ "index": {
5922
+ "description": "The step's position in `steps`",
5923
+ "nullable": true,
5924
+ "type": "integer"
5925
+ },
5926
+ "issue": {
5927
+ "description": "The step's identifier, once it exists",
5928
+ "nullable": true,
5929
+ "type": "string"
5930
+ },
5931
+ "key": {
5932
+ "description": "The step's key; null for the root or plan",
5933
+ "nullable": true,
5934
+ "type": "string"
5935
+ },
5936
+ "message": {
5937
+ "type": "string"
5938
+ }
5939
+ },
5940
+ "required": [
5941
+ "key",
5942
+ "index",
5943
+ "issue",
5944
+ "code",
5945
+ "field",
5946
+ "message"
5947
+ ],
5948
+ "type": "object"
5949
+ },
5950
+ "type": "array"
5951
+ }
5952
+ },
5953
+ "required": [
5954
+ "error",
5955
+ "message",
5956
+ "violations"
5957
+ ],
5958
+ "type": "object"
5959
+ }
5960
+ }
5961
+ },
5962
+ "description": "The plan is not valid; nothing was written"
5963
+ }
5964
+ },
5965
+ "summary": "Create a plan",
5966
+ "tags": []
5967
+ }
5968
+ },
5969
+ "/api/v1/plans/{id}": {
5970
+ "get": {
5971
+ "callbacks": {},
5972
+ "deprecated": false,
5973
+ "description": "Requires the `harness:read` scope. The plan's status, budgets and current revision, and its whole tree in tree order, root first: each member's step `key`, `executor`, parent, state, readiness, wait conditions, and whether an edit since the release holds it (`held`) or it was added after the release (`in_revision` false). `edges` are the `blocks` edges between members (`from` blocks `to`). `estimate` is the spend ceiling for the Operator steps under the current profile, or null.",
5974
+ "parameters": [
5975
+ {
5976
+ "description": "Plan id",
5977
+ "in": "path",
5978
+ "name": "id",
5979
+ "required": true,
5980
+ "schema": {
5981
+ "format": "uuid",
5982
+ "type": "string"
5983
+ }
5984
+ }
5985
+ ],
5986
+ "responses": {
5987
+ "200": {
5988
+ "content": {
5989
+ "application/json": {
5990
+ "schema": {
5991
+ "properties": {
5992
+ "data": {
5993
+ "properties": {
5994
+ "created_by": {
5995
+ "nullable": true,
5996
+ "properties": {
5997
+ "email": {
5998
+ "nullable": true,
5999
+ "type": "string"
6000
+ },
6001
+ "id": {
6002
+ "format": "uuid",
6003
+ "nullable": true,
6004
+ "type": "string"
6005
+ },
6006
+ "name": {
6007
+ "nullable": true,
6008
+ "type": "string"
6009
+ }
6010
+ },
6011
+ "required": [
6012
+ "id",
6013
+ "name",
6014
+ "email"
6015
+ ],
6016
+ "type": "object"
6017
+ },
6018
+ "edges": {
6019
+ "items": {
6020
+ "properties": {
6021
+ "from": {
6022
+ "type": "string"
6023
+ },
6024
+ "to": {
6025
+ "type": "string"
6026
+ }
6027
+ },
6028
+ "required": [
6029
+ "from",
6030
+ "to"
6031
+ ],
6032
+ "type": "object"
6033
+ },
6034
+ "type": "array"
6035
+ },
6036
+ "estimate": {
6037
+ "nullable": true,
6038
+ "properties": {
6039
+ "ceiling_cents": {
6040
+ "type": "integer"
6041
+ },
6042
+ "minimum_budget_cents": {
6043
+ "type": "integer"
6044
+ },
6045
+ "per_attempt_reservation_cents": {
6046
+ "type": "integer"
6047
+ },
6048
+ "step_cap_cents": {
6049
+ "type": "integer"
6050
+ }
6051
+ },
6052
+ "type": "object"
6053
+ },
6054
+ "held_steps": {
6055
+ "description": "Steps an edit holds",
6056
+ "items": {
6057
+ "type": "string"
6058
+ },
6059
+ "type": "array"
6060
+ },
6061
+ "id": {
6062
+ "format": "uuid",
6063
+ "type": "string"
6064
+ },
6065
+ "inserted_at": {
6066
+ "format": "date-time",
6067
+ "type": "string"
6068
+ },
6069
+ "released_at": {
6070
+ "format": "date-time",
6071
+ "nullable": true,
6072
+ "type": "string"
6073
+ },
6074
+ "released_by": {
6075
+ "nullable": true,
6076
+ "properties": {
6077
+ "email": {
6078
+ "nullable": true,
6079
+ "type": "string"
6080
+ },
6081
+ "id": {
6082
+ "format": "uuid",
6083
+ "nullable": true,
6084
+ "type": "string"
6085
+ },
6086
+ "name": {
6087
+ "nullable": true,
6088
+ "type": "string"
6089
+ }
6090
+ },
6091
+ "required": [
6092
+ "id",
6093
+ "name",
6094
+ "email"
6095
+ ],
6096
+ "type": "object"
6097
+ },
6098
+ "retry_budget": {
6099
+ "type": "integer"
6100
+ },
6101
+ "revision": {
6102
+ "nullable": true,
6103
+ "properties": {
6104
+ "checksum": {
6105
+ "description": "SHA-256 of the frozen steps",
6106
+ "type": "string"
6107
+ },
6108
+ "id": {
6109
+ "format": "uuid",
6110
+ "type": "string"
6111
+ },
6112
+ "inserted_at": {
6113
+ "format": "date-time",
6114
+ "type": "string"
6115
+ },
6116
+ "number": {
6117
+ "type": "integer"
6118
+ }
6119
+ },
6120
+ "required": [
6121
+ "id",
6122
+ "number",
6123
+ "checksum",
6124
+ "inserted_at"
6125
+ ],
6126
+ "type": "object"
6127
+ },
6128
+ "root": {
6129
+ "nullable": true,
6130
+ "properties": {
6131
+ "id": {
6132
+ "type": "string"
6133
+ },
6134
+ "identifier": {
6135
+ "type": "string"
6136
+ },
6137
+ "title": {
6138
+ "type": "string"
6139
+ }
6140
+ },
6141
+ "type": "object"
6142
+ },
6143
+ "spend_budget_cents": {
6144
+ "nullable": true,
6145
+ "type": "integer"
6146
+ },
6147
+ "status": {
6148
+ "enum": [
6149
+ "held",
6150
+ "released",
6151
+ "running",
6152
+ "completed",
6153
+ "needs_attention"
6154
+ ],
6155
+ "type": "string"
6156
+ },
6157
+ "steps": {
6158
+ "items": {
6159
+ "properties": {
6160
+ "archived": {
6161
+ "type": "boolean"
6162
+ },
6163
+ "conditions": {
6164
+ "items": {
6165
+ "additionalProperties": false,
6166
+ "properties": {
6167
+ "id": {
6168
+ "format": "uuid",
6169
+ "type": "string"
6170
+ },
6171
+ "inserted_at": {
6172
+ "format": "date-time",
6173
+ "type": "string"
6174
+ },
6175
+ "issue_id": {
6176
+ "format": "uuid",
6177
+ "type": "string"
6178
+ },
6179
+ "kind": {
6180
+ "enum": [
6181
+ "not_before",
6182
+ "gate",
6183
+ "event"
6184
+ ],
6185
+ "type": "string"
6186
+ },
6187
+ "label": {
6188
+ "description": "A gate's label; null for other kinds",
6189
+ "nullable": true,
6190
+ "type": "string"
6191
+ },
6192
+ "not_before": {
6193
+ "description": "A `not_before` condition's instant; null for other kinds",
6194
+ "format": "date-time",
6195
+ "nullable": true,
6196
+ "type": "string"
6197
+ },
6198
+ "satisfied": {
6199
+ "type": "boolean"
6200
+ },
6201
+ "satisfied_at": {
6202
+ "format": "date-time",
6203
+ "nullable": true,
6204
+ "type": "string"
6205
+ },
6206
+ "satisfied_by": {
6207
+ "description": "Who ticked a gate; null otherwise",
6208
+ "nullable": true,
6209
+ "properties": {
6210
+ "email": {
6211
+ "nullable": true,
6212
+ "type": "string"
6213
+ },
6214
+ "id": {
6215
+ "format": "uuid",
6216
+ "nullable": true,
6217
+ "type": "string"
6218
+ },
6219
+ "name": {
6220
+ "nullable": true,
6221
+ "type": "string"
6222
+ }
6223
+ },
6224
+ "required": [
6225
+ "id",
6226
+ "name",
6227
+ "email"
6228
+ ],
6229
+ "type": "object"
6230
+ },
6231
+ "updated_at": {
6232
+ "format": "date-time",
6233
+ "type": "string"
6234
+ }
6235
+ },
6236
+ "required": [
6237
+ "id",
6238
+ "issue_id",
6239
+ "kind",
6240
+ "label",
6241
+ "not_before",
6242
+ "satisfied",
6243
+ "satisfied_at",
6244
+ "satisfied_by",
6245
+ "inserted_at",
6246
+ "updated_at"
6247
+ ],
6248
+ "type": "object"
6249
+ },
6250
+ "type": "array"
6251
+ },
6252
+ "container": {
6253
+ "description": "Has sub-steps; completes when they all complete",
6254
+ "type": "boolean"
6255
+ },
6256
+ "executor": {
6257
+ "enum": [
6258
+ "none",
6259
+ "operator"
6260
+ ],
6261
+ "type": "string"
6262
+ },
6263
+ "held": {
6264
+ "type": "boolean"
6265
+ },
6266
+ "identifier": {
6267
+ "type": "string"
6268
+ },
6269
+ "in_revision": {
6270
+ "type": "boolean"
6271
+ },
6272
+ "issue_id": {
6273
+ "format": "uuid",
6274
+ "type": "string"
6275
+ },
6276
+ "key": {
6277
+ "nullable": true,
6278
+ "type": "string"
6279
+ },
6280
+ "parent": {
6281
+ "description": "The containing step's identifier; null for the root",
6282
+ "nullable": true,
6283
+ "type": "string"
6284
+ },
6285
+ "ready": {
6286
+ "type": "boolean"
6287
+ },
6288
+ "state": {
6289
+ "properties": {
6290
+ "id": {
6291
+ "type": "string"
6292
+ },
6293
+ "name": {
6294
+ "type": "string"
6295
+ },
6296
+ "type": {
6297
+ "type": "string"
6298
+ }
6299
+ },
6300
+ "type": "object"
6301
+ },
6302
+ "team": {
6303
+ "properties": {
6304
+ "id": {
6305
+ "type": "string"
6306
+ },
6307
+ "key": {
6308
+ "type": "string"
6309
+ },
6310
+ "name": {
6311
+ "type": "string"
6312
+ }
6313
+ },
6314
+ "type": "object"
6315
+ },
6316
+ "title": {
6317
+ "type": "string"
6318
+ }
6319
+ },
6320
+ "required": [
6321
+ "issue_id",
6322
+ "identifier",
6323
+ "key",
6324
+ "title",
6325
+ "parent",
6326
+ "executor",
6327
+ "container",
6328
+ "state",
6329
+ "ready",
6330
+ "held",
6331
+ "conditions"
6332
+ ],
6333
+ "type": "object"
6334
+ },
6335
+ "type": "array"
6336
+ },
6337
+ "updated_at": {
6338
+ "format": "date-time",
6339
+ "type": "string"
6340
+ }
6341
+ },
6342
+ "required": [
6343
+ "id",
6344
+ "status",
6345
+ "root",
6346
+ "retry_budget",
6347
+ "spend_budget_cents",
6348
+ "revision",
6349
+ "held_steps",
6350
+ "steps",
6351
+ "edges"
6352
+ ],
6353
+ "type": "object"
6354
+ }
6355
+ },
6356
+ "required": [
6357
+ "data"
6358
+ ],
6359
+ "type": "object"
6360
+ }
6361
+ }
6362
+ },
6363
+ "description": "Success"
6364
+ },
6365
+ "400": {
6366
+ "description": "Bad request"
6367
+ },
6368
+ "401": {
6369
+ "description": "Missing or invalid token"
6370
+ },
6371
+ "403": {
6372
+ "description": "Token not permitted (org-scoped, non-admin, or missing scope)"
6373
+ },
6374
+ "404": {
6375
+ "description": "Not found"
6376
+ },
6377
+ "422": {
6378
+ "description": "Validation error"
6379
+ }
6380
+ },
6381
+ "summary": "Get a plan",
6382
+ "tags": []
6383
+ },
6384
+ "patch": {
6385
+ "callbacks": {},
6386
+ "deprecated": false,
6387
+ "description": "Requires the `harness:write` scope. Changes step attributes (`executor`, `key`) of the steps named, by `step` key or `issue` identifier, and the budgets; only what is named changes. Editing a released step holds it until the plan is released again. A budget edit of a released plan answers 409 `plan_released`: hold it first. Descriptions, edges, conditions and parents are edited through the issue endpoints. Requires staff standing or being the plan's requester.",
6388
+ "parameters": [
6389
+ {
6390
+ "description": "Plan id",
6391
+ "in": "path",
6392
+ "name": "id",
6393
+ "required": true,
6394
+ "schema": {
6395
+ "format": "uuid",
6396
+ "type": "string"
6397
+ }
6398
+ }
6399
+ ],
6400
+ "requestBody": {
6401
+ "content": {
6402
+ "application/json": {
6403
+ "schema": {
6404
+ "additionalProperties": false,
6405
+ "properties": {
6406
+ "actor": {
6407
+ "description": "Display name to attribute the write to (e.g. an agent). Defaults to the token name for API tokens and to the signed-in user for login tokens. Display-only, never an access-control input.",
6408
+ "type": "string"
6409
+ },
6410
+ "retry_budget": {
6411
+ "minimum": 0,
6412
+ "type": "integer"
6413
+ },
6414
+ "spend_budget_cents": {
6415
+ "minimum": 0,
6416
+ "nullable": true,
6417
+ "type": "integer"
6418
+ },
6419
+ "steps": {
6420
+ "items": {
6421
+ "additionalProperties": false,
6422
+ "properties": {
6423
+ "executor": {
6424
+ "enum": [
6425
+ "none",
6426
+ "operator"
6427
+ ],
6428
+ "type": "string"
6429
+ },
6430
+ "issue": {
6431
+ "description": "The step's issue identifier; give this or `step`",
6432
+ "type": "string"
6433
+ },
6434
+ "key": {
6435
+ "description": "The step's new key",
6436
+ "maxLength": 100,
6437
+ "nullable": true,
6438
+ "type": "string"
6439
+ },
6440
+ "step": {
6441
+ "description": "The step's key; give this or `issue`",
6442
+ "type": "string"
6443
+ }
6444
+ },
6445
+ "type": "object"
6446
+ },
6447
+ "type": "array"
6448
+ }
6449
+ },
6450
+ "type": "object"
6451
+ }
6452
+ }
6453
+ },
6454
+ "required": true
6455
+ },
6456
+ "responses": {
6457
+ "200": {
6458
+ "content": {
6459
+ "application/json": {
6460
+ "schema": {
6461
+ "properties": {
6462
+ "data": {
6463
+ "properties": {
6464
+ "created_by": {
6465
+ "nullable": true,
6466
+ "properties": {
6467
+ "email": {
6468
+ "nullable": true,
6469
+ "type": "string"
6470
+ },
6471
+ "id": {
6472
+ "format": "uuid",
6473
+ "nullable": true,
6474
+ "type": "string"
6475
+ },
6476
+ "name": {
6477
+ "nullable": true,
6478
+ "type": "string"
6479
+ }
6480
+ },
6481
+ "required": [
6482
+ "id",
6483
+ "name",
6484
+ "email"
6485
+ ],
6486
+ "type": "object"
6487
+ },
6488
+ "edges": {
6489
+ "items": {
6490
+ "properties": {
6491
+ "from": {
6492
+ "type": "string"
6493
+ },
6494
+ "to": {
6495
+ "type": "string"
6496
+ }
6497
+ },
6498
+ "required": [
6499
+ "from",
6500
+ "to"
6501
+ ],
6502
+ "type": "object"
6503
+ },
6504
+ "type": "array"
6505
+ },
6506
+ "estimate": {
6507
+ "nullable": true,
6508
+ "properties": {
6509
+ "ceiling_cents": {
6510
+ "type": "integer"
6511
+ },
6512
+ "minimum_budget_cents": {
6513
+ "type": "integer"
6514
+ },
6515
+ "per_attempt_reservation_cents": {
6516
+ "type": "integer"
6517
+ },
6518
+ "step_cap_cents": {
6519
+ "type": "integer"
6520
+ }
6521
+ },
6522
+ "type": "object"
6523
+ },
6524
+ "held_steps": {
6525
+ "description": "Steps an edit holds",
6526
+ "items": {
6527
+ "type": "string"
6528
+ },
6529
+ "type": "array"
6530
+ },
6531
+ "id": {
6532
+ "format": "uuid",
6533
+ "type": "string"
6534
+ },
6535
+ "inserted_at": {
6536
+ "format": "date-time",
6537
+ "type": "string"
6538
+ },
6539
+ "released_at": {
6540
+ "format": "date-time",
6541
+ "nullable": true,
6542
+ "type": "string"
6543
+ },
6544
+ "released_by": {
6545
+ "nullable": true,
6546
+ "properties": {
6547
+ "email": {
6548
+ "nullable": true,
6549
+ "type": "string"
6550
+ },
6551
+ "id": {
6552
+ "format": "uuid",
6553
+ "nullable": true,
6554
+ "type": "string"
6555
+ },
6556
+ "name": {
6557
+ "nullable": true,
6558
+ "type": "string"
6559
+ }
6560
+ },
6561
+ "required": [
6562
+ "id",
6563
+ "name",
6564
+ "email"
6565
+ ],
6566
+ "type": "object"
6567
+ },
6568
+ "retry_budget": {
6569
+ "type": "integer"
6570
+ },
6571
+ "revision": {
6572
+ "nullable": true,
6573
+ "properties": {
6574
+ "checksum": {
6575
+ "description": "SHA-256 of the frozen steps",
6576
+ "type": "string"
6577
+ },
6578
+ "id": {
6579
+ "format": "uuid",
6580
+ "type": "string"
6581
+ },
6582
+ "inserted_at": {
6583
+ "format": "date-time",
6584
+ "type": "string"
6585
+ },
6586
+ "number": {
6587
+ "type": "integer"
6588
+ }
6589
+ },
6590
+ "required": [
6591
+ "id",
6592
+ "number",
6593
+ "checksum",
6594
+ "inserted_at"
6595
+ ],
6596
+ "type": "object"
6597
+ },
6598
+ "root": {
6599
+ "nullable": true,
6600
+ "properties": {
6601
+ "id": {
6602
+ "type": "string"
6603
+ },
6604
+ "identifier": {
6605
+ "type": "string"
6606
+ },
6607
+ "title": {
6608
+ "type": "string"
6609
+ }
6610
+ },
6611
+ "type": "object"
6612
+ },
6613
+ "spend_budget_cents": {
6614
+ "nullable": true,
6615
+ "type": "integer"
6616
+ },
6617
+ "status": {
6618
+ "enum": [
6619
+ "held",
6620
+ "released",
6621
+ "running",
6622
+ "completed",
6623
+ "needs_attention"
6624
+ ],
6625
+ "type": "string"
6626
+ },
6627
+ "steps": {
6628
+ "items": {
6629
+ "properties": {
6630
+ "archived": {
6631
+ "type": "boolean"
6632
+ },
6633
+ "conditions": {
6634
+ "items": {
6635
+ "additionalProperties": false,
6636
+ "properties": {
6637
+ "id": {
6638
+ "format": "uuid",
6639
+ "type": "string"
6640
+ },
6641
+ "inserted_at": {
6642
+ "format": "date-time",
6643
+ "type": "string"
6644
+ },
6645
+ "issue_id": {
6646
+ "format": "uuid",
6647
+ "type": "string"
6648
+ },
6649
+ "kind": {
6650
+ "enum": [
6651
+ "not_before",
6652
+ "gate",
6653
+ "event"
6654
+ ],
6655
+ "type": "string"
6656
+ },
6657
+ "label": {
6658
+ "description": "A gate's label; null for other kinds",
6659
+ "nullable": true,
6660
+ "type": "string"
6661
+ },
6662
+ "not_before": {
6663
+ "description": "A `not_before` condition's instant; null for other kinds",
6664
+ "format": "date-time",
6665
+ "nullable": true,
6666
+ "type": "string"
6667
+ },
6668
+ "satisfied": {
6669
+ "type": "boolean"
6670
+ },
6671
+ "satisfied_at": {
6672
+ "format": "date-time",
6673
+ "nullable": true,
6674
+ "type": "string"
6675
+ },
6676
+ "satisfied_by": {
6677
+ "description": "Who ticked a gate; null otherwise",
6678
+ "nullable": true,
6679
+ "properties": {
6680
+ "email": {
6681
+ "nullable": true,
6682
+ "type": "string"
6683
+ },
6684
+ "id": {
6685
+ "format": "uuid",
6686
+ "nullable": true,
6687
+ "type": "string"
6688
+ },
6689
+ "name": {
6690
+ "nullable": true,
6691
+ "type": "string"
6692
+ }
6693
+ },
6694
+ "required": [
6695
+ "id",
6696
+ "name",
6697
+ "email"
6698
+ ],
6699
+ "type": "object"
6700
+ },
6701
+ "updated_at": {
6702
+ "format": "date-time",
6703
+ "type": "string"
6704
+ }
6705
+ },
6706
+ "required": [
6707
+ "id",
6708
+ "issue_id",
6709
+ "kind",
6710
+ "label",
6711
+ "not_before",
6712
+ "satisfied",
6713
+ "satisfied_at",
6714
+ "satisfied_by",
6715
+ "inserted_at",
6716
+ "updated_at"
6717
+ ],
6718
+ "type": "object"
6719
+ },
6720
+ "type": "array"
6721
+ },
6722
+ "container": {
6723
+ "description": "Has sub-steps; completes when they all complete",
6724
+ "type": "boolean"
6725
+ },
6726
+ "executor": {
6727
+ "enum": [
6728
+ "none",
6729
+ "operator"
6730
+ ],
6731
+ "type": "string"
6732
+ },
6733
+ "held": {
6734
+ "type": "boolean"
6735
+ },
6736
+ "identifier": {
6737
+ "type": "string"
6738
+ },
6739
+ "in_revision": {
6740
+ "type": "boolean"
6741
+ },
6742
+ "issue_id": {
6743
+ "format": "uuid",
6744
+ "type": "string"
6745
+ },
6746
+ "key": {
6747
+ "nullable": true,
6748
+ "type": "string"
6749
+ },
6750
+ "parent": {
6751
+ "description": "The containing step's identifier; null for the root",
6752
+ "nullable": true,
6753
+ "type": "string"
6754
+ },
6755
+ "ready": {
6756
+ "type": "boolean"
6757
+ },
6758
+ "state": {
6759
+ "properties": {
6760
+ "id": {
6761
+ "type": "string"
6762
+ },
6763
+ "name": {
6764
+ "type": "string"
6765
+ },
6766
+ "type": {
6767
+ "type": "string"
6768
+ }
6769
+ },
6770
+ "type": "object"
6771
+ },
6772
+ "team": {
6773
+ "properties": {
6774
+ "id": {
6775
+ "type": "string"
6776
+ },
6777
+ "key": {
6778
+ "type": "string"
6779
+ },
6780
+ "name": {
6781
+ "type": "string"
6782
+ }
6783
+ },
6784
+ "type": "object"
6785
+ },
6786
+ "title": {
6787
+ "type": "string"
6788
+ }
6789
+ },
6790
+ "required": [
6791
+ "issue_id",
6792
+ "identifier",
6793
+ "key",
6794
+ "title",
6795
+ "parent",
6796
+ "executor",
6797
+ "container",
6798
+ "state",
6799
+ "ready",
6800
+ "held",
6801
+ "conditions"
6802
+ ],
6803
+ "type": "object"
6804
+ },
6805
+ "type": "array"
6806
+ },
6807
+ "updated_at": {
6808
+ "format": "date-time",
6809
+ "type": "string"
6810
+ }
6811
+ },
6812
+ "required": [
6813
+ "id",
6814
+ "status",
6815
+ "root",
6816
+ "retry_budget",
6817
+ "spend_budget_cents",
6818
+ "revision",
6819
+ "held_steps",
6820
+ "steps",
6821
+ "edges"
6822
+ ],
6823
+ "type": "object"
6824
+ }
6825
+ },
6826
+ "required": [
6827
+ "data"
6828
+ ],
6829
+ "type": "object"
6830
+ }
6831
+ }
6832
+ },
6833
+ "description": "Success"
6834
+ },
6835
+ "400": {
6836
+ "description": "Bad request"
6837
+ },
6838
+ "401": {
6839
+ "description": "Missing or invalid token"
6840
+ },
6841
+ "403": {
6842
+ "description": "Token not permitted (org-scoped, non-admin, or missing scope)"
6843
+ },
6844
+ "404": {
6845
+ "description": "Not found"
6846
+ },
6847
+ "409": {
6848
+ "description": "The plan is completed or released, or a step's Operator job may run"
6849
+ },
6850
+ "422": {
6851
+ "content": {
6852
+ "application/json": {
6853
+ "schema": {
6854
+ "properties": {
6855
+ "error": {
6856
+ "enum": [
6857
+ "invalid_plan"
6858
+ ],
6859
+ "type": "string"
6860
+ },
6861
+ "message": {
6862
+ "type": "string"
6863
+ },
6864
+ "request_id": {
6865
+ "nullable": true,
6866
+ "type": "string"
6867
+ },
6868
+ "violations": {
6869
+ "items": {
6870
+ "properties": {
6871
+ "code": {
6872
+ "description": "Machine-readable reason, e.g. dependency_cycle",
6873
+ "type": "string"
6874
+ },
6875
+ "field": {
6876
+ "nullable": true,
6877
+ "type": "string"
6878
+ },
6879
+ "index": {
6880
+ "description": "The step's position in `steps`",
6881
+ "nullable": true,
6882
+ "type": "integer"
6883
+ },
6884
+ "issue": {
6885
+ "description": "The step's identifier, once it exists",
6886
+ "nullable": true,
6887
+ "type": "string"
6888
+ },
6889
+ "key": {
6890
+ "description": "The step's key; null for the root or plan",
6891
+ "nullable": true,
6892
+ "type": "string"
6893
+ },
6894
+ "message": {
6895
+ "type": "string"
6896
+ }
6897
+ },
6898
+ "required": [
6899
+ "key",
6900
+ "index",
6901
+ "issue",
6902
+ "code",
6903
+ "field",
6904
+ "message"
6905
+ ],
6906
+ "type": "object"
6907
+ },
6908
+ "type": "array"
6909
+ }
6910
+ },
6911
+ "required": [
6912
+ "error",
6913
+ "message",
6914
+ "violations"
6915
+ ],
6916
+ "type": "object"
6917
+ }
6918
+ }
6919
+ },
6920
+ "description": "The plan is not valid; nothing was written"
6921
+ }
6922
+ },
6923
+ "summary": "Edit a plan",
6924
+ "tags": []
6925
+ }
6926
+ },
6927
+ "/api/v1/plans/{id}/release": {
6928
+ "post": {
6929
+ "callbacks": {},
6930
+ "deprecated": false,
6931
+ "description": "Requires the `harness:write` scope. Releases a held plan, or one that needs attention, as the credential's user: freezes its next revision and lets its ready steps run. A plan with Operator steps runs them in its plan room, created or reused with the releaser and `collaborators` as its people, under a delegated grant that needs a spend budget and the releaser's right to run Operator. Requires staff standing or being the plan's requester.",
6932
+ "parameters": [
6933
+ {
6934
+ "description": "Plan id",
6935
+ "in": "path",
6936
+ "name": "id",
6937
+ "required": true,
6938
+ "schema": {
6939
+ "format": "uuid",
6940
+ "type": "string"
6941
+ }
6942
+ }
6943
+ ],
6944
+ "requestBody": {
6945
+ "content": {
6946
+ "application/json": {
6947
+ "schema": {
6948
+ "additionalProperties": false,
6949
+ "properties": {
6950
+ "actor": {
6951
+ "description": "Display name to attribute the write to (e.g. an agent). Defaults to the token name for API tokens and to the signed-in user for login tokens. Display-only, never an access-control input.",
6952
+ "type": "string"
6953
+ },
6954
+ "collaborators": {
6955
+ "description": "People of this organization (user ids or emails) to add to the plan room besides the releaser; a plan without Operator steps has no room",
6956
+ "items": {
6957
+ "type": "string"
6958
+ },
6959
+ "maxItems": 20,
6960
+ "type": "array"
6961
+ },
6962
+ "retry_budget": {
6963
+ "minimum": 0,
6964
+ "type": "integer"
6965
+ },
6966
+ "spend_budget_cents": {
6967
+ "minimum": 0,
6968
+ "nullable": true,
6969
+ "type": "integer"
6970
+ }
6971
+ },
6972
+ "type": "object"
6973
+ }
6974
+ }
6975
+ },
6976
+ "required": true
6977
+ },
6978
+ "responses": {
6979
+ "200": {
6980
+ "content": {
6981
+ "application/json": {
6982
+ "schema": {
6983
+ "properties": {
6984
+ "data": {
6985
+ "properties": {
6986
+ "created_by": {
6987
+ "nullable": true,
6988
+ "properties": {
6989
+ "email": {
6990
+ "nullable": true,
6991
+ "type": "string"
6992
+ },
6993
+ "id": {
6994
+ "format": "uuid",
6995
+ "nullable": true,
6996
+ "type": "string"
6997
+ },
6998
+ "name": {
6999
+ "nullable": true,
7000
+ "type": "string"
7001
+ }
7002
+ },
7003
+ "required": [
7004
+ "id",
7005
+ "name",
7006
+ "email"
7007
+ ],
7008
+ "type": "object"
7009
+ },
7010
+ "edges": {
7011
+ "items": {
7012
+ "properties": {
7013
+ "from": {
7014
+ "type": "string"
7015
+ },
7016
+ "to": {
7017
+ "type": "string"
7018
+ }
7019
+ },
7020
+ "required": [
7021
+ "from",
7022
+ "to"
7023
+ ],
7024
+ "type": "object"
7025
+ },
7026
+ "type": "array"
7027
+ },
7028
+ "estimate": {
7029
+ "nullable": true,
7030
+ "properties": {
7031
+ "ceiling_cents": {
7032
+ "type": "integer"
7033
+ },
7034
+ "minimum_budget_cents": {
7035
+ "type": "integer"
7036
+ },
7037
+ "per_attempt_reservation_cents": {
7038
+ "type": "integer"
7039
+ },
7040
+ "step_cap_cents": {
7041
+ "type": "integer"
7042
+ }
7043
+ },
7044
+ "type": "object"
7045
+ },
7046
+ "held_steps": {
7047
+ "description": "Steps an edit holds",
7048
+ "items": {
7049
+ "type": "string"
7050
+ },
7051
+ "type": "array"
7052
+ },
7053
+ "id": {
7054
+ "format": "uuid",
7055
+ "type": "string"
7056
+ },
7057
+ "inserted_at": {
7058
+ "format": "date-time",
7059
+ "type": "string"
7060
+ },
7061
+ "released_at": {
7062
+ "format": "date-time",
7063
+ "nullable": true,
7064
+ "type": "string"
7065
+ },
7066
+ "released_by": {
7067
+ "nullable": true,
7068
+ "properties": {
7069
+ "email": {
7070
+ "nullable": true,
7071
+ "type": "string"
7072
+ },
7073
+ "id": {
7074
+ "format": "uuid",
7075
+ "nullable": true,
7076
+ "type": "string"
7077
+ },
7078
+ "name": {
7079
+ "nullable": true,
7080
+ "type": "string"
7081
+ }
7082
+ },
7083
+ "required": [
7084
+ "id",
7085
+ "name",
7086
+ "email"
7087
+ ],
7088
+ "type": "object"
7089
+ },
7090
+ "retry_budget": {
7091
+ "type": "integer"
7092
+ },
7093
+ "revision": {
7094
+ "nullable": true,
7095
+ "properties": {
7096
+ "checksum": {
7097
+ "description": "SHA-256 of the frozen steps",
7098
+ "type": "string"
7099
+ },
7100
+ "id": {
7101
+ "format": "uuid",
7102
+ "type": "string"
7103
+ },
7104
+ "inserted_at": {
7105
+ "format": "date-time",
7106
+ "type": "string"
7107
+ },
7108
+ "number": {
7109
+ "type": "integer"
7110
+ }
7111
+ },
7112
+ "required": [
7113
+ "id",
7114
+ "number",
7115
+ "checksum",
7116
+ "inserted_at"
7117
+ ],
7118
+ "type": "object"
7119
+ },
7120
+ "root": {
7121
+ "nullable": true,
7122
+ "properties": {
7123
+ "id": {
7124
+ "type": "string"
7125
+ },
7126
+ "identifier": {
7127
+ "type": "string"
7128
+ },
7129
+ "title": {
7130
+ "type": "string"
7131
+ }
7132
+ },
7133
+ "type": "object"
7134
+ },
7135
+ "spend_budget_cents": {
7136
+ "nullable": true,
7137
+ "type": "integer"
7138
+ },
7139
+ "status": {
7140
+ "enum": [
7141
+ "held",
7142
+ "released",
7143
+ "running",
7144
+ "completed",
7145
+ "needs_attention"
7146
+ ],
7147
+ "type": "string"
7148
+ },
7149
+ "steps": {
7150
+ "items": {
7151
+ "properties": {
7152
+ "archived": {
7153
+ "type": "boolean"
7154
+ },
7155
+ "conditions": {
7156
+ "items": {
7157
+ "additionalProperties": false,
7158
+ "properties": {
7159
+ "id": {
7160
+ "format": "uuid",
7161
+ "type": "string"
7162
+ },
7163
+ "inserted_at": {
7164
+ "format": "date-time",
7165
+ "type": "string"
7166
+ },
7167
+ "issue_id": {
7168
+ "format": "uuid",
7169
+ "type": "string"
7170
+ },
7171
+ "kind": {
7172
+ "enum": [
7173
+ "not_before",
7174
+ "gate",
7175
+ "event"
7176
+ ],
7177
+ "type": "string"
7178
+ },
7179
+ "label": {
7180
+ "description": "A gate's label; null for other kinds",
7181
+ "nullable": true,
7182
+ "type": "string"
7183
+ },
7184
+ "not_before": {
7185
+ "description": "A `not_before` condition's instant; null for other kinds",
7186
+ "format": "date-time",
7187
+ "nullable": true,
7188
+ "type": "string"
7189
+ },
7190
+ "satisfied": {
7191
+ "type": "boolean"
7192
+ },
7193
+ "satisfied_at": {
7194
+ "format": "date-time",
7195
+ "nullable": true,
7196
+ "type": "string"
7197
+ },
7198
+ "satisfied_by": {
7199
+ "description": "Who ticked a gate; null otherwise",
7200
+ "nullable": true,
7201
+ "properties": {
7202
+ "email": {
7203
+ "nullable": true,
7204
+ "type": "string"
7205
+ },
7206
+ "id": {
7207
+ "format": "uuid",
7208
+ "nullable": true,
7209
+ "type": "string"
7210
+ },
7211
+ "name": {
7212
+ "nullable": true,
7213
+ "type": "string"
7214
+ }
7215
+ },
7216
+ "required": [
7217
+ "id",
7218
+ "name",
7219
+ "email"
7220
+ ],
7221
+ "type": "object"
7222
+ },
7223
+ "updated_at": {
7224
+ "format": "date-time",
7225
+ "type": "string"
7226
+ }
7227
+ },
7228
+ "required": [
7229
+ "id",
7230
+ "issue_id",
7231
+ "kind",
7232
+ "label",
7233
+ "not_before",
7234
+ "satisfied",
7235
+ "satisfied_at",
7236
+ "satisfied_by",
7237
+ "inserted_at",
7238
+ "updated_at"
7239
+ ],
7240
+ "type": "object"
7241
+ },
7242
+ "type": "array"
7243
+ },
7244
+ "container": {
7245
+ "description": "Has sub-steps; completes when they all complete",
7246
+ "type": "boolean"
7247
+ },
7248
+ "executor": {
7249
+ "enum": [
7250
+ "none",
7251
+ "operator"
7252
+ ],
7253
+ "type": "string"
7254
+ },
7255
+ "held": {
7256
+ "type": "boolean"
7257
+ },
7258
+ "identifier": {
7259
+ "type": "string"
7260
+ },
7261
+ "in_revision": {
7262
+ "type": "boolean"
7263
+ },
7264
+ "issue_id": {
7265
+ "format": "uuid",
7266
+ "type": "string"
7267
+ },
7268
+ "key": {
7269
+ "nullable": true,
7270
+ "type": "string"
7271
+ },
7272
+ "parent": {
7273
+ "description": "The containing step's identifier; null for the root",
7274
+ "nullable": true,
7275
+ "type": "string"
7276
+ },
7277
+ "ready": {
7278
+ "type": "boolean"
7279
+ },
7280
+ "state": {
7281
+ "properties": {
7282
+ "id": {
7283
+ "type": "string"
7284
+ },
7285
+ "name": {
7286
+ "type": "string"
7287
+ },
7288
+ "type": {
7289
+ "type": "string"
7290
+ }
7291
+ },
7292
+ "type": "object"
7293
+ },
7294
+ "team": {
7295
+ "properties": {
7296
+ "id": {
7297
+ "type": "string"
7298
+ },
7299
+ "key": {
7300
+ "type": "string"
7301
+ },
7302
+ "name": {
7303
+ "type": "string"
7304
+ }
7305
+ },
7306
+ "type": "object"
7307
+ },
7308
+ "title": {
7309
+ "type": "string"
7310
+ }
7311
+ },
7312
+ "required": [
7313
+ "issue_id",
7314
+ "identifier",
7315
+ "key",
7316
+ "title",
7317
+ "parent",
7318
+ "executor",
7319
+ "container",
7320
+ "state",
7321
+ "ready",
7322
+ "held",
7323
+ "conditions"
7324
+ ],
7325
+ "type": "object"
7326
+ },
7327
+ "type": "array"
7328
+ },
7329
+ "updated_at": {
7330
+ "format": "date-time",
7331
+ "type": "string"
7332
+ }
7333
+ },
7334
+ "required": [
7335
+ "id",
7336
+ "status",
7337
+ "root",
7338
+ "retry_budget",
7339
+ "spend_budget_cents",
7340
+ "revision",
7341
+ "held_steps",
7342
+ "steps",
7343
+ "edges"
7344
+ ],
7345
+ "type": "object"
7346
+ }
7347
+ },
7348
+ "required": [
7349
+ "data"
7350
+ ],
7351
+ "type": "object"
7352
+ }
7353
+ }
7354
+ },
7355
+ "description": "Success"
7356
+ },
7357
+ "400": {
7358
+ "description": "Bad request"
7359
+ },
7360
+ "401": {
7361
+ "description": "Missing or invalid token"
7362
+ },
7363
+ "403": {
7364
+ "description": "No right to release the plan, or to run Operator in its room"
7365
+ },
7366
+ "404": {
7367
+ "description": "Not found"
7368
+ },
7369
+ "409": {
7370
+ "description": "The plan is already released or completed"
7371
+ },
7372
+ "422": {
7373
+ "content": {
7374
+ "application/json": {
7375
+ "schema": {
7376
+ "properties": {
7377
+ "error": {
7378
+ "enum": [
7379
+ "invalid_plan"
7380
+ ],
7381
+ "type": "string"
7382
+ },
7383
+ "message": {
7384
+ "type": "string"
7385
+ },
7386
+ "request_id": {
7387
+ "nullable": true,
7388
+ "type": "string"
7389
+ },
7390
+ "violations": {
7391
+ "items": {
7392
+ "properties": {
7393
+ "code": {
7394
+ "description": "Machine-readable reason, e.g. dependency_cycle",
7395
+ "type": "string"
7396
+ },
7397
+ "field": {
7398
+ "nullable": true,
7399
+ "type": "string"
7400
+ },
7401
+ "index": {
7402
+ "description": "The step's position in `steps`",
7403
+ "nullable": true,
7404
+ "type": "integer"
7405
+ },
7406
+ "issue": {
7407
+ "description": "The step's identifier, once it exists",
7408
+ "nullable": true,
7409
+ "type": "string"
7410
+ },
7411
+ "key": {
7412
+ "description": "The step's key; null for the root or plan",
7413
+ "nullable": true,
7414
+ "type": "string"
7415
+ },
7416
+ "message": {
7417
+ "type": "string"
7418
+ }
7419
+ },
7420
+ "required": [
7421
+ "key",
7422
+ "index",
7423
+ "issue",
7424
+ "code",
7425
+ "field",
7426
+ "message"
7427
+ ],
7428
+ "type": "object"
7429
+ },
7430
+ "type": "array"
7431
+ }
7432
+ },
7433
+ "required": [
7434
+ "error",
7435
+ "message",
7436
+ "violations"
7437
+ ],
7438
+ "type": "object"
7439
+ }
7440
+ }
7441
+ },
7442
+ "description": "The plan is not valid; nothing was written"
7443
+ }
7444
+ },
7445
+ "summary": "Release a plan",
7446
+ "tags": []
7447
+ }
7448
+ },
7449
+ "/api/v1/plans/{id}/hold": {
7450
+ "post": {
7451
+ "callbacks": {},
7452
+ "deprecated": false,
7453
+ "description": "Requires the `harness:write` scope. Pauses every step: none is ready until the plan is released again. Holding a held plan changes nothing. Requires staff standing or being the plan's requester.",
7454
+ "parameters": [
7455
+ {
7456
+ "description": "Plan id",
7457
+ "in": "path",
7458
+ "name": "id",
7459
+ "required": true,
7460
+ "schema": {
7461
+ "format": "uuid",
7462
+ "type": "string"
7463
+ }
7464
+ }
7465
+ ],
7466
+ "responses": {
7467
+ "200": {
7468
+ "content": {
7469
+ "application/json": {
7470
+ "schema": {
7471
+ "properties": {
7472
+ "data": {
7473
+ "properties": {
7474
+ "created_by": {
7475
+ "nullable": true,
7476
+ "properties": {
7477
+ "email": {
7478
+ "nullable": true,
7479
+ "type": "string"
7480
+ },
7481
+ "id": {
7482
+ "format": "uuid",
7483
+ "nullable": true,
7484
+ "type": "string"
7485
+ },
7486
+ "name": {
7487
+ "nullable": true,
7488
+ "type": "string"
7489
+ }
7490
+ },
7491
+ "required": [
7492
+ "id",
7493
+ "name",
7494
+ "email"
7495
+ ],
7496
+ "type": "object"
7497
+ },
7498
+ "edges": {
7499
+ "items": {
7500
+ "properties": {
7501
+ "from": {
7502
+ "type": "string"
7503
+ },
7504
+ "to": {
7505
+ "type": "string"
7506
+ }
7507
+ },
7508
+ "required": [
7509
+ "from",
7510
+ "to"
7511
+ ],
7512
+ "type": "object"
7513
+ },
7514
+ "type": "array"
7515
+ },
7516
+ "estimate": {
7517
+ "nullable": true,
7518
+ "properties": {
7519
+ "ceiling_cents": {
7520
+ "type": "integer"
7521
+ },
7522
+ "minimum_budget_cents": {
7523
+ "type": "integer"
7524
+ },
7525
+ "per_attempt_reservation_cents": {
7526
+ "type": "integer"
7527
+ },
7528
+ "step_cap_cents": {
7529
+ "type": "integer"
7530
+ }
7531
+ },
7532
+ "type": "object"
7533
+ },
7534
+ "held_steps": {
7535
+ "description": "Steps an edit holds",
7536
+ "items": {
7537
+ "type": "string"
7538
+ },
7539
+ "type": "array"
7540
+ },
7541
+ "id": {
7542
+ "format": "uuid",
7543
+ "type": "string"
7544
+ },
7545
+ "inserted_at": {
7546
+ "format": "date-time",
7547
+ "type": "string"
7548
+ },
7549
+ "released_at": {
7550
+ "format": "date-time",
7551
+ "nullable": true,
7552
+ "type": "string"
7553
+ },
7554
+ "released_by": {
7555
+ "nullable": true,
7556
+ "properties": {
7557
+ "email": {
7558
+ "nullable": true,
7559
+ "type": "string"
7560
+ },
7561
+ "id": {
7562
+ "format": "uuid",
7563
+ "nullable": true,
7564
+ "type": "string"
7565
+ },
7566
+ "name": {
7567
+ "nullable": true,
7568
+ "type": "string"
7569
+ }
7570
+ },
7571
+ "required": [
7572
+ "id",
7573
+ "name",
7574
+ "email"
7575
+ ],
7576
+ "type": "object"
7577
+ },
7578
+ "retry_budget": {
7579
+ "type": "integer"
7580
+ },
7581
+ "revision": {
7582
+ "nullable": true,
7583
+ "properties": {
7584
+ "checksum": {
7585
+ "description": "SHA-256 of the frozen steps",
7586
+ "type": "string"
7587
+ },
7588
+ "id": {
7589
+ "format": "uuid",
7590
+ "type": "string"
7591
+ },
7592
+ "inserted_at": {
7593
+ "format": "date-time",
7594
+ "type": "string"
7595
+ },
7596
+ "number": {
7597
+ "type": "integer"
7598
+ }
7599
+ },
7600
+ "required": [
7601
+ "id",
7602
+ "number",
7603
+ "checksum",
7604
+ "inserted_at"
7605
+ ],
7606
+ "type": "object"
7607
+ },
7608
+ "root": {
7609
+ "nullable": true,
7610
+ "properties": {
7611
+ "id": {
7612
+ "type": "string"
7613
+ },
7614
+ "identifier": {
7615
+ "type": "string"
7616
+ },
7617
+ "title": {
7618
+ "type": "string"
7619
+ }
7620
+ },
7621
+ "type": "object"
7622
+ },
7623
+ "spend_budget_cents": {
7624
+ "nullable": true,
7625
+ "type": "integer"
7626
+ },
7627
+ "status": {
7628
+ "enum": [
7629
+ "held",
7630
+ "released",
7631
+ "running",
7632
+ "completed",
7633
+ "needs_attention"
7634
+ ],
7635
+ "type": "string"
7636
+ },
7637
+ "steps": {
7638
+ "items": {
7639
+ "properties": {
7640
+ "archived": {
7641
+ "type": "boolean"
7642
+ },
7643
+ "conditions": {
7644
+ "items": {
7645
+ "additionalProperties": false,
7646
+ "properties": {
7647
+ "id": {
7648
+ "format": "uuid",
7649
+ "type": "string"
7650
+ },
7651
+ "inserted_at": {
7652
+ "format": "date-time",
7653
+ "type": "string"
7654
+ },
7655
+ "issue_id": {
7656
+ "format": "uuid",
7657
+ "type": "string"
7658
+ },
7659
+ "kind": {
7660
+ "enum": [
7661
+ "not_before",
7662
+ "gate",
7663
+ "event"
7664
+ ],
7665
+ "type": "string"
7666
+ },
7667
+ "label": {
7668
+ "description": "A gate's label; null for other kinds",
7669
+ "nullable": true,
7670
+ "type": "string"
7671
+ },
7672
+ "not_before": {
7673
+ "description": "A `not_before` condition's instant; null for other kinds",
7674
+ "format": "date-time",
7675
+ "nullable": true,
7676
+ "type": "string"
7677
+ },
7678
+ "satisfied": {
7679
+ "type": "boolean"
7680
+ },
7681
+ "satisfied_at": {
7682
+ "format": "date-time",
7683
+ "nullable": true,
7684
+ "type": "string"
7685
+ },
7686
+ "satisfied_by": {
7687
+ "description": "Who ticked a gate; null otherwise",
7688
+ "nullable": true,
7689
+ "properties": {
7690
+ "email": {
7691
+ "nullable": true,
7692
+ "type": "string"
7693
+ },
7694
+ "id": {
7695
+ "format": "uuid",
7696
+ "nullable": true,
7697
+ "type": "string"
7698
+ },
7699
+ "name": {
7700
+ "nullable": true,
7701
+ "type": "string"
7702
+ }
7703
+ },
7704
+ "required": [
7705
+ "id",
7706
+ "name",
7707
+ "email"
7708
+ ],
7709
+ "type": "object"
7710
+ },
7711
+ "updated_at": {
7712
+ "format": "date-time",
7713
+ "type": "string"
7714
+ }
7715
+ },
7716
+ "required": [
7717
+ "id",
7718
+ "issue_id",
7719
+ "kind",
7720
+ "label",
7721
+ "not_before",
7722
+ "satisfied",
7723
+ "satisfied_at",
7724
+ "satisfied_by",
7725
+ "inserted_at",
7726
+ "updated_at"
7727
+ ],
7728
+ "type": "object"
7729
+ },
7730
+ "type": "array"
7731
+ },
7732
+ "container": {
7733
+ "description": "Has sub-steps; completes when they all complete",
7734
+ "type": "boolean"
7735
+ },
7736
+ "executor": {
7737
+ "enum": [
7738
+ "none",
7739
+ "operator"
7740
+ ],
7741
+ "type": "string"
7742
+ },
7743
+ "held": {
7744
+ "type": "boolean"
7745
+ },
7746
+ "identifier": {
7747
+ "type": "string"
7748
+ },
7749
+ "in_revision": {
7750
+ "type": "boolean"
7751
+ },
7752
+ "issue_id": {
7753
+ "format": "uuid",
7754
+ "type": "string"
7755
+ },
7756
+ "key": {
7757
+ "nullable": true,
7758
+ "type": "string"
7759
+ },
7760
+ "parent": {
7761
+ "description": "The containing step's identifier; null for the root",
7762
+ "nullable": true,
7763
+ "type": "string"
7764
+ },
7765
+ "ready": {
7766
+ "type": "boolean"
7767
+ },
7768
+ "state": {
7769
+ "properties": {
7770
+ "id": {
7771
+ "type": "string"
7772
+ },
7773
+ "name": {
7774
+ "type": "string"
7775
+ },
7776
+ "type": {
7777
+ "type": "string"
7778
+ }
7779
+ },
7780
+ "type": "object"
7781
+ },
7782
+ "team": {
7783
+ "properties": {
7784
+ "id": {
7785
+ "type": "string"
7786
+ },
7787
+ "key": {
7788
+ "type": "string"
7789
+ },
7790
+ "name": {
7791
+ "type": "string"
7792
+ }
7793
+ },
7794
+ "type": "object"
7795
+ },
7796
+ "title": {
7797
+ "type": "string"
7798
+ }
7799
+ },
7800
+ "required": [
7801
+ "issue_id",
7802
+ "identifier",
7803
+ "key",
7804
+ "title",
7805
+ "parent",
7806
+ "executor",
7807
+ "container",
7808
+ "state",
7809
+ "ready",
7810
+ "held",
7811
+ "conditions"
7812
+ ],
7813
+ "type": "object"
7814
+ },
7815
+ "type": "array"
7816
+ },
7817
+ "updated_at": {
7818
+ "format": "date-time",
7819
+ "type": "string"
7820
+ }
7821
+ },
7822
+ "required": [
7823
+ "id",
7824
+ "status",
7825
+ "root",
7826
+ "retry_budget",
7827
+ "spend_budget_cents",
7828
+ "revision",
7829
+ "held_steps",
7830
+ "steps",
7831
+ "edges"
7832
+ ],
7833
+ "type": "object"
7834
+ }
7835
+ },
7836
+ "required": [
7837
+ "data"
7838
+ ],
7839
+ "type": "object"
7840
+ }
7841
+ }
7842
+ },
7843
+ "description": "Success"
7844
+ },
7845
+ "400": {
7846
+ "description": "Bad request"
7847
+ },
7848
+ "401": {
7849
+ "description": "Missing or invalid token"
7850
+ },
7851
+ "403": {
7852
+ "description": "Token not permitted (org-scoped, non-admin, or missing scope)"
7853
+ },
7854
+ "404": {
7855
+ "description": "Not found"
7856
+ },
7857
+ "409": {
7858
+ "description": "The plan is completed"
7859
+ },
7860
+ "422": {
7861
+ "description": "Validation error"
7862
+ }
7863
+ },
7864
+ "summary": "Hold a plan",
7865
+ "tags": []
7866
+ }
3954
7867
  }
3955
7868
  },
3956
7869
  "security": [