@shipeasy/openapi 2.4.0 → 2.5.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.
@@ -223,12 +223,26 @@ CreateConfigRequest:
223
223
  additionalProperties: {}
224
224
  description: JSON Schema (draft 2020-12) describing the shape of the config value. Top-level `type` must be `'object'`; every published value is validated against this schema.
225
225
  value:
226
+ type: object
227
+ additionalProperties: {}
226
228
  description: "Initial config value. Either a single JSON object applied to every env, or a `{ env: value }` map seeding per-env values. Must match `schema`. Defaults to `{}` on every env when omitted."
229
+ dev:
230
+ type: object
231
+ additionalProperties: {}
232
+ description: "Seed the **dev** env's initial value (version 1), overriding `value` for dev. Published immediately. Must match `schema`."
233
+ staging:
234
+ type: object
235
+ additionalProperties: {}
236
+ description: "Seed the **staging** env's initial value (version 1), overriding `value` for staging. Published immediately. Must match `schema`."
237
+ prod:
238
+ type: object
239
+ additionalProperties: {}
240
+ description: "Seed the **prod** env's initial value (version 1), overriding `value` for prod. Published immediately. Must match `schema`."
227
241
  required:
228
242
  - name
229
243
  - schema
230
244
  additionalProperties: false
231
- description: Body for `POST /api/admin/configs`. `name` + `schema` required.
245
+ description: "Body for `POST /api/admin/configs`. `name` + `schema` required. Per-env `dev`/`staging`/`prod` values are published to that env at version 1 (overriding `value`)."
232
246
  CreateConfigResponse:
233
247
  type: object
234
248
  properties:
@@ -251,11 +265,25 @@ UpdateConfigRequest:
251
265
  type: object
252
266
  additionalProperties: {}
253
267
  value:
254
- description: Flat value applied to **every** env. Publishes a new version per env. To target one env, use `PUT /{id}/drafts` then `POST /{id}/publish`.
268
+ type: object
269
+ additionalProperties: {}
270
+ description: Flat value applied to **every** env. Publishes a new version per env. To publish one env only, pass that env's key (`dev`/`staging`/`prod`) instead.
271
+ dev:
272
+ type: object
273
+ additionalProperties: {}
274
+ description: "Publish a new version to the **dev** env only, immediately (no draft). Overrides `value` for dev. Must match the effective schema."
275
+ staging:
276
+ type: object
277
+ additionalProperties: {}
278
+ description: "Publish a new version to the **staging** env only, immediately (no draft). Overrides `value` for staging. Must match the effective schema."
279
+ prod:
280
+ type: object
281
+ additionalProperties: {}
282
+ description: "Publish a new version to the **prod** env only, immediately (no draft). Overrides `value` for prod. Must match the effective schema."
255
283
  folder:
256
284
  $ref: ./common.yaml#/Folder
257
285
  additionalProperties: false
258
- description: Body for `PATCH /api/admin/configs/{id}`. Partial — only supplied fields change. `value` republishes on every env.
286
+ description: "Body for `PATCH /api/admin/configs/{id}`. Partial — only supplied fields change. `value` republishes on every env; per-env `dev`/`staging`/`prod` publish a new version to just that env."
259
287
  UpdateConfigResponse:
260
288
  type: object
261
289
  properties:
@@ -300,6 +328,8 @@ SaveConfigDraftRequest:
300
328
  env:
301
329
  $ref: ./common.yaml#/Env
302
330
  value:
331
+ type: object
332
+ additionalProperties: {}
303
333
  description: Draft value to stage on `env`. Validated against the config's current schema.
304
334
  required:
305
335
  - env
@@ -205,6 +205,9 @@ GateApiRow:
205
205
  locked:
206
206
  description: If `true`, dashboard hides edit controls (e.g. the trailing public-floor entry).
207
207
  type: boolean
208
+ whitelist:
209
+ description: Cosmetic marker. When `true`, the dashboard renders this condition as the pinned, always-first "whitelist" allowlist block (a direct `email`/`user_id` `in […]` list) rather than a numbered targeting step. Purely presentational — ignored by evaluation, which treats the entry as an ordinary condition.
210
+ type: boolean
208
211
  required:
209
212
  - id
210
213
  - type
@@ -517,6 +520,9 @@ CreateGateRequest:
517
520
  locked:
518
521
  description: If `true`, dashboard hides edit controls (e.g. the trailing public-floor entry).
519
522
  type: boolean
523
+ whitelist:
524
+ description: Cosmetic marker. When `true`, the dashboard renders this condition as the pinned, always-first "whitelist" allowlist block (a direct `email`/`user_id` `in […]` list) rather than a numbered targeting step. Purely presentational — ignored by evaluation, which treats the entry as an ordinary condition.
525
+ type: boolean
520
526
  required:
521
527
  - id
522
528
  - type
@@ -802,6 +808,9 @@ UpdateGateRequest:
802
808
  locked:
803
809
  description: If `true`, dashboard hides edit controls (e.g. the trailing public-floor entry).
804
810
  type: boolean
811
+ whitelist:
812
+ description: Cosmetic marker. When `true`, the dashboard renders this condition as the pinned, always-first "whitelist" allowlist block (a direct `email`/`user_id` `in […]` list) rather than a numbered targeting step. Purely presentational — ignored by evaluation, which treats the entry as an ordinary condition.
813
+ type: boolean
805
814
  required:
806
815
  - id
807
816
  - type
@@ -487,6 +487,11 @@ MetricDirection:
487
487
  - lower_better
488
488
  - neutral
489
489
  description: Desired direction of movement. `higher_better` (default), `lower_better`, or `neutral` (guardrail).
490
+ MetricDisplayUnit:
491
+ description: Display unit (e.g. `ms`, `%`, `$`), or `null` when unitless.
492
+ anyOf:
493
+ - type: string
494
+ - type: "null"
490
495
  CreateMetricRequest:
491
496
  oneOf:
492
497
  - $ref: "#/CreateMetricWithQuery"
@@ -509,6 +514,8 @@ CreateMetricWithQuery:
509
514
  $ref: "#/MetricDefaultMinEffectOfInterest"
510
515
  direction:
511
516
  $ref: "#/MetricDirection"
517
+ unit:
518
+ $ref: "#/MetricDisplayUnit"
512
519
  required:
513
520
  - name
514
521
  - event_name
@@ -532,6 +539,8 @@ CreateMetricWithQueryIr:
532
539
  $ref: "#/MetricDefaultMinEffectOfInterest"
533
540
  direction:
534
541
  $ref: "#/MetricDirection"
542
+ unit:
543
+ $ref: "#/MetricDisplayUnit"
535
544
  required:
536
545
  - name
537
546
  - event_name
@@ -559,6 +568,8 @@ UpdateMetricWithQuery:
559
568
  $ref: "#/MetricDefaultMinEffectOfInterest"
560
569
  direction:
561
570
  $ref: "#/MetricDirection"
571
+ unit:
572
+ $ref: "#/MetricDisplayUnit"
562
573
  required:
563
574
  - query
564
575
  additionalProperties: false
@@ -578,6 +589,8 @@ UpdateMetricWithQueryIr:
578
589
  $ref: "#/MetricDefaultMinEffectOfInterest"
579
590
  direction:
580
591
  $ref: "#/MetricDirection"
592
+ unit:
593
+ $ref: "#/MetricDisplayUnit"
581
594
  required:
582
595
  - query_ir
583
596
  additionalProperties: false
@@ -595,8 +608,10 @@ UpdateMetricFields:
595
608
  $ref: "#/MetricDefaultMinEffectOfInterest"
596
609
  direction:
597
610
  $ref: "#/MetricDirection"
611
+ unit:
612
+ $ref: "#/MetricDisplayUnit"
598
613
  additionalProperties: false
599
- description: Update-metric variant that leaves the query untouched (metadata-only edit — folder, event, winsorisation, default minimum effect of interest, direction).
614
+ description: Update-metric variant that leaves the query untouched (metadata-only edit — folder, event, winsorisation, default minimum effect of interest, direction, display unit).
600
615
  CreateMetricResponse:
601
616
  type: object
602
617
  properties:
@@ -356,6 +356,11 @@ OpsRun:
356
356
  - type: string
357
357
  - type: "null"
358
358
  description: The agent-run session id recorded on the ack (dashboard deep-links to the run page), or `null`.
359
+ sessionUrl:
360
+ anyOf:
361
+ - type: string
362
+ - type: "null"
363
+ description: "The run's session-page deep link, or `null`. DERIVED (never stored): rebuilt from `sessionId` + the run's trigger connector — Claude's routine id (`?trigger=`), Copilot's repo (`/tasks/`), Cursor/Jules from the id alone."
359
364
  startedAt:
360
365
  type: string
361
366
  description: ISO-8601 timestamp the run started (the ack time).
@@ -365,15 +370,7 @@ OpsRun:
365
370
  - type: "null"
366
371
  description: ISO-8601 timestamp the run closed, or `null` while still open.
367
372
  completedAction:
368
- anyOf:
369
- - type: string
370
- enum:
371
- - link_pr
372
- - notify
373
- - status
374
- - superseded
375
- - type: "null"
376
- description: "Which final action closed the run — `link_pr`/`notify` are the agent's terminal ops actions, `status` a completion status flip (ready_for_qa/resolved), `superseded` a newer ack replacing it. `null` while the run is open."
373
+ $ref: "#/OpsRunActionOrNull"
377
374
  prNumber:
378
375
  anyOf:
379
376
  - type: number
@@ -390,6 +387,7 @@ OpsRun:
390
387
  - connectorId
391
388
  - ackedBy
392
389
  - sessionId
390
+ - sessionUrl
393
391
  - startedAt
394
392
  - completedAt
395
393
  - completedAction
@@ -918,6 +916,28 @@ CreateBugRequest:
918
916
  - $ref: "#/OpsItemPriority"
919
917
  - type: "null"
920
918
  description: Initial triage priority, or `null`.
919
+ status:
920
+ anyOf:
921
+ - $ref: "#/OpsItemStatus"
922
+ description: Initial lifecycle status; defaults to `open` when omitted.
923
+ assigneeId:
924
+ anyOf:
925
+ - type: string
926
+ - type: "null"
927
+ description: The `users.id` of the person to assign as owner at creation, or `null`.
928
+ subscribers:
929
+ type: array
930
+ items:
931
+ type: string
932
+ format: email
933
+ default: []
934
+ description: Emails of teammates to subscribe to this item's Slack pings at creation.
935
+ tags:
936
+ type: array
937
+ items:
938
+ type: string
939
+ default: []
940
+ description: Tag names to attach at creation (get-or-created by name, deduped case-insensitively).
921
941
  reporterEmail:
922
942
  anyOf:
923
943
  - type: string
@@ -987,6 +1007,28 @@ CreateFeatureRequestRequest:
987
1007
  - $ref: "#/OpsItemPriority"
988
1008
  - type: "null"
989
1009
  description: Initial triage priority, or `null`.
1010
+ status:
1011
+ anyOf:
1012
+ - $ref: "#/OpsItemStatus"
1013
+ description: Initial lifecycle status; defaults to `open` when omitted.
1014
+ assigneeId:
1015
+ anyOf:
1016
+ - type: string
1017
+ - type: "null"
1018
+ description: The `users.id` of the person to assign as owner at creation, or `null`.
1019
+ subscribers:
1020
+ type: array
1021
+ items:
1022
+ type: string
1023
+ format: email
1024
+ default: []
1025
+ description: Emails of teammates to subscribe to this item's Slack pings at creation.
1026
+ tags:
1027
+ type: array
1028
+ items:
1029
+ type: string
1030
+ default: []
1031
+ description: Tag names to attach at creation (get-or-created by name, deduped case-insensitively).
990
1032
  reporterEmail:
991
1033
  anyOf:
992
1034
  - type: string
@@ -1127,6 +1169,22 @@ OpsItemNotifyOrNull:
1127
1169
  - $ref: ./common.yaml#/NotificationTarget
1128
1170
  - type: "null"
1129
1171
  description: Where this item's completion notification lands, or `null`.
1172
+ OpsRunAction:
1173
+ type: string
1174
+ enum:
1175
+ - link_pr
1176
+ - notify
1177
+ - status
1178
+ - superseded
1179
+ description: >-
1180
+ The final action that closed a run record — `link_pr`/`notify` are the
1181
+ agent's terminal ops actions, `status` a completion status flip
1182
+ (ready_for_qa/resolved), `superseded` a newer ack replacing an open run.
1183
+ OpsRunActionOrNull:
1184
+ anyOf:
1185
+ - $ref: "#/OpsRunAction"
1186
+ - type: "null"
1187
+ description: Which final action closed the run, or `null` while it is open (or a non-run record).
1130
1188
  UpdateOpsItemStatusRequest:
1131
1189
  type: object
1132
1190
  properties:
@@ -1681,22 +1739,19 @@ OpsInvestigation:
1681
1739
  anyOf:
1682
1740
  - type: string
1683
1741
  - type: "null"
1684
- description: The agent-run session id, or `null`.
1685
- ackedBy:
1742
+ description: "The agent-run session id, or `null`."
1743
+ sessionUrl:
1686
1744
  anyOf:
1687
1745
  - type: string
1688
1746
  - type: "null"
1689
- description: Email of the human who acked (run records for a human ack), or `null`.
1690
- completedAction:
1747
+ description: "The run's session-page deep link, or `null`. DERIVED (never stored): rebuilt from `sessionId` + the run's trigger connector — Claude's routine id (`?trigger=`), Copilot's repo (`/tasks/`), Cursor/Jules from the id alone. Only `working` run records carry one."
1748
+ ackedBy:
1691
1749
  anyOf:
1692
1750
  - type: string
1693
- enum:
1694
- - link_pr
1695
- - notify
1696
- - status
1697
- - superseded
1698
1751
  - type: "null"
1699
- description: "Which final action closed a `working` run record, or `null` (open run / non-run record)."
1752
+ description: Email of the human who acked (run records for a human ack), or `null`.
1753
+ completedAction:
1754
+ $ref: "#/OpsRunActionOrNull"
1700
1755
  createdAt:
1701
1756
  type: string
1702
1757
  description: ISO-8601 creation timestamp.
@@ -1724,6 +1779,7 @@ OpsInvestigation:
1724
1779
  - startedAt
1725
1780
  - completedAt
1726
1781
  - sessionId
1782
+ - sessionUrl
1727
1783
  - ackedBy
1728
1784
  - completedAction
1729
1785
  - createdAt
@@ -1840,6 +1896,94 @@ CreateOpsInvestigationRequest:
1840
1896
  - kind
1841
1897
  additionalProperties: false
1842
1898
  description: "Body for `POST /api/admin/ops/{handle}/investigation`. `kind` is required; include at least one content field (`summary`/`findings`/`question`/`qaNotes`) — the panel renders whatever it gets."
1899
+ UpdateOpsInvestigationRequest:
1900
+ type: object
1901
+ properties:
1902
+ kind:
1903
+ type: string
1904
+ enum:
1905
+ - investigated
1906
+ - detected
1907
+ - question
1908
+ - ready_for_qa
1909
+ - working
1910
+ - note
1911
+ description: Reclassify the record's lifecycle stage (e.g. flip a `working` run into `investigated` once findings land).
1912
+ summary:
1913
+ type: string
1914
+ maxLength: 2000
1915
+ description: One-line summary of the record.
1916
+ findings:
1917
+ type: string
1918
+ maxLength: 50000
1919
+ description: The full findings write-up (markdown).
1920
+ question:
1921
+ type: string
1922
+ maxLength: 10000
1923
+ description: A blocking question for the team (markdown).
1924
+ qaNotes:
1925
+ type: string
1926
+ maxLength: 50000
1927
+ description: How to verify the fix — QA notes (markdown).
1928
+ model:
1929
+ type: string
1930
+ maxLength: 200
1931
+ description: The model the agent ran on.
1932
+ prNumber:
1933
+ type: integer
1934
+ description: A PR the record references.
1935
+ prUrl:
1936
+ type: string
1937
+ format: uri
1938
+ maxLength: 2000
1939
+ description: HTML URL of that PR.
1940
+ sources:
1941
+ type: array
1942
+ maxItems: 200
1943
+ items:
1944
+ type: object
1945
+ properties:
1946
+ path:
1947
+ type: string
1948
+ description: Repo-relative file path inspected.
1949
+ url:
1950
+ type: string
1951
+ description: External link consulted.
1952
+ label:
1953
+ type: string
1954
+ description: Human-readable label for the source.
1955
+ additionalProperties: false
1956
+ description: One file/link inspected while producing the record.
1957
+ description: The files/links inspected.
1958
+ confidence:
1959
+ type: string
1960
+ enum:
1961
+ - low
1962
+ - medium
1963
+ - high
1964
+ description: Self-reported confidence in the record.
1965
+ tokensUsed:
1966
+ type: integer
1967
+ description: Tokens the run consumed.
1968
+ durationMs:
1969
+ type: integer
1970
+ description: Run duration in milliseconds.
1971
+ visibility:
1972
+ type: string
1973
+ enum:
1974
+ - draft
1975
+ - published
1976
+ description: Record visibility. `draft` keeps it out of the panel; `published` surfaces it.
1977
+ completedAt:
1978
+ type: string
1979
+ description: ISO-8601 timestamp the work finished. Set it (or flip `kind` off `working`) to mark a run record done.
1980
+ sessionId:
1981
+ type: string
1982
+ maxLength: 300
1983
+ description: The agent-run session id, so the dashboard can deep-link to the run.
1984
+ additionalProperties: false
1985
+ minProperties: 1
1986
+ description: "Body for `PATCH /api/admin/ops/{handle}/investigation/{investigationId}` — a partial update of one existing investigation record (typically the `working` run record you were handed). Send only the fields you want to change; at least one is required."
1843
1987
  NotificationFeedItem:
1844
1988
  type: object
1845
1989
  properties:
package/spec/openapi.yaml CHANGED
@@ -209,6 +209,15 @@ tags:
209
209
  **Mentions.** `@teammate` in a body raises an in-app notification for that
210
210
  person; `@shipeasy` asks Jarvis (the AI agent) to read the item and reply.
211
211
  Comments authored by Jarvis carry `authorType: system`.
212
+ - name: Investigations
213
+ parent: Ops
214
+ description: |-
215
+ Investigation records on a queue item — the structured, read-only write-ups
216
+ an AI agent produces while working it (findings / a blocking question / QA
217
+ notes), plus the `working` run rows an ack or an AI hand-off opens. This is
218
+ the AI-write seam the cockpit's detail panel renders: `list` reads what a
219
+ previous run found, `create` appends a new record, and `update` fills in the
220
+ `working` run record you were handed (findings, PR, confidence) as you work.
212
221
  - name: Projects
213
222
  description: |-
214
223
  Projects: the account-level container every other resource is scoped to.
@@ -351,6 +360,8 @@ paths:
351
360
  $ref: ./paths/ops.yaml#/~1api~1admin~1ops~1{handle}~1ack
352
361
  /api/admin/ops/{handle}/investigation:
353
362
  $ref: ./paths/ops.yaml#/~1api~1admin~1ops~1{handle}~1investigation
363
+ /api/admin/ops/{handle}/investigation/{investigationId}:
364
+ $ref: ./paths/ops.yaml#/~1api~1admin~1ops~1{handle}~1investigation~1{investigationId}
354
365
  /api/admin/agent-profiles:
355
366
  $ref: ./paths/ops.yaml#/~1api~1admin~1agent-profiles
356
367
  /api/admin/ops/{handle}/comments:
@@ -87,7 +87,7 @@
87
87
 
88
88
  - **Minimal create** — `name` + `schema`. Initial value defaults to `{}`.
89
89
  - **Seeded create** — supply a flat `value` to publish the same object on every env.
90
- - **Per-env seed** — supply a `{ env: value }` map for different per-env starting values.
90
+ - **Per-env seed** — supply a `{ env: value }` map under `value`, or pass the env keys `dev`/`staging`/`prod` directly (each overrides `value` for that env and is published at version 1).
91
91
  tags:
92
92
  - Configs
93
93
  parameters:
@@ -129,8 +129,8 @@
129
129
  - name: free
130
130
  - name: pro
131
131
  perEnvSeed:
132
- summary: Per-env seed
133
- description: "Pass a `{ env: value }` map to seed different initial values per env."
132
+ summary: Per-env seed (env keys)
133
+ description: "Pass the env keys directly to seed different initial values per env. Each overrides `value` for that env and is published at version 1."
134
134
  value:
135
135
  name: pricing.tiers
136
136
  schema:
@@ -140,20 +140,15 @@
140
140
  type: array
141
141
  required:
142
142
  - tiers
143
- value:
144
- dev:
145
- tiers:
146
- - name: free
147
- - name: pro
148
- - name: enterprise
149
- stage:
150
- tiers:
151
- - name: free
152
- - name: pro
153
- prod:
154
- tiers:
155
- - name: free
156
- - name: pro
143
+ dev:
144
+ tiers:
145
+ - name: free
146
+ - name: pro
147
+ - name: enterprise
148
+ prod:
149
+ tiers:
150
+ - name: free
151
+ - name: pro
157
152
  responses:
158
153
  "201":
159
154
  description: Create a dynamic config
@@ -302,15 +297,13 @@
302
297
  operationId: updateConfig
303
298
  summary: Update a dynamic config
304
299
  description: |-
305
- Partial update. When `value` is supplied it is **republished on every env** (new version per env). When `schema` is supplied it replaces the current schema; every existing value is re-validated.
306
-
307
- For env-scoped edits, use the draft/publish flow (`PUT /{id}/drafts` then `POST /{id}/publish`) instead.
300
+ Partial update. When `value` is supplied it is **republished on every env** (new version per env). A per-env key (`dev`/`staging`/`prod`) publishes a new version to **only that env**, immediately, overriding `value` for it. When `schema` is supplied it replaces the current schema; every existing value is re-validated.
308
301
 
309
302
  **Use cases**
310
303
 
311
304
  - **Republish flat value** — `{ "value": {…} }` sets the same value on every env.
305
+ - **Publish one env** — `{ "prod": {…} }` publishes a new version to prod only, instantly.
312
306
  - **Schema migration** — `{ "schema": {…} }` replaces the schema; existing values are re-validated.
313
- - **Env-scoped edits** — use `PUT /{id}/drafts` + `POST /{id}/publish` instead of PATCH.
314
307
  tags:
315
308
  - Configs
316
309
  parameters:
@@ -336,6 +329,15 @@
336
329
  tiers:
337
330
  - name: free
338
331
  - name: pro
332
+ prodOnly:
333
+ summary: Per-env — publish prod only
334
+ description: Publishes a new version to prod only, immediately. dev/staging untouched.
335
+ value:
336
+ prod:
337
+ tiers:
338
+ - name: free
339
+ - name: pro
340
+ - name: enterprise
339
341
  schemaOnly:
340
342
  summary: Schema-only update
341
343
  description: Replaces the schema. Existing values must still validate or the update fails.
@@ -496,6 +498,7 @@
496
498
  - VALIDATION
497
499
  x-cli:
498
500
  name: draft
501
+ hidden: true
499
502
  positional:
500
503
  - id
501
504
  delete:
@@ -555,6 +558,7 @@
555
558
  - NOT_FOUND
556
559
  x-cli:
557
560
  name: discard-draft
561
+ hidden: true
558
562
  positional:
559
563
  - id
560
564
  /api/admin/configs/{id}/publish:
@@ -626,6 +630,7 @@
626
630
  - VALIDATION
627
631
  x-cli:
628
632
  name: publish
633
+ hidden: true
629
634
  positional:
630
635
  - id
631
636
  /api/admin/configs/{id}/activity:
@@ -690,6 +695,7 @@
690
695
  - NOT_FOUND
691
696
  x-cli:
692
697
  name: activity
698
+ hidden: true
693
699
  positional:
694
700
  - id
695
701
  /api/admin/configs/{id}/versions:
@@ -756,6 +762,7 @@
756
762
  - NOT_FOUND
757
763
  x-cli:
758
764
  name: versions
765
+ hidden: true
759
766
  positional:
760
767
  - id
761
768
  /api/admin/configs/{id}/schema:
@@ -505,7 +505,7 @@
505
505
  **Use case:** Read what a previous agent run already found before starting
506
506
  your own investigation of the item.
507
507
  tags:
508
- - Ops
508
+ - Investigations
509
509
  parameters:
510
510
  - $ref: ../components/parameters.yaml#/ProjectId
511
511
  - name: handle
@@ -536,6 +536,10 @@
536
536
  - UNAUTHORIZED
537
537
  - FORBIDDEN
538
538
  - NOT_FOUND
539
+ x-cli:
540
+ name: list
541
+ positional:
542
+ - handle
539
543
  post:
540
544
  operationId: createOpsInvestigation
541
545
  summary: Record an investigation
@@ -551,7 +555,7 @@
551
555
  markdown findings, sources inspected, confidence) so the team — and the
552
556
  next agent run — sees what you learned.
553
557
  tags:
554
- - Ops
558
+ - Investigations
555
559
  parameters:
556
560
  - $ref: ../components/parameters.yaml#/ProjectId
557
561
  - name: handle
@@ -609,6 +613,85 @@
609
613
  - FORBIDDEN
610
614
  - NOT_FOUND
611
615
  - VALIDATION
616
+ x-cli:
617
+ name: create
618
+ positional:
619
+ - handle
620
+ /api/admin/ops/{handle}/investigation/{investigationId}:
621
+ patch:
622
+ operationId: updateOpsInvestigation
623
+ summary: Update an investigation record
624
+ description: |-
625
+ Update one existing investigation record in place — the write-back seam for
626
+ the `working` run record you were handed when a run was launched. Fill in
627
+ the `summary`/`findings`, attach the fixing PR, record your `confidence`
628
+ and the `sources` you inspected, or flip its `kind` off `working` once the
629
+ investigation is done. A partial patch: send only the fields you want to
630
+ change. Safe for restricted ops keys (it never reads or deletes).
631
+
632
+ **Use case:** A run started with an empty `working` record; as you work,
633
+ PATCH it with your findings so the cockpit's detail panel fills in live —
634
+ no need to append a second record.
635
+ tags:
636
+ - Investigations
637
+ parameters:
638
+ - $ref: ../components/parameters.yaml#/ProjectId
639
+ - name: handle
640
+ in: path
641
+ required: true
642
+ description: Per-project item number (e.g. `7`) or the full ops item id.
643
+ schema:
644
+ $ref: ../components/schemas/common.yaml#/ResourceId
645
+ - name: investigationId
646
+ in: path
647
+ required: true
648
+ description: The investigation record id (from `POST`/`GET .../investigation` or the `runId` an ack/launch returned).
649
+ schema:
650
+ $ref: ../components/schemas/common.yaml#/ResourceId
651
+ requestBody:
652
+ required: true
653
+ content:
654
+ application/json:
655
+ schema:
656
+ $ref: ../components/schemas/ops.yaml#/UpdateOpsInvestigationRequest
657
+ examples:
658
+ findings:
659
+ summary: Fill in the run record's findings
660
+ value:
661
+ kind: investigated
662
+ summary: Root cause is a stale KV read on the checkout flag.
663
+ findings: "The `checkout.cta` gate is rebuilt without a CDN purge, so…"
664
+ confidence: high
665
+ prNumber: 4821
666
+ prUrl: https://github.com/acme/web/pull/4821
667
+ responses:
668
+ "200":
669
+ description: The updated investigation record
670
+ content:
671
+ application/json:
672
+ schema:
673
+ $ref: ../components/schemas/ops.yaml#/OpsInvestigation
674
+ "400":
675
+ $ref: ../components/responses.yaml#/BadRequest
676
+ "401":
677
+ $ref: ../components/responses.yaml#/Unauthorized
678
+ "403":
679
+ $ref: ../components/responses.yaml#/Forbidden
680
+ "404":
681
+ $ref: ../components/responses.yaml#/NotFound
682
+ "422":
683
+ $ref: ../components/responses.yaml#/UnprocessableEntity
684
+ x-error-codes:
685
+ - BAD_REQUEST
686
+ - UNAUTHORIZED
687
+ - FORBIDDEN
688
+ - NOT_FOUND
689
+ - VALIDATION
690
+ x-cli:
691
+ name: update
692
+ positional:
693
+ - handle
694
+ - investigationId
612
695
  /api/admin/agent-profiles:
613
696
  get:
614
697
  operationId: listOpsAgents