forge-openclaw-plugin 0.2.15 → 0.2.19

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.
Files changed (67) hide show
  1. package/README.md +39 -4
  2. package/dist/assets/{board-C_m78kvK.js → board-8L3uX7_O.js} +2 -2
  3. package/dist/assets/{board-C_m78kvK.js.map → board-8L3uX7_O.js.map} +1 -1
  4. package/dist/assets/index-Cj1IBH_w.js +36 -0
  5. package/dist/assets/index-Cj1IBH_w.js.map +1 -0
  6. package/dist/assets/index-DQT6EbuS.css +1 -0
  7. package/dist/assets/{motion-CpZvZumD.js → motion-1GAqqi8M.js} +2 -2
  8. package/dist/assets/{motion-CpZvZumD.js.map → motion-1GAqqi8M.js.map} +1 -1
  9. package/dist/assets/{table-DtyXTw03.js → table-DBGlgRjk.js} +2 -2
  10. package/dist/assets/{table-DtyXTw03.js.map → table-DBGlgRjk.js.map} +1 -1
  11. package/dist/assets/{ui-BXbpiKyS.js → ui-iTluWjC4.js} +2 -2
  12. package/dist/assets/{ui-BXbpiKyS.js.map → ui-iTluWjC4.js.map} +1 -1
  13. package/dist/assets/{vendor-QBH6qVEe.js → vendor-BvM2F9Dp.js} +151 -81
  14. package/dist/assets/vendor-BvM2F9Dp.js.map +1 -0
  15. package/dist/assets/{viz-w-IMeueL.js → viz-CNeunkfu.js} +2 -2
  16. package/dist/assets/{viz-w-IMeueL.js.map → viz-CNeunkfu.js.map} +1 -1
  17. package/dist/index.html +8 -8
  18. package/dist/openclaw/local-runtime.js +142 -9
  19. package/dist/openclaw/parity.js +1 -0
  20. package/dist/openclaw/plugin-entry-shared.js +7 -1
  21. package/dist/openclaw/routes.js +7 -0
  22. package/dist/openclaw/tools.js +198 -16
  23. package/dist/server/app.js +2615 -251
  24. package/dist/server/managers/platform/secrets-manager.js +44 -1
  25. package/dist/server/managers/runtime.js +3 -1
  26. package/dist/server/openapi.js +2212 -170
  27. package/dist/server/repositories/calendar.js +1101 -0
  28. package/dist/server/repositories/deleted-entities.js +10 -2
  29. package/dist/server/repositories/habits.js +358 -0
  30. package/dist/server/repositories/notes.js +161 -28
  31. package/dist/server/repositories/projects.js +45 -13
  32. package/dist/server/repositories/rewards.js +176 -6
  33. package/dist/server/repositories/settings.js +47 -5
  34. package/dist/server/repositories/task-runs.js +46 -10
  35. package/dist/server/repositories/tasks.js +25 -9
  36. package/dist/server/repositories/weekly-reviews.js +109 -0
  37. package/dist/server/repositories/work-adjustments.js +105 -0
  38. package/dist/server/services/calendar-runtime.js +1301 -0
  39. package/dist/server/services/context.js +16 -6
  40. package/dist/server/services/dashboard.js +6 -3
  41. package/dist/server/services/entity-crud.js +116 -3
  42. package/dist/server/services/gamification.js +66 -18
  43. package/dist/server/services/insights.js +2 -1
  44. package/dist/server/services/projects.js +32 -8
  45. package/dist/server/services/reviews.js +17 -2
  46. package/dist/server/services/work-time.js +27 -0
  47. package/dist/server/types.js +1069 -45
  48. package/openclaw.plugin.json +1 -1
  49. package/package.json +1 -1
  50. package/server/migrations/003_habits.sql +30 -0
  51. package/server/migrations/004_habit_links.sql +8 -0
  52. package/server/migrations/005_habit_psyche_links.sql +24 -0
  53. package/server/migrations/006_work_adjustments.sql +14 -0
  54. package/server/migrations/007_weekly_review_closures.sql +17 -0
  55. package/server/migrations/008_calendar_execution.sql +147 -0
  56. package/server/migrations/009_true_calendar_events.sql +195 -0
  57. package/server/migrations/010_calendar_selection_state.sql +6 -0
  58. package/server/migrations/011_calendar_timezone_backfill.sql +11 -0
  59. package/server/migrations/012_work_block_ranges.sql +7 -0
  60. package/server/migrations/013_microsoft_local_auth_settings.sql +8 -0
  61. package/server/migrations/014_note_tags_and_ephemeral.sql +8 -0
  62. package/skills/forge-openclaw/SKILL.md +130 -10
  63. package/skills/forge-openclaw/cron_jobs.md +395 -0
  64. package/dist/assets/index-BWtLtXwb.js +0 -36
  65. package/dist/assets/index-BWtLtXwb.js.map +0 -1
  66. package/dist/assets/index-Dp5GXY_z.css +0 -1
  67. package/dist/assets/vendor-QBH6qVEe.js.map +0 -1
@@ -55,7 +55,18 @@ export function buildOpenApiDocument() {
55
55
  const goal = {
56
56
  type: "object",
57
57
  additionalProperties: false,
58
- required: ["id", "title", "description", "horizon", "status", "targetPoints", "themeColor", "createdAt", "updatedAt", "tagIds"],
58
+ required: [
59
+ "id",
60
+ "title",
61
+ "description",
62
+ "horizon",
63
+ "status",
64
+ "targetPoints",
65
+ "themeColor",
66
+ "createdAt",
67
+ "updatedAt",
68
+ "tagIds"
69
+ ],
59
70
  properties: {
60
71
  id: { type: "string" },
61
72
  title: { type: "string" },
@@ -75,7 +86,14 @@ export function buildOpenApiDocument() {
75
86
  {
76
87
  type: "object",
77
88
  additionalProperties: false,
78
- required: ["progress", "totalTasks", "completedTasks", "earnedPoints", "momentumLabel", "tags"],
89
+ required: [
90
+ "progress",
91
+ "totalTasks",
92
+ "completedTasks",
93
+ "earnedPoints",
94
+ "momentumLabel",
95
+ "tags"
96
+ ],
79
97
  properties: {
80
98
  progress: { type: "number" },
81
99
  totalTasks: { type: "integer" },
@@ -90,7 +108,18 @@ export function buildOpenApiDocument() {
90
108
  const project = {
91
109
  type: "object",
92
110
  additionalProperties: false,
93
- required: ["id", "goalId", "title", "description", "status", "targetPoints", "themeColor", "createdAt", "updatedAt"],
111
+ required: [
112
+ "id",
113
+ "goalId",
114
+ "title",
115
+ "description",
116
+ "status",
117
+ "targetPoints",
118
+ "themeColor",
119
+ "schedulingRules",
120
+ "createdAt",
121
+ "updatedAt"
122
+ ],
94
123
  properties: {
95
124
  id: { type: "string" },
96
125
  goalId: { type: "string" },
@@ -99,6 +128,7 @@ export function buildOpenApiDocument() {
99
128
  status: { type: "string", enum: ["active", "paused", "completed"] },
100
129
  targetPoints: { type: "integer" },
101
130
  themeColor: { type: "string" },
131
+ schedulingRules: { $ref: "#/components/schemas/CalendarSchedulingRules" },
102
132
  createdAt: { type: "string", format: "date-time" },
103
133
  updatedAt: { type: "string", format: "date-time" }
104
134
  }
@@ -106,10 +136,22 @@ export function buildOpenApiDocument() {
106
136
  const taskTimeSummary = {
107
137
  type: "object",
108
138
  additionalProperties: false,
109
- required: ["totalTrackedSeconds", "totalCreditedSeconds", "activeRunCount", "hasCurrentRun", "currentRunId"],
139
+ required: [
140
+ "totalTrackedSeconds",
141
+ "totalCreditedSeconds",
142
+ "liveTrackedSeconds",
143
+ "liveCreditedSeconds",
144
+ "manualAdjustedSeconds",
145
+ "activeRunCount",
146
+ "hasCurrentRun",
147
+ "currentRunId"
148
+ ],
110
149
  properties: {
111
150
  totalTrackedSeconds: { type: "integer" },
112
151
  totalCreditedSeconds: { type: "number" },
152
+ liveTrackedSeconds: { type: "integer" },
153
+ liveCreditedSeconds: { type: "number" },
154
+ manualAdjustedSeconds: { type: "integer" },
113
155
  activeRunCount: { type: "integer" },
114
156
  hasCurrentRun: { type: "boolean" },
115
157
  currentRunId: nullable({ type: "string" })
@@ -164,6 +206,8 @@ export function buildOpenApiDocument() {
164
206
  "effort",
165
207
  "energy",
166
208
  "points",
209
+ "plannedDurationSeconds",
210
+ "schedulingRules",
167
211
  "sortOrder",
168
212
  "completedAt",
169
213
  "createdAt",
@@ -175,7 +219,10 @@ export function buildOpenApiDocument() {
175
219
  id: { type: "string" },
176
220
  title: { type: "string" },
177
221
  description: { type: "string" },
178
- status: { type: "string", enum: ["backlog", "focus", "in_progress", "blocked", "done"] },
222
+ status: {
223
+ type: "string",
224
+ enum: ["backlog", "focus", "in_progress", "blocked", "done"]
225
+ },
179
226
  priority: { type: "string", enum: ["low", "medium", "high", "critical"] },
180
227
  owner: { type: "string" },
181
228
  goalId: nullable({ type: "string" }),
@@ -184,6 +231,10 @@ export function buildOpenApiDocument() {
184
231
  effort: { type: "string", enum: ["light", "deep", "marathon"] },
185
232
  energy: { type: "string", enum: ["low", "steady", "high"] },
186
233
  points: { type: "integer" },
234
+ plannedDurationSeconds: nullable({ type: "integer" }),
235
+ schedulingRules: nullable({
236
+ $ref: "#/components/schemas/CalendarSchedulingRules"
237
+ }),
187
238
  sortOrder: { type: "integer" },
188
239
  completedAt: nullable({ type: "string", format: "date-time" }),
189
240
  createdAt: { type: "string", format: "date-time" },
@@ -216,14 +267,18 @@ export function buildOpenApiDocument() {
216
267
  "creditedSeconds",
217
268
  "remainingSeconds",
218
269
  "overtimeSeconds",
219
- "isCurrent"
270
+ "isCurrent",
271
+ "overrideReason"
220
272
  ],
221
273
  properties: {
222
274
  id: { type: "string" },
223
275
  taskId: { type: "string" },
224
276
  taskTitle: { type: "string" },
225
277
  actor: { type: "string" },
226
- status: { type: "string", enum: ["active", "completed", "released", "timed_out"] },
278
+ status: {
279
+ type: "string",
280
+ enum: ["active", "completed", "released", "timed_out"]
281
+ },
227
282
  note: { type: "string" },
228
283
  leaseTtlSeconds: { type: "integer" },
229
284
  claimedAt: { type: "string", format: "date-time" },
@@ -239,19 +294,536 @@ export function buildOpenApiDocument() {
239
294
  creditedSeconds: { type: "number" },
240
295
  remainingSeconds: nullable({ type: "integer" }),
241
296
  overtimeSeconds: { type: "integer" },
242
- isCurrent: { type: "boolean" }
297
+ isCurrent: { type: "boolean" },
298
+ overrideReason: nullable({ type: "string" })
299
+ }
300
+ };
301
+ const calendarSchedulingRules = {
302
+ type: "object",
303
+ additionalProperties: false,
304
+ required: [
305
+ "allowWorkBlockKinds",
306
+ "blockWorkBlockKinds",
307
+ "allowCalendarIds",
308
+ "blockCalendarIds",
309
+ "allowEventTypes",
310
+ "blockEventTypes",
311
+ "allowEventKeywords",
312
+ "blockEventKeywords",
313
+ "allowAvailability",
314
+ "blockAvailability"
315
+ ],
316
+ properties: {
317
+ allowWorkBlockKinds: arrayOf({
318
+ type: "string",
319
+ enum: [
320
+ "main_activity",
321
+ "secondary_activity",
322
+ "third_activity",
323
+ "rest",
324
+ "holiday",
325
+ "custom"
326
+ ]
327
+ }),
328
+ blockWorkBlockKinds: arrayOf({
329
+ type: "string",
330
+ enum: [
331
+ "main_activity",
332
+ "secondary_activity",
333
+ "third_activity",
334
+ "rest",
335
+ "holiday",
336
+ "custom"
337
+ ]
338
+ }),
339
+ allowCalendarIds: arrayOf({ type: "string" }),
340
+ blockCalendarIds: arrayOf({ type: "string" }),
341
+ allowEventTypes: arrayOf({ type: "string" }),
342
+ blockEventTypes: arrayOf({ type: "string" }),
343
+ allowEventKeywords: arrayOf({ type: "string" }),
344
+ blockEventKeywords: arrayOf({ type: "string" }),
345
+ allowAvailability: arrayOf({ type: "string", enum: ["busy", "free"] }),
346
+ blockAvailability: arrayOf({ type: "string", enum: ["busy", "free"] })
347
+ }
348
+ };
349
+ const calendarConnection = {
350
+ type: "object",
351
+ additionalProperties: false,
352
+ required: [
353
+ "id",
354
+ "provider",
355
+ "label",
356
+ "accountLabel",
357
+ "status",
358
+ "config",
359
+ "forgeCalendarId",
360
+ "lastSyncedAt",
361
+ "lastSyncError",
362
+ "createdAt",
363
+ "updatedAt"
364
+ ],
365
+ properties: {
366
+ id: { type: "string" },
367
+ provider: { type: "string", enum: ["google", "apple", "caldav"] },
368
+ label: { type: "string" },
369
+ accountLabel: { type: "string" },
370
+ status: {
371
+ type: "string",
372
+ enum: ["connected", "needs_attention", "error"]
373
+ },
374
+ config: { type: "object", additionalProperties: true },
375
+ forgeCalendarId: nullable({ type: "string" }),
376
+ lastSyncedAt: nullable({ type: "string", format: "date-time" }),
377
+ lastSyncError: nullable({ type: "string" }),
378
+ createdAt: { type: "string", format: "date-time" },
379
+ updatedAt: { type: "string", format: "date-time" }
380
+ }
381
+ };
382
+ const calendarResource = {
383
+ type: "object",
384
+ additionalProperties: false,
385
+ required: [
386
+ "id",
387
+ "connectionId",
388
+ "remoteId",
389
+ "title",
390
+ "description",
391
+ "color",
392
+ "timezone",
393
+ "isPrimary",
394
+ "canWrite",
395
+ "forgeManaged",
396
+ "lastSyncedAt",
397
+ "createdAt",
398
+ "updatedAt"
399
+ ],
400
+ properties: {
401
+ id: { type: "string" },
402
+ connectionId: { type: "string" },
403
+ remoteId: { type: "string" },
404
+ title: { type: "string" },
405
+ description: { type: "string" },
406
+ color: { type: "string" },
407
+ timezone: { type: "string" },
408
+ isPrimary: { type: "boolean" },
409
+ canWrite: { type: "boolean" },
410
+ forgeManaged: { type: "boolean" },
411
+ lastSyncedAt: nullable({ type: "string", format: "date-time" }),
412
+ createdAt: { type: "string", format: "date-time" },
413
+ updatedAt: { type: "string", format: "date-time" }
414
+ }
415
+ };
416
+ const calendarEventSource = {
417
+ type: "object",
418
+ additionalProperties: false,
419
+ required: [
420
+ "id",
421
+ "provider",
422
+ "connectionId",
423
+ "calendarId",
424
+ "remoteCalendarId",
425
+ "remoteEventId",
426
+ "remoteUid",
427
+ "recurrenceInstanceId",
428
+ "isMasterRecurring",
429
+ "remoteHref",
430
+ "remoteEtag",
431
+ "syncState",
432
+ "lastSyncedAt",
433
+ "createdAt",
434
+ "updatedAt"
435
+ ],
436
+ properties: {
437
+ id: { type: "string" },
438
+ provider: { type: "string", enum: ["google", "apple", "caldav"] },
439
+ connectionId: nullable({ type: "string" }),
440
+ calendarId: nullable({ type: "string" }),
441
+ remoteCalendarId: nullable({ type: "string" }),
442
+ remoteEventId: { type: "string" },
443
+ remoteUid: nullable({ type: "string" }),
444
+ recurrenceInstanceId: nullable({ type: "string" }),
445
+ isMasterRecurring: { type: "boolean" },
446
+ remoteHref: nullable({ type: "string" }),
447
+ remoteEtag: nullable({ type: "string" }),
448
+ syncState: {
449
+ type: "string",
450
+ enum: [
451
+ "pending_create",
452
+ "pending_update",
453
+ "pending_delete",
454
+ "synced",
455
+ "error",
456
+ "deleted"
457
+ ]
458
+ },
459
+ lastSyncedAt: nullable({ type: "string", format: "date-time" }),
460
+ createdAt: { type: "string", format: "date-time" },
461
+ updatedAt: { type: "string", format: "date-time" }
462
+ }
463
+ };
464
+ const calendarEventLink = {
465
+ type: "object",
466
+ additionalProperties: false,
467
+ required: [
468
+ "id",
469
+ "entityType",
470
+ "entityId",
471
+ "relationshipType",
472
+ "createdAt",
473
+ "updatedAt"
474
+ ],
475
+ properties: {
476
+ id: { type: "string" },
477
+ entityType: { $ref: "#/components/schemas/CrudEntityType" },
478
+ entityId: { type: "string" },
479
+ relationshipType: { type: "string" },
480
+ createdAt: { type: "string", format: "date-time" },
481
+ updatedAt: { type: "string", format: "date-time" }
482
+ }
483
+ };
484
+ const calendarEvent = {
485
+ type: "object",
486
+ additionalProperties: false,
487
+ required: [
488
+ "id",
489
+ "connectionId",
490
+ "calendarId",
491
+ "remoteId",
492
+ "ownership",
493
+ "originType",
494
+ "status",
495
+ "title",
496
+ "description",
497
+ "location",
498
+ "startAt",
499
+ "endAt",
500
+ "timezone",
501
+ "isAllDay",
502
+ "availability",
503
+ "eventType",
504
+ "categories",
505
+ "sourceMappings",
506
+ "links",
507
+ "remoteUpdatedAt",
508
+ "deletedAt",
509
+ "createdAt",
510
+ "updatedAt"
511
+ ],
512
+ properties: {
513
+ id: { type: "string" },
514
+ connectionId: nullable({ type: "string" }),
515
+ calendarId: nullable({ type: "string" }),
516
+ remoteId: nullable({ type: "string" }),
517
+ ownership: { type: "string", enum: ["external", "forge"] },
518
+ originType: {
519
+ type: "string",
520
+ enum: ["native", "google", "apple", "caldav", "derived"]
521
+ },
522
+ status: { type: "string", enum: ["confirmed", "tentative", "cancelled"] },
523
+ title: { type: "string" },
524
+ description: { type: "string" },
525
+ location: { type: "string" },
526
+ startAt: { type: "string", format: "date-time" },
527
+ endAt: { type: "string", format: "date-time" },
528
+ timezone: { type: "string" },
529
+ isAllDay: { type: "boolean" },
530
+ availability: { type: "string", enum: ["busy", "free"] },
531
+ eventType: { type: "string" },
532
+ categories: arrayOf({ type: "string" }),
533
+ sourceMappings: arrayOf({
534
+ $ref: "#/components/schemas/CalendarEventSource"
535
+ }),
536
+ links: arrayOf({ $ref: "#/components/schemas/CalendarEventLink" }),
537
+ remoteUpdatedAt: nullable({ type: "string", format: "date-time" }),
538
+ deletedAt: nullable({ type: "string", format: "date-time" }),
539
+ createdAt: { type: "string", format: "date-time" },
540
+ updatedAt: { type: "string", format: "date-time" }
541
+ }
542
+ };
543
+ const workBlockTemplate = {
544
+ type: "object",
545
+ additionalProperties: false,
546
+ required: [
547
+ "id",
548
+ "title",
549
+ "kind",
550
+ "color",
551
+ "timezone",
552
+ "weekDays",
553
+ "startMinute",
554
+ "endMinute",
555
+ "startsOn",
556
+ "endsOn",
557
+ "blockingState",
558
+ "createdAt",
559
+ "updatedAt"
560
+ ],
561
+ properties: {
562
+ id: { type: "string" },
563
+ title: { type: "string" },
564
+ kind: {
565
+ type: "string",
566
+ enum: [
567
+ "main_activity",
568
+ "secondary_activity",
569
+ "third_activity",
570
+ "rest",
571
+ "holiday",
572
+ "custom"
573
+ ]
574
+ },
575
+ color: { type: "string" },
576
+ timezone: { type: "string" },
577
+ weekDays: arrayOf({ type: "integer", minimum: 0, maximum: 6 }),
578
+ startMinute: { type: "integer" },
579
+ endMinute: { type: "integer" },
580
+ startsOn: nullable({ type: "string", format: "date" }),
581
+ endsOn: nullable({ type: "string", format: "date" }),
582
+ blockingState: { type: "string", enum: ["allowed", "blocked"] },
583
+ createdAt: { type: "string", format: "date-time" },
584
+ updatedAt: { type: "string", format: "date-time" }
585
+ }
586
+ };
587
+ const workBlockInstance = {
588
+ type: "object",
589
+ additionalProperties: false,
590
+ required: [
591
+ "id",
592
+ "templateId",
593
+ "dateKey",
594
+ "startAt",
595
+ "endAt",
596
+ "title",
597
+ "kind",
598
+ "color",
599
+ "blockingState",
600
+ "calendarEventId",
601
+ "createdAt",
602
+ "updatedAt"
603
+ ],
604
+ properties: {
605
+ id: { type: "string" },
606
+ templateId: { type: "string" },
607
+ dateKey: { type: "string", format: "date" },
608
+ startAt: { type: "string", format: "date-time" },
609
+ endAt: { type: "string", format: "date-time" },
610
+ title: { type: "string" },
611
+ kind: {
612
+ type: "string",
613
+ enum: [
614
+ "main_activity",
615
+ "secondary_activity",
616
+ "third_activity",
617
+ "rest",
618
+ "holiday",
619
+ "custom"
620
+ ]
621
+ },
622
+ color: { type: "string" },
623
+ blockingState: { type: "string", enum: ["allowed", "blocked"] },
624
+ calendarEventId: nullable({ type: "string" }),
625
+ createdAt: { type: "string", format: "date-time" },
626
+ updatedAt: { type: "string", format: "date-time" }
627
+ }
628
+ };
629
+ const taskTimebox = {
630
+ type: "object",
631
+ additionalProperties: false,
632
+ required: [
633
+ "id",
634
+ "taskId",
635
+ "projectId",
636
+ "connectionId",
637
+ "calendarId",
638
+ "remoteEventId",
639
+ "linkedTaskRunId",
640
+ "status",
641
+ "source",
642
+ "title",
643
+ "startsAt",
644
+ "endsAt",
645
+ "overrideReason",
646
+ "createdAt",
647
+ "updatedAt"
648
+ ],
649
+ properties: {
650
+ id: { type: "string" },
651
+ taskId: { type: "string" },
652
+ projectId: nullable({ type: "string" }),
653
+ connectionId: nullable({ type: "string" }),
654
+ calendarId: nullable({ type: "string" }),
655
+ remoteEventId: nullable({ type: "string" }),
656
+ linkedTaskRunId: nullable({ type: "string" }),
657
+ status: {
658
+ type: "string",
659
+ enum: ["planned", "active", "completed", "cancelled"]
660
+ },
661
+ source: { type: "string", enum: ["manual", "suggested", "live_run"] },
662
+ title: { type: "string" },
663
+ startsAt: { type: "string", format: "date-time" },
664
+ endsAt: { type: "string", format: "date-time" },
665
+ overrideReason: nullable({ type: "string" }),
666
+ createdAt: { type: "string", format: "date-time" },
667
+ updatedAt: { type: "string", format: "date-time" }
668
+ }
669
+ };
670
+ const calendarOverviewPayload = {
671
+ type: "object",
672
+ additionalProperties: false,
673
+ required: [
674
+ "generatedAt",
675
+ "providers",
676
+ "connections",
677
+ "calendars",
678
+ "events",
679
+ "workBlockTemplates",
680
+ "workBlockInstances",
681
+ "timeboxes"
682
+ ],
683
+ properties: {
684
+ generatedAt: { type: "string", format: "date-time" },
685
+ providers: arrayOf({
686
+ type: "object",
687
+ additionalProperties: false,
688
+ required: [
689
+ "provider",
690
+ "label",
691
+ "supportsDedicatedForgeCalendar",
692
+ "connectionHelp"
693
+ ],
694
+ properties: {
695
+ provider: { type: "string", enum: ["google", "apple", "caldav"] },
696
+ label: { type: "string" },
697
+ supportsDedicatedForgeCalendar: { type: "boolean" },
698
+ connectionHelp: { type: "string" }
699
+ }
700
+ }),
701
+ connections: arrayOf({ $ref: "#/components/schemas/CalendarConnection" }),
702
+ calendars: arrayOf({ $ref: "#/components/schemas/CalendarResource" }),
703
+ events: arrayOf({ $ref: "#/components/schemas/CalendarEvent" }),
704
+ workBlockTemplates: arrayOf({
705
+ $ref: "#/components/schemas/WorkBlockTemplate"
706
+ }),
707
+ workBlockInstances: arrayOf({
708
+ $ref: "#/components/schemas/WorkBlockInstance"
709
+ }),
710
+ timeboxes: arrayOf({ $ref: "#/components/schemas/TaskTimebox" })
711
+ }
712
+ };
713
+ const habitCheckIn = {
714
+ type: "object",
715
+ additionalProperties: false,
716
+ required: [
717
+ "id",
718
+ "habitId",
719
+ "dateKey",
720
+ "status",
721
+ "note",
722
+ "deltaXp",
723
+ "createdAt",
724
+ "updatedAt"
725
+ ],
726
+ properties: {
727
+ id: { type: "string" },
728
+ habitId: { type: "string" },
729
+ dateKey: { type: "string", format: "date" },
730
+ status: { type: "string", enum: ["done", "missed"] },
731
+ note: { type: "string" },
732
+ deltaXp: { type: "integer" },
733
+ createdAt: { type: "string", format: "date-time" },
734
+ updatedAt: { type: "string", format: "date-time" }
735
+ }
736
+ };
737
+ const habit = {
738
+ type: "object",
739
+ additionalProperties: false,
740
+ required: [
741
+ "id",
742
+ "title",
743
+ "description",
744
+ "status",
745
+ "polarity",
746
+ "frequency",
747
+ "targetCount",
748
+ "weekDays",
749
+ "linkedGoalIds",
750
+ "linkedProjectIds",
751
+ "linkedTaskIds",
752
+ "linkedValueIds",
753
+ "linkedPatternIds",
754
+ "linkedBehaviorIds",
755
+ "linkedBeliefIds",
756
+ "linkedModeIds",
757
+ "linkedReportIds",
758
+ "linkedBehaviorId",
759
+ "linkedBehaviorTitle",
760
+ "linkedBehaviorTitles",
761
+ "rewardXp",
762
+ "penaltyXp",
763
+ "createdAt",
764
+ "updatedAt",
765
+ "lastCheckInAt",
766
+ "lastCheckInStatus",
767
+ "streakCount",
768
+ "completionRate",
769
+ "dueToday",
770
+ "checkIns"
771
+ ],
772
+ properties: {
773
+ id: { type: "string" },
774
+ title: { type: "string" },
775
+ description: { type: "string" },
776
+ status: { type: "string", enum: ["active", "paused", "archived"] },
777
+ polarity: { type: "string", enum: ["positive", "negative"] },
778
+ frequency: { type: "string", enum: ["daily", "weekly"] },
779
+ targetCount: { type: "integer" },
780
+ weekDays: arrayOf({ type: "integer" }),
781
+ linkedGoalIds: arrayOf({ type: "string" }),
782
+ linkedProjectIds: arrayOf({ type: "string" }),
783
+ linkedTaskIds: arrayOf({ type: "string" }),
784
+ linkedValueIds: arrayOf({ type: "string" }),
785
+ linkedPatternIds: arrayOf({ type: "string" }),
786
+ linkedBehaviorIds: arrayOf({ type: "string" }),
787
+ linkedBeliefIds: arrayOf({ type: "string" }),
788
+ linkedModeIds: arrayOf({ type: "string" }),
789
+ linkedReportIds: arrayOf({ type: "string" }),
790
+ linkedBehaviorId: nullable({ type: "string" }),
791
+ linkedBehaviorTitle: nullable({ type: "string" }),
792
+ linkedBehaviorTitles: arrayOf({ type: "string" }),
793
+ rewardXp: { type: "integer" },
794
+ penaltyXp: { type: "integer" },
795
+ createdAt: { type: "string", format: "date-time" },
796
+ updatedAt: { type: "string", format: "date-time" },
797
+ lastCheckInAt: nullable({ type: "string", format: "date-time" }),
798
+ lastCheckInStatus: nullable({ type: "string", enum: ["done", "missed"] }),
799
+ streakCount: { type: "integer" },
800
+ completionRate: { type: "number" },
801
+ dueToday: { type: "boolean" },
802
+ checkIns: arrayOf({ $ref: "#/components/schemas/HabitCheckIn" })
243
803
  }
244
804
  };
245
805
  const activityEvent = {
246
806
  type: "object",
247
807
  additionalProperties: false,
248
- required: ["id", "entityType", "entityId", "eventType", "title", "description", "actor", "source", "metadata", "createdAt"],
808
+ required: [
809
+ "id",
810
+ "entityType",
811
+ "entityId",
812
+ "eventType",
813
+ "title",
814
+ "description",
815
+ "actor",
816
+ "source",
817
+ "metadata",
818
+ "createdAt"
819
+ ],
249
820
  properties: {
250
821
  id: { type: "string" },
251
822
  entityType: {
252
823
  type: "string",
253
824
  enum: [
254
825
  "task",
826
+ "habit",
255
827
  "goal",
256
828
  "project",
257
829
  "domain",
@@ -284,7 +856,12 @@ export function buildOpenApiDocument() {
284
856
  metadata: {
285
857
  type: "object",
286
858
  additionalProperties: {
287
- anyOf: [{ type: "string" }, { type: "number" }, { type: "boolean" }, { type: "null" }]
859
+ anyOf: [
860
+ { type: "string" },
861
+ { type: "number" },
862
+ { type: "boolean" },
863
+ { type: "null" }
864
+ ]
288
865
  }
289
866
  },
290
867
  createdAt: { type: "string", format: "date-time" }
@@ -293,7 +870,18 @@ export function buildOpenApiDocument() {
293
870
  const gamificationProfile = {
294
871
  type: "object",
295
872
  additionalProperties: false,
296
- required: ["totalXp", "level", "currentLevelXp", "nextLevelXp", "weeklyXp", "streakDays", "comboMultiplier", "momentumScore", "topGoalId", "topGoalTitle"],
873
+ required: [
874
+ "totalXp",
875
+ "level",
876
+ "currentLevelXp",
877
+ "nextLevelXp",
878
+ "weeklyXp",
879
+ "streakDays",
880
+ "comboMultiplier",
881
+ "momentumScore",
882
+ "topGoalId",
883
+ "topGoalTitle"
884
+ ],
297
885
  properties: {
298
886
  totalXp: { type: "integer" },
299
887
  level: { type: "integer" },
@@ -320,7 +908,18 @@ export function buildOpenApiDocument() {
320
908
  const note = {
321
909
  type: "object",
322
910
  additionalProperties: false,
323
- required: ["id", "contentMarkdown", "contentPlain", "author", "source", "createdAt", "updatedAt", "links"],
911
+ required: [
912
+ "id",
913
+ "contentMarkdown",
914
+ "contentPlain",
915
+ "author",
916
+ "source",
917
+ "createdAt",
918
+ "updatedAt",
919
+ "links",
920
+ "tags",
921
+ "destroyAt"
922
+ ],
324
923
  properties: {
325
924
  id: { type: "string" },
326
925
  contentMarkdown: { type: "string" },
@@ -329,7 +928,9 @@ export function buildOpenApiDocument() {
329
928
  source: { type: "string", enum: ["ui", "openclaw", "agent", "system"] },
330
929
  createdAt: { type: "string", format: "date-time" },
331
930
  updatedAt: { type: "string", format: "date-time" },
332
- links: arrayOf({ $ref: "#/components/schemas/NoteLink" })
931
+ links: arrayOf({ $ref: "#/components/schemas/NoteLink" }),
932
+ tags: arrayOf({ type: "string" }),
933
+ destroyAt: nullable({ type: "string", format: "date-time" })
333
934
  }
334
935
  };
335
936
  const noteSummary = {
@@ -349,7 +950,15 @@ export function buildOpenApiDocument() {
349
950
  const achievementSignal = {
350
951
  type: "object",
351
952
  additionalProperties: false,
352
- required: ["id", "title", "summary", "tier", "progressLabel", "unlocked", "unlockedAt"],
953
+ required: [
954
+ "id",
955
+ "title",
956
+ "summary",
957
+ "tier",
958
+ "progressLabel",
959
+ "unlocked",
960
+ "unlockedAt"
961
+ ],
353
962
  properties: {
354
963
  id: { type: "string" },
355
964
  title: { type: "string" },
@@ -363,7 +972,16 @@ export function buildOpenApiDocument() {
363
972
  const milestoneReward = {
364
973
  type: "object",
365
974
  additionalProperties: false,
366
- required: ["id", "title", "summary", "rewardLabel", "progressLabel", "current", "target", "completed"],
975
+ required: [
976
+ "id",
977
+ "title",
978
+ "summary",
979
+ "rewardLabel",
980
+ "progressLabel",
981
+ "current",
982
+ "target",
983
+ "completed"
984
+ ],
367
985
  properties: {
368
986
  id: { type: "string" },
369
987
  title: { type: "string" },
@@ -378,12 +996,35 @@ export function buildOpenApiDocument() {
378
996
  const dashboardPayload = {
379
997
  type: "object",
380
998
  additionalProperties: false,
381
- required: ["stats", "goals", "projects", "tasks", "tags", "suggestedTags", "owners", "executionBuckets", "gamification", "achievements", "milestoneRewards", "recentActivity", "notesSummaryByEntity"],
999
+ required: [
1000
+ "stats",
1001
+ "goals",
1002
+ "projects",
1003
+ "tasks",
1004
+ "habits",
1005
+ "tags",
1006
+ "suggestedTags",
1007
+ "owners",
1008
+ "executionBuckets",
1009
+ "gamification",
1010
+ "achievements",
1011
+ "milestoneRewards",
1012
+ "recentActivity",
1013
+ "notesSummaryByEntity"
1014
+ ],
382
1015
  properties: {
383
1016
  stats: {
384
1017
  type: "object",
385
1018
  additionalProperties: false,
386
- required: ["totalPoints", "completedThisWeek", "activeGoals", "alignmentScore", "focusTasks", "overdueTasks", "dueThisWeek"],
1019
+ required: [
1020
+ "totalPoints",
1021
+ "completedThisWeek",
1022
+ "activeGoals",
1023
+ "alignmentScore",
1024
+ "focusTasks",
1025
+ "overdueTasks",
1026
+ "dueThisWeek"
1027
+ ],
387
1028
  properties: {
388
1029
  totalPoints: { type: "integer" },
389
1030
  completedThisWeek: { type: "integer" },
@@ -397,6 +1038,7 @@ export function buildOpenApiDocument() {
397
1038
  goals: arrayOf({ $ref: "#/components/schemas/DashboardGoal" }),
398
1039
  projects: arrayOf({ $ref: "#/components/schemas/ProjectSummary" }),
399
1040
  tasks: arrayOf({ $ref: "#/components/schemas/Task" }),
1041
+ habits: arrayOf({ $ref: "#/components/schemas/Habit" }),
400
1042
  tags: arrayOf({ $ref: "#/components/schemas/Tag" }),
401
1043
  suggestedTags: arrayOf({ $ref: "#/components/schemas/Tag" }),
402
1044
  owners: arrayOf({ type: "string" }),
@@ -405,30 +1047,60 @@ export function buildOpenApiDocument() {
405
1047
  additionalProperties: false,
406
1048
  required: ["id", "label", "summary", "tone", "tasks"],
407
1049
  properties: {
408
- id: { type: "string", enum: ["overdue", "due_soon", "focus_now", "recently_completed"] },
1050
+ id: {
1051
+ type: "string",
1052
+ enum: ["overdue", "due_soon", "focus_now", "recently_completed"]
1053
+ },
409
1054
  label: { type: "string" },
410
1055
  summary: { type: "string" },
411
- tone: { type: "string", enum: ["urgent", "accent", "neutral", "success"] },
1056
+ tone: {
1057
+ type: "string",
1058
+ enum: ["urgent", "accent", "neutral", "success"]
1059
+ },
412
1060
  tasks: arrayOf({ $ref: "#/components/schemas/Task" })
413
1061
  }
414
1062
  }),
415
1063
  gamification: { $ref: "#/components/schemas/GamificationProfile" },
416
1064
  achievements: arrayOf({ $ref: "#/components/schemas/AchievementSignal" }),
417
- milestoneRewards: arrayOf({ $ref: "#/components/schemas/MilestoneReward" }),
1065
+ milestoneRewards: arrayOf({
1066
+ $ref: "#/components/schemas/MilestoneReward"
1067
+ }),
418
1068
  recentActivity: arrayOf({ $ref: "#/components/schemas/ActivityEvent" }),
419
- notesSummaryByEntity: { $ref: "#/components/schemas/NotesSummaryByEntity" }
1069
+ notesSummaryByEntity: {
1070
+ $ref: "#/components/schemas/NotesSummaryByEntity"
1071
+ }
420
1072
  }
421
1073
  };
422
1074
  const overviewContext = {
423
1075
  type: "object",
424
1076
  additionalProperties: false,
425
- required: ["generatedAt", "strategicHeader", "projects", "activeGoals", "topTasks", "recentEvidence", "achievements", "domainBalance", "neglectedGoals"],
1077
+ required: [
1078
+ "generatedAt",
1079
+ "strategicHeader",
1080
+ "projects",
1081
+ "activeGoals",
1082
+ "topTasks",
1083
+ "dueHabits",
1084
+ "recentEvidence",
1085
+ "achievements",
1086
+ "domainBalance",
1087
+ "neglectedGoals"
1088
+ ],
426
1089
  properties: {
427
1090
  generatedAt: { type: "string", format: "date-time" },
428
1091
  strategicHeader: {
429
1092
  type: "object",
430
1093
  additionalProperties: false,
431
- required: ["streakDays", "level", "totalXp", "currentLevelXp", "nextLevelXp", "momentumScore", "focusTasks", "overdueTasks"],
1094
+ required: [
1095
+ "streakDays",
1096
+ "level",
1097
+ "totalXp",
1098
+ "currentLevelXp",
1099
+ "nextLevelXp",
1100
+ "momentumScore",
1101
+ "focusTasks",
1102
+ "overdueTasks"
1103
+ ],
432
1104
  properties: {
433
1105
  streakDays: { type: "integer" },
434
1106
  level: { type: "integer" },
@@ -443,12 +1115,21 @@ export function buildOpenApiDocument() {
443
1115
  projects: arrayOf({ $ref: "#/components/schemas/ProjectSummary" }),
444
1116
  activeGoals: arrayOf({ $ref: "#/components/schemas/DashboardGoal" }),
445
1117
  topTasks: arrayOf({ $ref: "#/components/schemas/Task" }),
1118
+ dueHabits: arrayOf({ $ref: "#/components/schemas/Habit" }),
446
1119
  recentEvidence: arrayOf({ $ref: "#/components/schemas/ActivityEvent" }),
447
1120
  achievements: arrayOf({ $ref: "#/components/schemas/AchievementSignal" }),
448
1121
  domainBalance: arrayOf({
449
1122
  type: "object",
450
1123
  additionalProperties: false,
451
- required: ["tagId", "label", "color", "goalCount", "activeTaskCount", "completedPoints", "momentumLabel"],
1124
+ required: [
1125
+ "tagId",
1126
+ "label",
1127
+ "color",
1128
+ "goalCount",
1129
+ "activeTaskCount",
1130
+ "completedPoints",
1131
+ "momentumLabel"
1132
+ ],
452
1133
  properties: {
453
1134
  tagId: { type: "string" },
454
1135
  label: { type: "string" },
@@ -475,7 +1156,16 @@ export function buildOpenApiDocument() {
475
1156
  const todayContext = {
476
1157
  type: "object",
477
1158
  additionalProperties: false,
478
- required: ["generatedAt", "directive", "timeline", "dailyQuests", "milestoneRewards", "momentum"],
1159
+ required: [
1160
+ "generatedAt",
1161
+ "directive",
1162
+ "timeline",
1163
+ "dueHabits",
1164
+ "dailyQuests",
1165
+ "milestoneRewards",
1166
+ "recentHabitRewards",
1167
+ "momentum"
1168
+ ],
479
1169
  properties: {
480
1170
  generatedAt: { type: "string", format: "date-time" },
481
1171
  directive: {
@@ -494,15 +1184,26 @@ export function buildOpenApiDocument() {
494
1184
  additionalProperties: false,
495
1185
  required: ["id", "label", "tasks"],
496
1186
  properties: {
497
- id: { type: "string", enum: ["completed", "active", "upcoming", "deferred"] },
1187
+ id: {
1188
+ type: "string",
1189
+ enum: ["completed", "active", "upcoming", "deferred"]
1190
+ },
498
1191
  label: { type: "string" },
499
1192
  tasks: arrayOf({ $ref: "#/components/schemas/Task" })
500
1193
  }
501
1194
  }),
1195
+ dueHabits: arrayOf({ $ref: "#/components/schemas/Habit" }),
502
1196
  dailyQuests: arrayOf({
503
1197
  type: "object",
504
1198
  additionalProperties: false,
505
- required: ["id", "title", "summary", "rewardXp", "progressLabel", "completed"],
1199
+ required: [
1200
+ "id",
1201
+ "title",
1202
+ "summary",
1203
+ "rewardXp",
1204
+ "progressLabel",
1205
+ "completed"
1206
+ ],
506
1207
  properties: {
507
1208
  id: { type: "string" },
508
1209
  title: { type: "string" },
@@ -512,7 +1213,12 @@ export function buildOpenApiDocument() {
512
1213
  completed: { type: "boolean" }
513
1214
  }
514
1215
  }),
515
- milestoneRewards: arrayOf({ $ref: "#/components/schemas/MilestoneReward" }),
1216
+ milestoneRewards: arrayOf({
1217
+ $ref: "#/components/schemas/MilestoneReward"
1218
+ }),
1219
+ recentHabitRewards: arrayOf({
1220
+ $ref: "#/components/schemas/RewardLedgerEvent"
1221
+ }),
516
1222
  momentum: {
517
1223
  type: "object",
518
1224
  additionalProperties: false,
@@ -528,7 +1234,13 @@ export function buildOpenApiDocument() {
528
1234
  const riskContext = {
529
1235
  type: "object",
530
1236
  additionalProperties: false,
531
- required: ["generatedAt", "overdueTasks", "blockedTasks", "neglectedGoals", "summary"],
1237
+ required: [
1238
+ "generatedAt",
1239
+ "overdueTasks",
1240
+ "blockedTasks",
1241
+ "neglectedGoals",
1242
+ "summary"
1243
+ ],
532
1244
  properties: {
533
1245
  generatedAt: { type: "string", format: "date-time" },
534
1246
  overdueTasks: arrayOf({ $ref: "#/components/schemas/Task" }),
@@ -550,7 +1262,21 @@ export function buildOpenApiDocument() {
550
1262
  const forgeSnapshot = {
551
1263
  type: "object",
552
1264
  additionalProperties: false,
553
- required: ["meta", "metrics", "dashboard", "overview", "today", "risk", "goals", "projects", "tags", "tasks", "activeTaskRuns", "activity"],
1265
+ required: [
1266
+ "meta",
1267
+ "metrics",
1268
+ "dashboard",
1269
+ "overview",
1270
+ "today",
1271
+ "risk",
1272
+ "goals",
1273
+ "projects",
1274
+ "tags",
1275
+ "tasks",
1276
+ "habits",
1277
+ "activeTaskRuns",
1278
+ "activity"
1279
+ ],
554
1280
  properties: {
555
1281
  meta: {
556
1282
  type: "object",
@@ -573,6 +1299,7 @@ export function buildOpenApiDocument() {
573
1299
  projects: arrayOf({ $ref: "#/components/schemas/ProjectSummary" }),
574
1300
  tags: arrayOf({ $ref: "#/components/schemas/Tag" }),
575
1301
  tasks: arrayOf({ $ref: "#/components/schemas/Task" }),
1302
+ habits: arrayOf({ $ref: "#/components/schemas/Habit" }),
576
1303
  activeTaskRuns: arrayOf({ $ref: "#/components/schemas/TaskRun" }),
577
1304
  activity: arrayOf({ $ref: "#/components/schemas/ActivityEvent" })
578
1305
  }
@@ -580,7 +1307,15 @@ export function buildOpenApiDocument() {
580
1307
  const taskContextPayload = {
581
1308
  type: "object",
582
1309
  additionalProperties: false,
583
- required: ["task", "goal", "project", "activeTaskRun", "taskRuns", "activity", "notesSummaryByEntity"],
1310
+ required: [
1311
+ "task",
1312
+ "goal",
1313
+ "project",
1314
+ "activeTaskRun",
1315
+ "taskRuns",
1316
+ "activity",
1317
+ "notesSummaryByEntity"
1318
+ ],
584
1319
  properties: {
585
1320
  task: { $ref: "#/components/schemas/Task" },
586
1321
  goal: nullable({ $ref: "#/components/schemas/Goal" }),
@@ -588,7 +1323,9 @@ export function buildOpenApiDocument() {
588
1323
  activeTaskRun: nullable({ $ref: "#/components/schemas/TaskRun" }),
589
1324
  taskRuns: arrayOf({ $ref: "#/components/schemas/TaskRun" }),
590
1325
  activity: arrayOf({ $ref: "#/components/schemas/ActivityEvent" }),
591
- notesSummaryByEntity: { $ref: "#/components/schemas/NotesSummaryByEntity" }
1326
+ notesSummaryByEntity: {
1327
+ $ref: "#/components/schemas/NotesSummaryByEntity"
1328
+ }
592
1329
  }
593
1330
  };
594
1331
  const projectBoardPayload = {
@@ -600,13 +1337,25 @@ export function buildOpenApiDocument() {
600
1337
  goal: { $ref: "#/components/schemas/Goal" },
601
1338
  tasks: arrayOf({ $ref: "#/components/schemas/Task" }),
602
1339
  activity: arrayOf({ $ref: "#/components/schemas/ActivityEvent" }),
603
- notesSummaryByEntity: { $ref: "#/components/schemas/NotesSummaryByEntity" }
1340
+ notesSummaryByEntity: {
1341
+ $ref: "#/components/schemas/NotesSummaryByEntity"
1342
+ }
604
1343
  }
605
1344
  };
606
1345
  const insightsPayload = {
607
1346
  type: "object",
608
1347
  additionalProperties: false,
609
- required: ["generatedAt", "status", "momentumHeatmap", "executionTrends", "domainBalance", "coaching", "evidenceDigest", "feed", "openCount"],
1348
+ required: [
1349
+ "generatedAt",
1350
+ "status",
1351
+ "momentumHeatmap",
1352
+ "executionTrends",
1353
+ "domainBalance",
1354
+ "coaching",
1355
+ "evidenceDigest",
1356
+ "feed",
1357
+ "openCount"
1358
+ ],
610
1359
  properties: {
611
1360
  generatedAt: { type: "string", format: "date-time" },
612
1361
  status: {
@@ -671,10 +1420,25 @@ export function buildOpenApiDocument() {
671
1420
  const weeklyReviewPayload = {
672
1421
  type: "object",
673
1422
  additionalProperties: false,
674
- required: ["generatedAt", "windowLabel", "momentumSummary", "chart", "wins", "calibration", "reward"],
1423
+ required: [
1424
+ "generatedAt",
1425
+ "windowLabel",
1426
+ "weekKey",
1427
+ "weekStartDate",
1428
+ "weekEndDate",
1429
+ "momentumSummary",
1430
+ "chart",
1431
+ "wins",
1432
+ "calibration",
1433
+ "reward",
1434
+ "completion"
1435
+ ],
675
1436
  properties: {
676
1437
  generatedAt: { type: "string", format: "date-time" },
677
1438
  windowLabel: { type: "string" },
1439
+ weekKey: { type: "string" },
1440
+ weekStartDate: { type: "string" },
1441
+ weekEndDate: { type: "string" },
678
1442
  momentumSummary: {
679
1443
  type: "object",
680
1444
  additionalProperties: false,
@@ -727,13 +1491,39 @@ export function buildOpenApiDocument() {
727
1491
  summary: { type: "string" },
728
1492
  rewardXp: { type: "integer" }
729
1493
  }
1494
+ },
1495
+ completion: {
1496
+ type: "object",
1497
+ additionalProperties: false,
1498
+ required: ["finalized", "finalizedAt", "finalizedBy"],
1499
+ properties: {
1500
+ finalized: { type: "boolean" },
1501
+ finalizedAt: nullable({ type: "string", format: "date-time" }),
1502
+ finalizedBy: nullable({ type: "string" })
1503
+ }
730
1504
  }
731
1505
  }
732
1506
  };
733
1507
  const agentTokenSummary = {
734
1508
  type: "object",
735
1509
  additionalProperties: false,
736
- required: ["id", "label", "tokenPrefix", "scopes", "agentId", "agentLabel", "trustLevel", "autonomyMode", "approvalMode", "description", "lastUsedAt", "revokedAt", "createdAt", "updatedAt", "status"],
1510
+ required: [
1511
+ "id",
1512
+ "label",
1513
+ "tokenPrefix",
1514
+ "scopes",
1515
+ "agentId",
1516
+ "agentLabel",
1517
+ "trustLevel",
1518
+ "autonomyMode",
1519
+ "approvalMode",
1520
+ "description",
1521
+ "lastUsedAt",
1522
+ "revokedAt",
1523
+ "createdAt",
1524
+ "updatedAt",
1525
+ "status"
1526
+ ],
737
1527
  properties: {
738
1528
  id: { type: "string" },
739
1529
  label: { type: "string" },
@@ -741,9 +1531,18 @@ export function buildOpenApiDocument() {
741
1531
  scopes: arrayOf({ type: "string" }),
742
1532
  agentId: nullable({ type: "string" }),
743
1533
  agentLabel: nullable({ type: "string" }),
744
- trustLevel: { type: "string", enum: ["standard", "trusted", "autonomous"] },
745
- autonomyMode: { type: "string", enum: ["approval_required", "scoped_write", "autonomous"] },
746
- approvalMode: { type: "string", enum: ["approval_by_default", "high_impact_only", "none"] },
1534
+ trustLevel: {
1535
+ type: "string",
1536
+ enum: ["standard", "trusted", "autonomous"]
1537
+ },
1538
+ autonomyMode: {
1539
+ type: "string",
1540
+ enum: ["approval_required", "scoped_write", "autonomous"]
1541
+ },
1542
+ approvalMode: {
1543
+ type: "string",
1544
+ enum: ["approval_by_default", "high_impact_only", "none"]
1545
+ },
747
1546
  description: { type: "string" },
748
1547
  lastUsedAt: nullable({ type: "string", format: "date-time" }),
749
1548
  revokedAt: nullable({ type: "string", format: "date-time" }),
@@ -758,7 +1557,10 @@ export function buildOpenApiDocument() {
758
1557
  required: ["maxActiveTasks", "timeAccountingMode"],
759
1558
  properties: {
760
1559
  maxActiveTasks: { type: "integer", minimum: 1, maximum: 8 },
761
- timeAccountingMode: { type: "string", enum: ["split", "parallel", "primary_only"] }
1560
+ timeAccountingMode: {
1561
+ type: "string",
1562
+ enum: ["split", "parallel", "primary_only"]
1563
+ }
762
1564
  }
763
1565
  };
764
1566
  const taskRunClaimInput = {
@@ -767,10 +1569,24 @@ export function buildOpenApiDocument() {
767
1569
  required: ["actor"],
768
1570
  properties: {
769
1571
  actor: { type: "string" },
770
- timerMode: { type: "string", enum: ["planned", "unlimited"], default: "unlimited" },
771
- plannedDurationSeconds: nullable({ type: "integer", minimum: 60, maximum: 86400 }),
1572
+ timerMode: {
1573
+ type: "string",
1574
+ enum: ["planned", "unlimited"],
1575
+ default: "unlimited"
1576
+ },
1577
+ plannedDurationSeconds: nullable({
1578
+ type: "integer",
1579
+ minimum: 60,
1580
+ maximum: 86400
1581
+ }),
1582
+ overrideReason: nullable({ type: "string" }),
772
1583
  isCurrent: { type: "boolean", default: true },
773
- leaseTtlSeconds: { type: "integer", minimum: 1, maximum: 14400, default: 900 },
1584
+ leaseTtlSeconds: {
1585
+ type: "integer",
1586
+ minimum: 1,
1587
+ maximum: 14400,
1588
+ default: 900
1589
+ },
774
1590
  note: { type: "string", default: "" }
775
1591
  }
776
1592
  };
@@ -779,7 +1595,12 @@ export function buildOpenApiDocument() {
779
1595
  additionalProperties: false,
780
1596
  properties: {
781
1597
  actor: { type: "string" },
782
- leaseTtlSeconds: { type: "integer", minimum: 1, maximum: 14400, default: 900 },
1598
+ leaseTtlSeconds: {
1599
+ type: "integer",
1600
+ minimum: 1,
1601
+ maximum: 14400,
1602
+ default: 900
1603
+ },
783
1604
  note: { type: "string" }
784
1605
  }
785
1606
  };
@@ -808,6 +1629,65 @@ export function buildOpenApiDocument() {
808
1629
  actor: { type: "string" }
809
1630
  }
810
1631
  };
1632
+ const workAdjustment = {
1633
+ type: "object",
1634
+ additionalProperties: false,
1635
+ required: [
1636
+ "id",
1637
+ "entityType",
1638
+ "entityId",
1639
+ "requestedDeltaMinutes",
1640
+ "appliedDeltaMinutes",
1641
+ "note",
1642
+ "actor",
1643
+ "source",
1644
+ "createdAt"
1645
+ ],
1646
+ properties: {
1647
+ id: { type: "string" },
1648
+ entityType: { type: "string", enum: ["task", "project"] },
1649
+ entityId: { type: "string" },
1650
+ requestedDeltaMinutes: { type: "integer" },
1651
+ appliedDeltaMinutes: { type: "integer" },
1652
+ note: { type: "string" },
1653
+ actor: nullable({ type: "string" }),
1654
+ source: { type: "string", enum: ["ui", "openclaw", "agent", "system"] },
1655
+ createdAt: { type: "string", format: "date-time" }
1656
+ }
1657
+ };
1658
+ const workAdjustmentTargetSummary = {
1659
+ type: "object",
1660
+ additionalProperties: false,
1661
+ required: ["entityType", "entityId", "title", "time"],
1662
+ properties: {
1663
+ entityType: { type: "string", enum: ["task", "project"] },
1664
+ entityId: { type: "string" },
1665
+ title: { type: "string" },
1666
+ time: { $ref: "#/components/schemas/TaskTimeSummary" }
1667
+ }
1668
+ };
1669
+ const workAdjustmentInput = {
1670
+ type: "object",
1671
+ additionalProperties: false,
1672
+ required: ["entityType", "entityId", "deltaMinutes"],
1673
+ properties: {
1674
+ entityType: { type: "string", enum: ["task", "project"] },
1675
+ entityId: { type: "string" },
1676
+ deltaMinutes: { type: "integer" },
1677
+ note: { type: "string", default: "" }
1678
+ }
1679
+ };
1680
+ const workAdjustmentResult = {
1681
+ type: "object",
1682
+ additionalProperties: false,
1683
+ required: ["adjustment", "target", "reward", "metrics"],
1684
+ properties: {
1685
+ adjustment: { $ref: "#/components/schemas/WorkAdjustment" },
1686
+ target: { $ref: "#/components/schemas/WorkAdjustmentTargetSummary" },
1687
+ reward: nullable({ $ref: "#/components/schemas/RewardLedgerEvent" }),
1688
+ metrics: { $ref: "#/components/schemas/XpMetricsPayload" }
1689
+ }
1690
+ };
811
1691
  const settingsUpdateInput = {
812
1692
  type: "object",
813
1693
  additionalProperties: false,
@@ -835,24 +1715,51 @@ export function buildOpenApiDocument() {
835
1715
  additionalProperties: false,
836
1716
  properties: {
837
1717
  maxActiveTasks: { type: "integer", minimum: 1, maximum: 8 },
838
- timeAccountingMode: { type: "string", enum: ["split", "parallel", "primary_only"] }
1718
+ timeAccountingMode: {
1719
+ type: "string",
1720
+ enum: ["split", "parallel", "primary_only"]
1721
+ }
839
1722
  }
840
1723
  },
841
- themePreference: { type: "string", enum: ["obsidian", "solar", "system"] },
1724
+ themePreference: {
1725
+ type: "string",
1726
+ enum: ["obsidian", "solar", "system"]
1727
+ },
842
1728
  localePreference: { type: "string", enum: ["en", "fr"] }
843
1729
  }
844
1730
  };
845
1731
  const agentIdentity = {
846
1732
  type: "object",
847
1733
  additionalProperties: false,
848
- required: ["id", "label", "agentType", "trustLevel", "autonomyMode", "approvalMode", "description", "tokenCount", "activeTokenCount", "createdAt", "updatedAt"],
1734
+ required: [
1735
+ "id",
1736
+ "label",
1737
+ "agentType",
1738
+ "trustLevel",
1739
+ "autonomyMode",
1740
+ "approvalMode",
1741
+ "description",
1742
+ "tokenCount",
1743
+ "activeTokenCount",
1744
+ "createdAt",
1745
+ "updatedAt"
1746
+ ],
849
1747
  properties: {
850
1748
  id: { type: "string" },
851
1749
  label: { type: "string" },
852
1750
  agentType: { type: "string" },
853
- trustLevel: { type: "string", enum: ["standard", "trusted", "autonomous"] },
854
- autonomyMode: { type: "string", enum: ["approval_required", "scoped_write", "autonomous"] },
855
- approvalMode: { type: "string", enum: ["approval_by_default", "high_impact_only", "none"] },
1751
+ trustLevel: {
1752
+ type: "string",
1753
+ enum: ["standard", "trusted", "autonomous"]
1754
+ },
1755
+ autonomyMode: {
1756
+ type: "string",
1757
+ enum: ["approval_required", "scoped_write", "autonomous"]
1758
+ },
1759
+ approvalMode: {
1760
+ type: "string",
1761
+ enum: ["approval_by_default", "high_impact_only", "none"]
1762
+ },
856
1763
  description: { type: "string" },
857
1764
  tokenCount: { type: "integer" },
858
1765
  activeTokenCount: { type: "integer" },
@@ -863,14 +1770,39 @@ export function buildOpenApiDocument() {
863
1770
  const insight = {
864
1771
  type: "object",
865
1772
  additionalProperties: false,
866
- required: ["id", "originType", "originAgentId", "originLabel", "visibility", "status", "entityType", "entityId", "timeframeLabel", "title", "summary", "recommendation", "rationale", "confidence", "ctaLabel", "evidence", "createdAt", "updatedAt"],
1773
+ required: [
1774
+ "id",
1775
+ "originType",
1776
+ "originAgentId",
1777
+ "originLabel",
1778
+ "visibility",
1779
+ "status",
1780
+ "entityType",
1781
+ "entityId",
1782
+ "timeframeLabel",
1783
+ "title",
1784
+ "summary",
1785
+ "recommendation",
1786
+ "rationale",
1787
+ "confidence",
1788
+ "ctaLabel",
1789
+ "evidence",
1790
+ "createdAt",
1791
+ "updatedAt"
1792
+ ],
867
1793
  properties: {
868
1794
  id: { type: "string" },
869
1795
  originType: { type: "string", enum: ["system", "user", "agent"] },
870
1796
  originAgentId: nullable({ type: "string" }),
871
1797
  originLabel: nullable({ type: "string" }),
872
- visibility: { type: "string", enum: ["visible", "pending_review", "archived"] },
873
- status: { type: "string", enum: ["open", "accepted", "dismissed", "snoozed", "applied", "expired"] },
1798
+ visibility: {
1799
+ type: "string",
1800
+ enum: ["visible", "pending_review", "archived"]
1801
+ },
1802
+ status: {
1803
+ type: "string",
1804
+ enum: ["open", "accepted", "dismissed", "snoozed", "applied", "expired"]
1805
+ },
874
1806
  entityType: nullable({ type: "string" }),
875
1807
  entityId: nullable({ type: "string" }),
876
1808
  timeframeLabel: nullable({ type: "string" }),
@@ -902,7 +1834,10 @@ export function buildOpenApiDocument() {
902
1834
  id: { type: "string" },
903
1835
  insightId: { type: "string" },
904
1836
  actor: nullable({ type: "string" }),
905
- feedbackType: { type: "string", enum: ["accepted", "dismissed", "applied", "snoozed"] },
1837
+ feedbackType: {
1838
+ type: "string",
1839
+ enum: ["accepted", "dismissed", "applied", "snoozed"]
1840
+ },
906
1841
  note: { type: "string" },
907
1842
  createdAt: { type: "string", format: "date-time" }
908
1843
  }
@@ -910,11 +1845,32 @@ export function buildOpenApiDocument() {
910
1845
  const approvalRequest = {
911
1846
  type: "object",
912
1847
  additionalProperties: false,
913
- required: ["id", "actionType", "status", "title", "summary", "entityType", "entityId", "requestedByAgentId", "requestedByTokenId", "requestedPayload", "approvedBy", "approvedAt", "rejectedBy", "rejectedAt", "resolutionNote", "createdAt", "updatedAt"],
1848
+ required: [
1849
+ "id",
1850
+ "actionType",
1851
+ "status",
1852
+ "title",
1853
+ "summary",
1854
+ "entityType",
1855
+ "entityId",
1856
+ "requestedByAgentId",
1857
+ "requestedByTokenId",
1858
+ "requestedPayload",
1859
+ "approvedBy",
1860
+ "approvedAt",
1861
+ "rejectedBy",
1862
+ "rejectedAt",
1863
+ "resolutionNote",
1864
+ "createdAt",
1865
+ "updatedAt"
1866
+ ],
914
1867
  properties: {
915
1868
  id: { type: "string" },
916
1869
  actionType: { type: "string" },
917
- status: { type: "string", enum: ["pending", "approved", "rejected", "cancelled", "executed"] },
1870
+ status: {
1871
+ type: "string",
1872
+ enum: ["pending", "approved", "rejected", "cancelled", "executed"]
1873
+ },
918
1874
  title: { type: "string" },
919
1875
  summary: { type: "string" },
920
1876
  entityType: nullable({ type: "string" }),
@@ -934,14 +1890,33 @@ export function buildOpenApiDocument() {
934
1890
  const agentAction = {
935
1891
  type: "object",
936
1892
  additionalProperties: false,
937
- required: ["id", "agentId", "tokenId", "actionType", "riskLevel", "status", "title", "summary", "payload", "idempotencyKey", "approvalRequestId", "outcome", "createdAt", "updatedAt", "completedAt"],
1893
+ required: [
1894
+ "id",
1895
+ "agentId",
1896
+ "tokenId",
1897
+ "actionType",
1898
+ "riskLevel",
1899
+ "status",
1900
+ "title",
1901
+ "summary",
1902
+ "payload",
1903
+ "idempotencyKey",
1904
+ "approvalRequestId",
1905
+ "outcome",
1906
+ "createdAt",
1907
+ "updatedAt",
1908
+ "completedAt"
1909
+ ],
938
1910
  properties: {
939
1911
  id: { type: "string" },
940
1912
  agentId: nullable({ type: "string" }),
941
1913
  tokenId: nullable({ type: "string" }),
942
1914
  actionType: { type: "string" },
943
1915
  riskLevel: { type: "string", enum: ["low", "medium", "high"] },
944
- status: { type: "string", enum: ["pending_approval", "approved", "rejected", "executed"] },
1916
+ status: {
1917
+ type: "string",
1918
+ enum: ["pending_approval", "approved", "rejected", "executed"]
1919
+ },
945
1920
  title: { type: "string" },
946
1921
  summary: { type: "string" },
947
1922
  payload: { type: "object", additionalProperties: true },
@@ -956,10 +1931,30 @@ export function buildOpenApiDocument() {
956
1931
  const rewardRule = {
957
1932
  type: "object",
958
1933
  additionalProperties: false,
959
- required: ["id", "family", "code", "title", "description", "active", "config", "createdAt", "updatedAt"],
1934
+ required: [
1935
+ "id",
1936
+ "family",
1937
+ "code",
1938
+ "title",
1939
+ "description",
1940
+ "active",
1941
+ "config",
1942
+ "createdAt",
1943
+ "updatedAt"
1944
+ ],
960
1945
  properties: {
961
1946
  id: { type: "string" },
962
- family: { type: "string", enum: ["completion", "consistency", "alignment", "recovery", "collaboration", "ambient"] },
1947
+ family: {
1948
+ type: "string",
1949
+ enum: [
1950
+ "completion",
1951
+ "consistency",
1952
+ "alignment",
1953
+ "recovery",
1954
+ "collaboration",
1955
+ "ambient"
1956
+ ]
1957
+ },
963
1958
  code: { type: "string" },
964
1959
  title: { type: "string" },
965
1960
  description: { type: "string" },
@@ -972,7 +1967,22 @@ export function buildOpenApiDocument() {
972
1967
  const rewardLedgerEvent = {
973
1968
  type: "object",
974
1969
  additionalProperties: false,
975
- required: ["id", "ruleId", "eventLogId", "entityType", "entityId", "actor", "source", "deltaXp", "reasonTitle", "reasonSummary", "reversibleGroup", "reversedByRewardId", "metadata", "createdAt"],
1970
+ required: [
1971
+ "id",
1972
+ "ruleId",
1973
+ "eventLogId",
1974
+ "entityType",
1975
+ "entityId",
1976
+ "actor",
1977
+ "source",
1978
+ "deltaXp",
1979
+ "reasonTitle",
1980
+ "reasonSummary",
1981
+ "reversibleGroup",
1982
+ "reversedByRewardId",
1983
+ "metadata",
1984
+ "createdAt"
1985
+ ],
976
1986
  properties: {
977
1987
  id: { type: "string" },
978
1988
  ruleId: nullable({ type: "string" }),
@@ -993,7 +2003,17 @@ export function buildOpenApiDocument() {
993
2003
  const eventLogEntry = {
994
2004
  type: "object",
995
2005
  additionalProperties: false,
996
- required: ["id", "eventKind", "entityType", "entityId", "actor", "source", "causedByEventId", "metadata", "createdAt"],
2006
+ required: [
2007
+ "id",
2008
+ "eventKind",
2009
+ "entityType",
2010
+ "entityId",
2011
+ "actor",
2012
+ "source",
2013
+ "causedByEventId",
2014
+ "metadata",
2015
+ "createdAt"
2016
+ ],
997
2017
  properties: {
998
2018
  id: { type: "string" },
999
2019
  eventKind: { type: "string" },
@@ -1009,7 +2029,14 @@ export function buildOpenApiDocument() {
1009
2029
  const xpMomentumPulse = {
1010
2030
  type: "object",
1011
2031
  additionalProperties: false,
1012
- required: ["status", "headline", "detail", "celebrationLabel", "nextMilestoneId", "nextMilestoneLabel"],
2032
+ required: [
2033
+ "status",
2034
+ "headline",
2035
+ "detail",
2036
+ "celebrationLabel",
2037
+ "nextMilestoneId",
2038
+ "nextMilestoneLabel"
2039
+ ],
1013
2040
  properties: {
1014
2041
  status: { type: "string", enum: ["surging", "steady", "recovering"] },
1015
2042
  headline: { type: "string" },
@@ -1022,11 +2049,22 @@ export function buildOpenApiDocument() {
1022
2049
  const xpMetricsPayload = {
1023
2050
  type: "object",
1024
2051
  additionalProperties: false,
1025
- required: ["profile", "achievements", "milestoneRewards", "momentumPulse", "recentLedger", "rules", "dailyAmbientXp", "dailyAmbientCap"],
2052
+ required: [
2053
+ "profile",
2054
+ "achievements",
2055
+ "milestoneRewards",
2056
+ "momentumPulse",
2057
+ "recentLedger",
2058
+ "rules",
2059
+ "dailyAmbientXp",
2060
+ "dailyAmbientCap"
2061
+ ],
1026
2062
  properties: {
1027
2063
  profile: { $ref: "#/components/schemas/GamificationProfile" },
1028
2064
  achievements: arrayOf({ $ref: "#/components/schemas/AchievementSignal" }),
1029
- milestoneRewards: arrayOf({ $ref: "#/components/schemas/MilestoneReward" }),
2065
+ milestoneRewards: arrayOf({
2066
+ $ref: "#/components/schemas/MilestoneReward"
2067
+ }),
1030
2068
  momentumPulse: { $ref: "#/components/schemas/XpMomentumPulse" },
1031
2069
  recentLedger: arrayOf({ $ref: "#/components/schemas/RewardLedgerEvent" }),
1032
2070
  rules: arrayOf({ $ref: "#/components/schemas/RewardRule" }),
@@ -1041,6 +2079,7 @@ export function buildOpenApiDocument() {
1041
2079
  "generatedAt",
1042
2080
  "activeProjects",
1043
2081
  "focusTasks",
2082
+ "dueHabits",
1044
2083
  "currentBoard",
1045
2084
  "recentActivity",
1046
2085
  "recentTaskRuns",
@@ -1051,6 +2090,7 @@ export function buildOpenApiDocument() {
1051
2090
  generatedAt: { type: "string", format: "date-time" },
1052
2091
  activeProjects: arrayOf({ $ref: "#/components/schemas/ProjectSummary" }),
1053
2092
  focusTasks: arrayOf({ $ref: "#/components/schemas/Task" }),
2093
+ dueHabits: arrayOf({ $ref: "#/components/schemas/Habit" }),
1054
2094
  currentBoard: {
1055
2095
  type: "object",
1056
2096
  additionalProperties: false,
@@ -1093,7 +2133,14 @@ export function buildOpenApiDocument() {
1093
2133
  capabilities: {
1094
2134
  type: "object",
1095
2135
  additionalProperties: false,
1096
- required: ["tokenPresent", "scopes", "canReadPsyche", "canWritePsyche", "canManageModes", "canManageRewards"],
2136
+ required: [
2137
+ "tokenPresent",
2138
+ "scopes",
2139
+ "canReadPsyche",
2140
+ "canWritePsyche",
2141
+ "canManageModes",
2142
+ "canManageRewards"
2143
+ ],
1097
2144
  properties: {
1098
2145
  tokenPresent: { type: "boolean" },
1099
2146
  scopes: arrayOf({ type: "string" }),
@@ -1128,7 +2175,16 @@ export function buildOpenApiDocument() {
1128
2175
  const settingsPayload = {
1129
2176
  type: "object",
1130
2177
  additionalProperties: false,
1131
- required: ["profile", "notifications", "execution", "themePreference", "localePreference", "security", "agents", "agentTokens"],
2178
+ required: [
2179
+ "profile",
2180
+ "notifications",
2181
+ "execution",
2182
+ "themePreference",
2183
+ "localePreference",
2184
+ "security",
2185
+ "agents",
2186
+ "agentTokens"
2187
+ ],
1132
2188
  properties: {
1133
2189
  profile: {
1134
2190
  type: "object",
@@ -1143,7 +2199,11 @@ export function buildOpenApiDocument() {
1143
2199
  notifications: {
1144
2200
  type: "object",
1145
2201
  additionalProperties: false,
1146
- required: ["goalDriftAlerts", "dailyQuestReminders", "achievementCelebrations"],
2202
+ required: [
2203
+ "goalDriftAlerts",
2204
+ "dailyQuestReminders",
2205
+ "achievementCelebrations"
2206
+ ],
1147
2207
  properties: {
1148
2208
  goalDriftAlerts: { type: "boolean" },
1149
2209
  dailyQuestReminders: { type: "boolean" },
@@ -1151,12 +2211,21 @@ export function buildOpenApiDocument() {
1151
2211
  }
1152
2212
  },
1153
2213
  execution: { $ref: "#/components/schemas/ExecutionSettings" },
1154
- themePreference: { type: "string", enum: ["obsidian", "solar", "system"] },
2214
+ themePreference: {
2215
+ type: "string",
2216
+ enum: ["obsidian", "solar", "system"]
2217
+ },
1155
2218
  localePreference: { type: "string", enum: ["en", "fr"] },
1156
2219
  security: {
1157
2220
  type: "object",
1158
2221
  additionalProperties: false,
1159
- required: ["integrityScore", "lastAuditAt", "storageMode", "activeSessions", "tokenCount"],
2222
+ required: [
2223
+ "integrityScore",
2224
+ "lastAuditAt",
2225
+ "storageMode",
2226
+ "activeSessions",
2227
+ "tokenCount"
2228
+ ],
1160
2229
  properties: {
1161
2230
  integrityScore: { type: "integer" },
1162
2231
  lastAuditAt: { type: "string", format: "date-time" },
@@ -1211,13 +2280,25 @@ export function buildOpenApiDocument() {
1211
2280
  settingsUrl: { type: "string" },
1212
2281
  tokenCreateUrl: { type: "string" },
1213
2282
  pluginBasePath: { type: "string" },
1214
- defaultConnectionMode: { type: "string", enum: ["operator_session", "managed_token"] },
2283
+ defaultConnectionMode: {
2284
+ type: "string",
2285
+ enum: ["operator_session", "managed_token"]
2286
+ },
1215
2287
  defaultActorLabel: { type: "string" },
1216
2288
  defaultTimeoutMs: { type: "integer" },
1217
2289
  recommendedScopes: arrayOf({ type: "string" }),
1218
- recommendedTrustLevel: { type: "string", enum: ["standard", "trusted", "autonomous"] },
1219
- recommendedAutonomyMode: { type: "string", enum: ["approval_required", "scoped_write", "autonomous"] },
1220
- recommendedApprovalMode: { type: "string", enum: ["approval_by_default", "high_impact_only", "none"] },
2290
+ recommendedTrustLevel: {
2291
+ type: "string",
2292
+ enum: ["standard", "trusted", "autonomous"]
2293
+ },
2294
+ recommendedAutonomyMode: {
2295
+ type: "string",
2296
+ enum: ["approval_required", "scoped_write", "autonomous"]
2297
+ },
2298
+ recommendedApprovalMode: {
2299
+ type: "string",
2300
+ enum: ["approval_by_default", "high_impact_only", "none"]
2301
+ },
1221
2302
  authModes: {
1222
2303
  type: "object",
1223
2304
  additionalProperties: false,
@@ -1249,7 +2330,12 @@ export function buildOpenApiDocument() {
1249
2330
  tokenRecovery: {
1250
2331
  type: "object",
1251
2332
  additionalProperties: false,
1252
- required: ["rawTokenStoredByForge", "recoveryAction", "rotationSummary", "settingsSummary"],
2333
+ required: [
2334
+ "rawTokenStoredByForge",
2335
+ "recoveryAction",
2336
+ "rotationSummary",
2337
+ "settingsSummary"
2338
+ ],
1253
2339
  properties: {
1254
2340
  rawTokenStoredByForge: { type: "boolean" },
1255
2341
  recoveryAction: { type: "string" },
@@ -1270,7 +2356,18 @@ export function buildOpenApiDocument() {
1270
2356
  conceptModel: {
1271
2357
  type: "object",
1272
2358
  additionalProperties: false,
1273
- required: ["goal", "project", "task", "taskRun", "note", "insight", "psyche"],
2359
+ required: [
2360
+ "goal",
2361
+ "project",
2362
+ "task",
2363
+ "taskRun",
2364
+ "note",
2365
+ "insight",
2366
+ "calendar",
2367
+ "workBlock",
2368
+ "taskTimebox",
2369
+ "psyche"
2370
+ ],
1274
2371
  properties: {
1275
2372
  goal: { type: "string" },
1276
2373
  project: { type: "string" },
@@ -1278,6 +2375,9 @@ export function buildOpenApiDocument() {
1278
2375
  taskRun: { type: "string" },
1279
2376
  note: { type: "string" },
1280
2377
  insight: { type: "string" },
2378
+ calendar: { type: "string" },
2379
+ workBlock: { type: "string" },
2380
+ taskTimebox: { type: "string" },
1281
2381
  psyche: { type: "string" }
1282
2382
  }
1283
2383
  },
@@ -1337,7 +2437,14 @@ export function buildOpenApiDocument() {
1337
2437
  entityCatalog: arrayOf({
1338
2438
  type: "object",
1339
2439
  additionalProperties: false,
1340
- required: ["entityType", "purpose", "minimumCreateFields", "relationshipRules", "searchHints", "fieldGuide"],
2440
+ required: [
2441
+ "entityType",
2442
+ "purpose",
2443
+ "minimumCreateFields",
2444
+ "relationshipRules",
2445
+ "searchHints",
2446
+ "fieldGuide"
2447
+ ],
1341
2448
  properties: {
1342
2449
  entityType: { type: "string" },
1343
2450
  purpose: { type: "string" },
@@ -1354,7 +2461,14 @@ export function buildOpenApiDocument() {
1354
2461
  required: { type: "boolean" },
1355
2462
  description: { type: "string" },
1356
2463
  enumValues: arrayOf({ type: "string" }),
1357
- defaultValue: { oneOf: [{ type: "string" }, { type: "number" }, { type: "boolean" }, { type: "null" }] },
2464
+ defaultValue: {
2465
+ oneOf: [
2466
+ { type: "string" },
2467
+ { type: "number" },
2468
+ { type: "boolean" },
2469
+ { type: "null" }
2470
+ ]
2471
+ },
1358
2472
  nullable: { type: "boolean" }
1359
2473
  }
1360
2474
  })
@@ -1363,7 +2477,15 @@ export function buildOpenApiDocument() {
1363
2477
  toolInputCatalog: arrayOf({
1364
2478
  type: "object",
1365
2479
  additionalProperties: false,
1366
- required: ["toolName", "summary", "whenToUse", "inputShape", "requiredFields", "notes", "example"],
2480
+ required: [
2481
+ "toolName",
2482
+ "summary",
2483
+ "whenToUse",
2484
+ "inputShape",
2485
+ "requiredFields",
2486
+ "notes",
2487
+ "example"
2488
+ ],
1367
2489
  properties: {
1368
2490
  toolName: { type: "string" },
1369
2491
  summary: { type: "string" },
@@ -1377,11 +2499,22 @@ export function buildOpenApiDocument() {
1377
2499
  verificationPaths: {
1378
2500
  type: "object",
1379
2501
  additionalProperties: false,
1380
- required: ["context", "xpMetrics", "weeklyReview", "settingsBin", "batchSearch", "psycheSchemaCatalog", "psycheEventTypes", "psycheEmotions"],
2502
+ required: [
2503
+ "context",
2504
+ "xpMetrics",
2505
+ "weeklyReview",
2506
+ "calendarOverview",
2507
+ "settingsBin",
2508
+ "batchSearch",
2509
+ "psycheSchemaCatalog",
2510
+ "psycheEventTypes",
2511
+ "psycheEmotions"
2512
+ ],
1381
2513
  properties: {
1382
2514
  context: { type: "string" },
1383
2515
  xpMetrics: { type: "string" },
1384
2516
  weeklyReview: { type: "string" },
2517
+ calendarOverview: { type: "string" },
1385
2518
  settingsBin: { type: "string" },
1386
2519
  batchSearch: { type: "string" },
1387
2520
  psycheSchemaCatalog: { type: "string" },
@@ -1392,13 +2525,22 @@ export function buildOpenApiDocument() {
1392
2525
  recommendedPluginTools: {
1393
2526
  type: "object",
1394
2527
  additionalProperties: false,
1395
- required: ["bootstrap", "readModels", "uiWorkflow", "entityWorkflow", "workWorkflow", "insightWorkflow"],
2528
+ required: [
2529
+ "bootstrap",
2530
+ "readModels",
2531
+ "uiWorkflow",
2532
+ "entityWorkflow",
2533
+ "workWorkflow",
2534
+ "calendarWorkflow",
2535
+ "insightWorkflow"
2536
+ ],
1396
2537
  properties: {
1397
2538
  bootstrap: arrayOf({ type: "string" }),
1398
2539
  readModels: arrayOf({ type: "string" }),
1399
2540
  uiWorkflow: arrayOf({ type: "string" }),
1400
2541
  entityWorkflow: arrayOf({ type: "string" }),
1401
2542
  workWorkflow: arrayOf({ type: "string" }),
2543
+ calendarWorkflow: arrayOf({ type: "string" }),
1402
2544
  insightWorkflow: arrayOf({ type: "string" })
1403
2545
  }
1404
2546
  },
@@ -1492,7 +2634,10 @@ export function buildOpenApiDocument() {
1492
2634
  properties: {
1493
2635
  generatedAt: { type: "string", format: "date-time" },
1494
2636
  totalCount: { type: "integer" },
1495
- countsByEntityType: { type: "object", additionalProperties: { type: "integer" } },
2637
+ countsByEntityType: {
2638
+ type: "object",
2639
+ additionalProperties: { type: "integer" }
2640
+ },
1496
2641
  records: arrayOf({ $ref: "#/components/schemas/DeletedEntityRecord" })
1497
2642
  }
1498
2643
  };
@@ -1530,7 +2675,16 @@ export function buildOpenApiDocument() {
1530
2675
  const domain = {
1531
2676
  type: "object",
1532
2677
  additionalProperties: false,
1533
- required: ["id", "slug", "title", "description", "themeColor", "sensitive", "createdAt", "updatedAt"],
2678
+ required: [
2679
+ "id",
2680
+ "slug",
2681
+ "title",
2682
+ "description",
2683
+ "themeColor",
2684
+ "sensitive",
2685
+ "createdAt",
2686
+ "updatedAt"
2687
+ ],
1534
2688
  properties: {
1535
2689
  id: { type: "string" },
1536
2690
  slug: { type: "string" },
@@ -1613,7 +2767,16 @@ export function buildOpenApiDocument() {
1613
2767
  const schemaCatalogEntry = {
1614
2768
  type: "object",
1615
2769
  additionalProperties: false,
1616
- required: ["id", "slug", "title", "family", "schemaType", "description", "createdAt", "updatedAt"],
2770
+ required: [
2771
+ "id",
2772
+ "slug",
2773
+ "title",
2774
+ "family",
2775
+ "schemaType",
2776
+ "description",
2777
+ "createdAt",
2778
+ "updatedAt"
2779
+ ],
1617
2780
  properties: {
1618
2781
  id: { type: "string" },
1619
2782
  slug: { type: "string" },
@@ -1628,7 +2791,15 @@ export function buildOpenApiDocument() {
1628
2791
  const eventType = {
1629
2792
  type: "object",
1630
2793
  additionalProperties: false,
1631
- required: ["id", "domainId", "label", "description", "system", "createdAt", "updatedAt"],
2794
+ required: [
2795
+ "id",
2796
+ "domainId",
2797
+ "label",
2798
+ "description",
2799
+ "system",
2800
+ "createdAt",
2801
+ "updatedAt"
2802
+ ],
1632
2803
  properties: {
1633
2804
  id: { type: "string" },
1634
2805
  domainId: { type: "string" },
@@ -1642,7 +2813,16 @@ export function buildOpenApiDocument() {
1642
2813
  const emotionDefinition = {
1643
2814
  type: "object",
1644
2815
  additionalProperties: false,
1645
- required: ["id", "domainId", "label", "description", "category", "system", "createdAt", "updatedAt"],
2816
+ required: [
2817
+ "id",
2818
+ "domainId",
2819
+ "label",
2820
+ "description",
2821
+ "category",
2822
+ "system",
2823
+ "createdAt",
2824
+ "updatedAt"
2825
+ ],
1646
2826
  properties: {
1647
2827
  id: { type: "string" },
1648
2828
  domainId: { type: "string" },
@@ -1763,7 +2943,16 @@ export function buildOpenApiDocument() {
1763
2943
  properties: {
1764
2944
  id: { type: "string" },
1765
2945
  domainId: { type: "string" },
1766
- family: { type: "string", enum: ["coping", "child", "critic_parent", "healthy_adult", "happy_child"] },
2946
+ family: {
2947
+ type: "string",
2948
+ enum: [
2949
+ "coping",
2950
+ "child",
2951
+ "critic_parent",
2952
+ "healthy_adult",
2953
+ "happy_child"
2954
+ ]
2955
+ },
1767
2956
  archetype: { type: "string" },
1768
2957
  title: { type: "string" },
1769
2958
  persona: { type: "string" },
@@ -1803,7 +2992,16 @@ export function buildOpenApiDocument() {
1803
2992
  additionalProperties: false,
1804
2993
  required: ["family", "archetype", "label", "confidence", "reasoning"],
1805
2994
  properties: {
1806
- family: { type: "string", enum: ["coping", "child", "critic_parent", "healthy_adult", "happy_child"] },
2995
+ family: {
2996
+ type: "string",
2997
+ enum: [
2998
+ "coping",
2999
+ "child",
3000
+ "critic_parent",
3001
+ "healthy_adult",
3002
+ "happy_child"
3003
+ ]
3004
+ },
1807
3005
  archetype: { type: "string" },
1808
3006
  label: { type: "string" },
1809
3007
  confidence: { type: "number" },
@@ -1892,7 +3090,12 @@ export function buildOpenApiDocument() {
1892
3090
  consequences: {
1893
3091
  type: "object",
1894
3092
  additionalProperties: false,
1895
- required: ["selfShortTerm", "selfLongTerm", "othersShortTerm", "othersLongTerm"],
3093
+ required: [
3094
+ "selfShortTerm",
3095
+ "selfLongTerm",
3096
+ "othersShortTerm",
3097
+ "othersLongTerm"
3098
+ ],
1896
3099
  properties: {
1897
3100
  selfShortTerm: arrayOf({ type: "string" }),
1898
3101
  selfLongTerm: arrayOf({ type: "string" }),
@@ -1989,10 +3192,22 @@ export function buildOpenApiDocument() {
1989
3192
  Goal: goal,
1990
3193
  DashboardGoal: dashboardGoal,
1991
3194
  Project: project,
3195
+ CalendarSchedulingRules: calendarSchedulingRules,
3196
+ CalendarConnection: calendarConnection,
3197
+ CalendarResource: calendarResource,
3198
+ CalendarEventSource: calendarEventSource,
3199
+ CalendarEventLink: calendarEventLink,
3200
+ CalendarEvent: calendarEvent,
3201
+ WorkBlockTemplate: workBlockTemplate,
3202
+ WorkBlockInstance: workBlockInstance,
3203
+ TaskTimebox: taskTimebox,
3204
+ CalendarOverviewPayload: calendarOverviewPayload,
1992
3205
  TaskTimeSummary: taskTimeSummary,
1993
3206
  ProjectSummary: projectSummary,
1994
3207
  Task: task,
1995
3208
  TaskRun: taskRun,
3209
+ HabitCheckIn: habitCheckIn,
3210
+ Habit: habit,
1996
3211
  ActivityEvent: activityEvent,
1997
3212
  GamificationProfile: gamificationProfile,
1998
3213
  AchievementSignal: achievementSignal,
@@ -2013,6 +3228,10 @@ export function buildOpenApiDocument() {
2013
3228
  TaskRunHeartbeatInput: taskRunHeartbeatInput,
2014
3229
  TaskRunFinishInput: taskRunFinishInput,
2015
3230
  TaskRunFocusInput: taskRunFocusInput,
3231
+ WorkAdjustment: workAdjustment,
3232
+ WorkAdjustmentTargetSummary: workAdjustmentTargetSummary,
3233
+ WorkAdjustmentInput: workAdjustmentInput,
3234
+ WorkAdjustmentResult: workAdjustmentResult,
2016
3235
  SettingsUpdateInput: settingsUpdateInput,
2017
3236
  AgentOnboardingPayload: agentOnboardingPayload,
2018
3237
  DeletedEntityRecord: deletedEntityRecord,
@@ -2066,13 +3285,27 @@ export function buildOpenApiDocument() {
2066
3285
  now: { type: "string", format: "date-time" },
2067
3286
  watchdog: {
2068
3287
  type: "object",
2069
- required: ["enabled", "healthy", "state", "reason", "status"],
3288
+ required: [
3289
+ "enabled",
3290
+ "healthy",
3291
+ "state",
3292
+ "reason",
3293
+ "status"
3294
+ ],
2070
3295
  properties: {
2071
3296
  enabled: { type: "boolean" },
2072
3297
  healthy: { type: "boolean" },
2073
- state: { type: "string", enum: ["disabled", "idle", "healthy", "degraded"] },
3298
+ state: {
3299
+ type: "string",
3300
+ enum: ["disabled", "idle", "healthy", "degraded"]
3301
+ },
2074
3302
  reason: { anyOf: [{ type: "string" }, { type: "null" }] },
2075
- status: { anyOf: [{ type: "object", additionalProperties: true }, { type: "null" }] }
3303
+ status: {
3304
+ anyOf: [
3305
+ { type: "object", additionalProperties: true },
3306
+ { type: "null" }
3307
+ ]
3308
+ }
2076
3309
  }
2077
3310
  }
2078
3311
  }
@@ -2097,7 +3330,9 @@ export function buildOpenApiDocument() {
2097
3330
  type: "object",
2098
3331
  required: ["context"],
2099
3332
  properties: {
2100
- context: { $ref: "#/components/schemas/OperatorContextPayload" }
3333
+ context: {
3334
+ $ref: "#/components/schemas/OperatorContextPayload"
3335
+ }
2101
3336
  }
2102
3337
  }, "Operator context")
2103
3338
  }
@@ -2111,7 +3346,9 @@ export function buildOpenApiDocument() {
2111
3346
  type: "object",
2112
3347
  required: ["overview"],
2113
3348
  properties: {
2114
- overview: { $ref: "#/components/schemas/OperatorOverviewPayload" }
3349
+ overview: {
3350
+ $ref: "#/components/schemas/OperatorOverviewPayload"
3351
+ }
2115
3352
  }
2116
3353
  }, "Operator overview")
2117
3354
  }
@@ -2140,7 +3377,9 @@ export function buildOpenApiDocument() {
2140
3377
  type: "object",
2141
3378
  required: ["overview"],
2142
3379
  properties: {
2143
- overview: { $ref: "#/components/schemas/PsycheOverviewPayload" }
3380
+ overview: {
3381
+ $ref: "#/components/schemas/PsycheOverviewPayload"
3382
+ }
2144
3383
  }
2145
3384
  }, "Psyche overview"),
2146
3385
  default: { $ref: "#/components/responses/Error" }
@@ -2151,14 +3390,26 @@ export function buildOpenApiDocument() {
2151
3390
  get: {
2152
3391
  summary: "List ACT-style values",
2153
3392
  responses: {
2154
- "200": jsonResponse({ type: "object", required: ["values"], properties: { values: arrayOf({ $ref: "#/components/schemas/PsycheValue" }) } }, "Psyche value collection"),
3393
+ "200": jsonResponse({
3394
+ type: "object",
3395
+ required: ["values"],
3396
+ properties: {
3397
+ values: arrayOf({ $ref: "#/components/schemas/PsycheValue" })
3398
+ }
3399
+ }, "Psyche value collection"),
2155
3400
  default: { $ref: "#/components/responses/Error" }
2156
3401
  }
2157
3402
  },
2158
3403
  post: {
2159
3404
  summary: "Create a Psyche value",
2160
3405
  responses: {
2161
- "201": jsonResponse({ type: "object", required: ["value"], properties: { value: { $ref: "#/components/schemas/PsycheValue" } } }, "Created value"),
3406
+ "201": jsonResponse({
3407
+ type: "object",
3408
+ required: ["value"],
3409
+ properties: {
3410
+ value: { $ref: "#/components/schemas/PsycheValue" }
3411
+ }
3412
+ }, "Created value"),
2162
3413
  default: { $ref: "#/components/responses/Error" }
2163
3414
  }
2164
3415
  }
@@ -2167,21 +3418,39 @@ export function buildOpenApiDocument() {
2167
3418
  get: {
2168
3419
  summary: "Get a Psyche value",
2169
3420
  responses: {
2170
- "200": jsonResponse({ type: "object", required: ["value"], properties: { value: { $ref: "#/components/schemas/PsycheValue" } } }, "Psyche value"),
3421
+ "200": jsonResponse({
3422
+ type: "object",
3423
+ required: ["value"],
3424
+ properties: {
3425
+ value: { $ref: "#/components/schemas/PsycheValue" }
3426
+ }
3427
+ }, "Psyche value"),
2171
3428
  default: { $ref: "#/components/responses/Error" }
2172
3429
  }
2173
3430
  },
2174
3431
  patch: {
2175
3432
  summary: "Update a Psyche value",
2176
3433
  responses: {
2177
- "200": jsonResponse({ type: "object", required: ["value"], properties: { value: { $ref: "#/components/schemas/PsycheValue" } } }, "Updated value"),
3434
+ "200": jsonResponse({
3435
+ type: "object",
3436
+ required: ["value"],
3437
+ properties: {
3438
+ value: { $ref: "#/components/schemas/PsycheValue" }
3439
+ }
3440
+ }, "Updated value"),
2178
3441
  default: { $ref: "#/components/responses/Error" }
2179
3442
  }
2180
3443
  },
2181
3444
  delete: {
2182
3445
  summary: "Delete a Psyche value",
2183
3446
  responses: {
2184
- "200": jsonResponse({ type: "object", required: ["value"], properties: { value: { $ref: "#/components/schemas/PsycheValue" } } }, "Deleted value"),
3447
+ "200": jsonResponse({
3448
+ type: "object",
3449
+ required: ["value"],
3450
+ properties: {
3451
+ value: { $ref: "#/components/schemas/PsycheValue" }
3452
+ }
3453
+ }, "Deleted value"),
2185
3454
  default: { $ref: "#/components/responses/Error" }
2186
3455
  }
2187
3456
  }
@@ -2190,14 +3459,28 @@ export function buildOpenApiDocument() {
2190
3459
  get: {
2191
3460
  summary: "List behavior patterns",
2192
3461
  responses: {
2193
- "200": jsonResponse({ type: "object", required: ["patterns"], properties: { patterns: arrayOf({ $ref: "#/components/schemas/BehaviorPattern" }) } }, "Behavior pattern collection"),
3462
+ "200": jsonResponse({
3463
+ type: "object",
3464
+ required: ["patterns"],
3465
+ properties: {
3466
+ patterns: arrayOf({
3467
+ $ref: "#/components/schemas/BehaviorPattern"
3468
+ })
3469
+ }
3470
+ }, "Behavior pattern collection"),
2194
3471
  default: { $ref: "#/components/responses/Error" }
2195
3472
  }
2196
3473
  },
2197
3474
  post: {
2198
3475
  summary: "Create a behavior pattern",
2199
3476
  responses: {
2200
- "201": jsonResponse({ type: "object", required: ["pattern"], properties: { pattern: { $ref: "#/components/schemas/BehaviorPattern" } } }, "Created behavior pattern"),
3477
+ "201": jsonResponse({
3478
+ type: "object",
3479
+ required: ["pattern"],
3480
+ properties: {
3481
+ pattern: { $ref: "#/components/schemas/BehaviorPattern" }
3482
+ }
3483
+ }, "Created behavior pattern"),
2201
3484
  default: { $ref: "#/components/responses/Error" }
2202
3485
  }
2203
3486
  }
@@ -2206,21 +3489,39 @@ export function buildOpenApiDocument() {
2206
3489
  get: {
2207
3490
  summary: "Get a behavior pattern",
2208
3491
  responses: {
2209
- "200": jsonResponse({ type: "object", required: ["pattern"], properties: { pattern: { $ref: "#/components/schemas/BehaviorPattern" } } }, "Behavior pattern"),
3492
+ "200": jsonResponse({
3493
+ type: "object",
3494
+ required: ["pattern"],
3495
+ properties: {
3496
+ pattern: { $ref: "#/components/schemas/BehaviorPattern" }
3497
+ }
3498
+ }, "Behavior pattern"),
2210
3499
  default: { $ref: "#/components/responses/Error" }
2211
3500
  }
2212
3501
  },
2213
3502
  patch: {
2214
3503
  summary: "Update a behavior pattern",
2215
3504
  responses: {
2216
- "200": jsonResponse({ type: "object", required: ["pattern"], properties: { pattern: { $ref: "#/components/schemas/BehaviorPattern" } } }, "Updated behavior pattern"),
3505
+ "200": jsonResponse({
3506
+ type: "object",
3507
+ required: ["pattern"],
3508
+ properties: {
3509
+ pattern: { $ref: "#/components/schemas/BehaviorPattern" }
3510
+ }
3511
+ }, "Updated behavior pattern"),
2217
3512
  default: { $ref: "#/components/responses/Error" }
2218
3513
  }
2219
3514
  },
2220
3515
  delete: {
2221
3516
  summary: "Delete a behavior pattern",
2222
3517
  responses: {
2223
- "200": jsonResponse({ type: "object", required: ["pattern"], properties: { pattern: { $ref: "#/components/schemas/BehaviorPattern" } } }, "Deleted behavior pattern"),
3518
+ "200": jsonResponse({
3519
+ type: "object",
3520
+ required: ["pattern"],
3521
+ properties: {
3522
+ pattern: { $ref: "#/components/schemas/BehaviorPattern" }
3523
+ }
3524
+ }, "Deleted behavior pattern"),
2224
3525
  default: { $ref: "#/components/responses/Error" }
2225
3526
  }
2226
3527
  }
@@ -2229,14 +3530,26 @@ export function buildOpenApiDocument() {
2229
3530
  get: {
2230
3531
  summary: "List tracked Psyche behaviors",
2231
3532
  responses: {
2232
- "200": jsonResponse({ type: "object", required: ["behaviors"], properties: { behaviors: arrayOf({ $ref: "#/components/schemas/Behavior" }) } }, "Behavior collection"),
3533
+ "200": jsonResponse({
3534
+ type: "object",
3535
+ required: ["behaviors"],
3536
+ properties: {
3537
+ behaviors: arrayOf({ $ref: "#/components/schemas/Behavior" })
3538
+ }
3539
+ }, "Behavior collection"),
2233
3540
  default: { $ref: "#/components/responses/Error" }
2234
3541
  }
2235
3542
  },
2236
3543
  post: {
2237
3544
  summary: "Create a Psyche behavior",
2238
3545
  responses: {
2239
- "201": jsonResponse({ type: "object", required: ["behavior"], properties: { behavior: { $ref: "#/components/schemas/Behavior" } } }, "Created behavior"),
3546
+ "201": jsonResponse({
3547
+ type: "object",
3548
+ required: ["behavior"],
3549
+ properties: {
3550
+ behavior: { $ref: "#/components/schemas/Behavior" }
3551
+ }
3552
+ }, "Created behavior"),
2240
3553
  default: { $ref: "#/components/responses/Error" }
2241
3554
  }
2242
3555
  }
@@ -2245,21 +3558,39 @@ export function buildOpenApiDocument() {
2245
3558
  get: {
2246
3559
  summary: "Get a Psyche behavior",
2247
3560
  responses: {
2248
- "200": jsonResponse({ type: "object", required: ["behavior"], properties: { behavior: { $ref: "#/components/schemas/Behavior" } } }, "Behavior detail"),
3561
+ "200": jsonResponse({
3562
+ type: "object",
3563
+ required: ["behavior"],
3564
+ properties: {
3565
+ behavior: { $ref: "#/components/schemas/Behavior" }
3566
+ }
3567
+ }, "Behavior detail"),
2249
3568
  default: { $ref: "#/components/responses/Error" }
2250
3569
  }
2251
3570
  },
2252
3571
  patch: {
2253
3572
  summary: "Update a Psyche behavior",
2254
3573
  responses: {
2255
- "200": jsonResponse({ type: "object", required: ["behavior"], properties: { behavior: { $ref: "#/components/schemas/Behavior" } } }, "Updated behavior"),
3574
+ "200": jsonResponse({
3575
+ type: "object",
3576
+ required: ["behavior"],
3577
+ properties: {
3578
+ behavior: { $ref: "#/components/schemas/Behavior" }
3579
+ }
3580
+ }, "Updated behavior"),
2256
3581
  default: { $ref: "#/components/responses/Error" }
2257
3582
  }
2258
3583
  },
2259
3584
  delete: {
2260
3585
  summary: "Delete a Psyche behavior",
2261
3586
  responses: {
2262
- "200": jsonResponse({ type: "object", required: ["behavior"], properties: { behavior: { $ref: "#/components/schemas/Behavior" } } }, "Deleted behavior"),
3587
+ "200": jsonResponse({
3588
+ type: "object",
3589
+ required: ["behavior"],
3590
+ properties: {
3591
+ behavior: { $ref: "#/components/schemas/Behavior" }
3592
+ }
3593
+ }, "Deleted behavior"),
2263
3594
  default: { $ref: "#/components/responses/Error" }
2264
3595
  }
2265
3596
  }
@@ -2268,7 +3599,15 @@ export function buildOpenApiDocument() {
2268
3599
  get: {
2269
3600
  summary: "List the fixed schema-therapy catalog",
2270
3601
  responses: {
2271
- "200": jsonResponse({ type: "object", required: ["schemas"], properties: { schemas: arrayOf({ $ref: "#/components/schemas/SchemaCatalogEntry" }) } }, "Schema catalog"),
3602
+ "200": jsonResponse({
3603
+ type: "object",
3604
+ required: ["schemas"],
3605
+ properties: {
3606
+ schemas: arrayOf({
3607
+ $ref: "#/components/schemas/SchemaCatalogEntry"
3608
+ })
3609
+ }
3610
+ }, "Schema catalog"),
2272
3611
  default: { $ref: "#/components/responses/Error" }
2273
3612
  }
2274
3613
  }
@@ -2277,14 +3616,26 @@ export function buildOpenApiDocument() {
2277
3616
  get: {
2278
3617
  summary: "List belief entries linked to schemas and reports",
2279
3618
  responses: {
2280
- "200": jsonResponse({ type: "object", required: ["beliefs"], properties: { beliefs: arrayOf({ $ref: "#/components/schemas/BeliefEntry" }) } }, "Belief collection"),
3619
+ "200": jsonResponse({
3620
+ type: "object",
3621
+ required: ["beliefs"],
3622
+ properties: {
3623
+ beliefs: arrayOf({ $ref: "#/components/schemas/BeliefEntry" })
3624
+ }
3625
+ }, "Belief collection"),
2281
3626
  default: { $ref: "#/components/responses/Error" }
2282
3627
  }
2283
3628
  },
2284
3629
  post: {
2285
3630
  summary: "Create a belief entry",
2286
3631
  responses: {
2287
- "201": jsonResponse({ type: "object", required: ["belief"], properties: { belief: { $ref: "#/components/schemas/BeliefEntry" } } }, "Created belief"),
3632
+ "201": jsonResponse({
3633
+ type: "object",
3634
+ required: ["belief"],
3635
+ properties: {
3636
+ belief: { $ref: "#/components/schemas/BeliefEntry" }
3637
+ }
3638
+ }, "Created belief"),
2288
3639
  default: { $ref: "#/components/responses/Error" }
2289
3640
  }
2290
3641
  }
@@ -2293,21 +3644,39 @@ export function buildOpenApiDocument() {
2293
3644
  get: {
2294
3645
  summary: "Get a belief entry",
2295
3646
  responses: {
2296
- "200": jsonResponse({ type: "object", required: ["belief"], properties: { belief: { $ref: "#/components/schemas/BeliefEntry" } } }, "Belief detail"),
3647
+ "200": jsonResponse({
3648
+ type: "object",
3649
+ required: ["belief"],
3650
+ properties: {
3651
+ belief: { $ref: "#/components/schemas/BeliefEntry" }
3652
+ }
3653
+ }, "Belief detail"),
2297
3654
  default: { $ref: "#/components/responses/Error" }
2298
3655
  }
2299
3656
  },
2300
3657
  patch: {
2301
3658
  summary: "Update a belief entry",
2302
3659
  responses: {
2303
- "200": jsonResponse({ type: "object", required: ["belief"], properties: { belief: { $ref: "#/components/schemas/BeliefEntry" } } }, "Updated belief"),
3660
+ "200": jsonResponse({
3661
+ type: "object",
3662
+ required: ["belief"],
3663
+ properties: {
3664
+ belief: { $ref: "#/components/schemas/BeliefEntry" }
3665
+ }
3666
+ }, "Updated belief"),
2304
3667
  default: { $ref: "#/components/responses/Error" }
2305
3668
  }
2306
3669
  },
2307
3670
  delete: {
2308
3671
  summary: "Delete a belief entry",
2309
3672
  responses: {
2310
- "200": jsonResponse({ type: "object", required: ["belief"], properties: { belief: { $ref: "#/components/schemas/BeliefEntry" } } }, "Deleted belief"),
3673
+ "200": jsonResponse({
3674
+ type: "object",
3675
+ required: ["belief"],
3676
+ properties: {
3677
+ belief: { $ref: "#/components/schemas/BeliefEntry" }
3678
+ }
3679
+ }, "Deleted belief"),
2311
3680
  default: { $ref: "#/components/responses/Error" }
2312
3681
  }
2313
3682
  }
@@ -2316,14 +3685,26 @@ export function buildOpenApiDocument() {
2316
3685
  get: {
2317
3686
  summary: "List Psyche mode profiles",
2318
3687
  responses: {
2319
- "200": jsonResponse({ type: "object", required: ["modes"], properties: { modes: arrayOf({ $ref: "#/components/schemas/ModeProfile" }) } }, "Mode collection"),
3688
+ "200": jsonResponse({
3689
+ type: "object",
3690
+ required: ["modes"],
3691
+ properties: {
3692
+ modes: arrayOf({ $ref: "#/components/schemas/ModeProfile" })
3693
+ }
3694
+ }, "Mode collection"),
2320
3695
  default: { $ref: "#/components/responses/Error" }
2321
3696
  }
2322
3697
  },
2323
3698
  post: {
2324
3699
  summary: "Create a Psyche mode profile",
2325
3700
  responses: {
2326
- "201": jsonResponse({ type: "object", required: ["mode"], properties: { mode: { $ref: "#/components/schemas/ModeProfile" } } }, "Created mode"),
3701
+ "201": jsonResponse({
3702
+ type: "object",
3703
+ required: ["mode"],
3704
+ properties: {
3705
+ mode: { $ref: "#/components/schemas/ModeProfile" }
3706
+ }
3707
+ }, "Created mode"),
2327
3708
  default: { $ref: "#/components/responses/Error" }
2328
3709
  }
2329
3710
  }
@@ -2332,21 +3713,39 @@ export function buildOpenApiDocument() {
2332
3713
  get: {
2333
3714
  summary: "Get a Psyche mode profile",
2334
3715
  responses: {
2335
- "200": jsonResponse({ type: "object", required: ["mode"], properties: { mode: { $ref: "#/components/schemas/ModeProfile" } } }, "Mode detail"),
3716
+ "200": jsonResponse({
3717
+ type: "object",
3718
+ required: ["mode"],
3719
+ properties: {
3720
+ mode: { $ref: "#/components/schemas/ModeProfile" }
3721
+ }
3722
+ }, "Mode detail"),
2336
3723
  default: { $ref: "#/components/responses/Error" }
2337
3724
  }
2338
3725
  },
2339
3726
  patch: {
2340
3727
  summary: "Update a Psyche mode profile",
2341
3728
  responses: {
2342
- "200": jsonResponse({ type: "object", required: ["mode"], properties: { mode: { $ref: "#/components/schemas/ModeProfile" } } }, "Updated mode"),
3729
+ "200": jsonResponse({
3730
+ type: "object",
3731
+ required: ["mode"],
3732
+ properties: {
3733
+ mode: { $ref: "#/components/schemas/ModeProfile" }
3734
+ }
3735
+ }, "Updated mode"),
2343
3736
  default: { $ref: "#/components/responses/Error" }
2344
3737
  }
2345
3738
  },
2346
3739
  delete: {
2347
3740
  summary: "Delete a Psyche mode profile",
2348
3741
  responses: {
2349
- "200": jsonResponse({ type: "object", required: ["mode"], properties: { mode: { $ref: "#/components/schemas/ModeProfile" } } }, "Deleted mode"),
3742
+ "200": jsonResponse({
3743
+ type: "object",
3744
+ required: ["mode"],
3745
+ properties: {
3746
+ mode: { $ref: "#/components/schemas/ModeProfile" }
3747
+ }
3748
+ }, "Deleted mode"),
2350
3749
  default: { $ref: "#/components/responses/Error" }
2351
3750
  }
2352
3751
  }
@@ -2355,14 +3754,28 @@ export function buildOpenApiDocument() {
2355
3754
  get: {
2356
3755
  summary: "List guided mode-identification sessions",
2357
3756
  responses: {
2358
- "200": jsonResponse({ type: "object", required: ["sessions"], properties: { sessions: arrayOf({ $ref: "#/components/schemas/ModeGuideSession" }) } }, "Mode guide sessions"),
3757
+ "200": jsonResponse({
3758
+ type: "object",
3759
+ required: ["sessions"],
3760
+ properties: {
3761
+ sessions: arrayOf({
3762
+ $ref: "#/components/schemas/ModeGuideSession"
3763
+ })
3764
+ }
3765
+ }, "Mode guide sessions"),
2359
3766
  default: { $ref: "#/components/responses/Error" }
2360
3767
  }
2361
3768
  },
2362
3769
  post: {
2363
3770
  summary: "Create a guided mode-identification session",
2364
3771
  responses: {
2365
- "201": jsonResponse({ type: "object", required: ["session"], properties: { session: { $ref: "#/components/schemas/ModeGuideSession" } } }, "Created mode guide session"),
3772
+ "201": jsonResponse({
3773
+ type: "object",
3774
+ required: ["session"],
3775
+ properties: {
3776
+ session: { $ref: "#/components/schemas/ModeGuideSession" }
3777
+ }
3778
+ }, "Created mode guide session"),
2366
3779
  default: { $ref: "#/components/responses/Error" }
2367
3780
  }
2368
3781
  }
@@ -2371,21 +3784,39 @@ export function buildOpenApiDocument() {
2371
3784
  get: {
2372
3785
  summary: "Get a guided mode-identification session",
2373
3786
  responses: {
2374
- "200": jsonResponse({ type: "object", required: ["session"], properties: { session: { $ref: "#/components/schemas/ModeGuideSession" } } }, "Mode guide detail"),
3787
+ "200": jsonResponse({
3788
+ type: "object",
3789
+ required: ["session"],
3790
+ properties: {
3791
+ session: { $ref: "#/components/schemas/ModeGuideSession" }
3792
+ }
3793
+ }, "Mode guide detail"),
2375
3794
  default: { $ref: "#/components/responses/Error" }
2376
3795
  }
2377
3796
  },
2378
3797
  patch: {
2379
3798
  summary: "Update a guided mode-identification session",
2380
3799
  responses: {
2381
- "200": jsonResponse({ type: "object", required: ["session"], properties: { session: { $ref: "#/components/schemas/ModeGuideSession" } } }, "Updated mode guide session"),
3800
+ "200": jsonResponse({
3801
+ type: "object",
3802
+ required: ["session"],
3803
+ properties: {
3804
+ session: { $ref: "#/components/schemas/ModeGuideSession" }
3805
+ }
3806
+ }, "Updated mode guide session"),
2382
3807
  default: { $ref: "#/components/responses/Error" }
2383
3808
  }
2384
3809
  },
2385
3810
  delete: {
2386
3811
  summary: "Delete a guided mode-identification session",
2387
3812
  responses: {
2388
- "200": jsonResponse({ type: "object", required: ["session"], properties: { session: { $ref: "#/components/schemas/ModeGuideSession" } } }, "Deleted mode guide session"),
3813
+ "200": jsonResponse({
3814
+ type: "object",
3815
+ required: ["session"],
3816
+ properties: {
3817
+ session: { $ref: "#/components/schemas/ModeGuideSession" }
3818
+ }
3819
+ }, "Deleted mode guide session"),
2389
3820
  default: { $ref: "#/components/responses/Error" }
2390
3821
  }
2391
3822
  }
@@ -2394,14 +3825,28 @@ export function buildOpenApiDocument() {
2394
3825
  get: {
2395
3826
  summary: "List seeded and custom Psyche event types",
2396
3827
  responses: {
2397
- "200": jsonResponse({ type: "object", required: ["eventTypes"], properties: { eventTypes: arrayOf({ $ref: "#/components/schemas/EventType" }) } }, "Event type collection"),
3828
+ "200": jsonResponse({
3829
+ type: "object",
3830
+ required: ["eventTypes"],
3831
+ properties: {
3832
+ eventTypes: arrayOf({
3833
+ $ref: "#/components/schemas/EventType"
3834
+ })
3835
+ }
3836
+ }, "Event type collection"),
2398
3837
  default: { $ref: "#/components/responses/Error" }
2399
3838
  }
2400
3839
  },
2401
3840
  post: {
2402
3841
  summary: "Create a custom Psyche event type",
2403
3842
  responses: {
2404
- "201": jsonResponse({ type: "object", required: ["eventType"], properties: { eventType: { $ref: "#/components/schemas/EventType" } } }, "Created event type"),
3843
+ "201": jsonResponse({
3844
+ type: "object",
3845
+ required: ["eventType"],
3846
+ properties: {
3847
+ eventType: { $ref: "#/components/schemas/EventType" }
3848
+ }
3849
+ }, "Created event type"),
2405
3850
  default: { $ref: "#/components/responses/Error" }
2406
3851
  }
2407
3852
  }
@@ -2410,21 +3855,39 @@ export function buildOpenApiDocument() {
2410
3855
  get: {
2411
3856
  summary: "Get a Psyche event type",
2412
3857
  responses: {
2413
- "200": jsonResponse({ type: "object", required: ["eventType"], properties: { eventType: { $ref: "#/components/schemas/EventType" } } }, "Event type detail"),
3858
+ "200": jsonResponse({
3859
+ type: "object",
3860
+ required: ["eventType"],
3861
+ properties: {
3862
+ eventType: { $ref: "#/components/schemas/EventType" }
3863
+ }
3864
+ }, "Event type detail"),
2414
3865
  default: { $ref: "#/components/responses/Error" }
2415
3866
  }
2416
3867
  },
2417
3868
  patch: {
2418
3869
  summary: "Update a custom Psyche event type",
2419
3870
  responses: {
2420
- "200": jsonResponse({ type: "object", required: ["eventType"], properties: { eventType: { $ref: "#/components/schemas/EventType" } } }, "Updated event type"),
3871
+ "200": jsonResponse({
3872
+ type: "object",
3873
+ required: ["eventType"],
3874
+ properties: {
3875
+ eventType: { $ref: "#/components/schemas/EventType" }
3876
+ }
3877
+ }, "Updated event type"),
2421
3878
  default: { $ref: "#/components/responses/Error" }
2422
3879
  }
2423
3880
  },
2424
3881
  delete: {
2425
3882
  summary: "Delete a custom Psyche event type",
2426
3883
  responses: {
2427
- "200": jsonResponse({ type: "object", required: ["eventType"], properties: { eventType: { $ref: "#/components/schemas/EventType" } } }, "Deleted event type"),
3884
+ "200": jsonResponse({
3885
+ type: "object",
3886
+ required: ["eventType"],
3887
+ properties: {
3888
+ eventType: { $ref: "#/components/schemas/EventType" }
3889
+ }
3890
+ }, "Deleted event type"),
2428
3891
  default: { $ref: "#/components/responses/Error" }
2429
3892
  }
2430
3893
  }
@@ -2433,14 +3896,28 @@ export function buildOpenApiDocument() {
2433
3896
  get: {
2434
3897
  summary: "List seeded and custom Psyche emotions",
2435
3898
  responses: {
2436
- "200": jsonResponse({ type: "object", required: ["emotions"], properties: { emotions: arrayOf({ $ref: "#/components/schemas/EmotionDefinition" }) } }, "Emotion collection"),
3899
+ "200": jsonResponse({
3900
+ type: "object",
3901
+ required: ["emotions"],
3902
+ properties: {
3903
+ emotions: arrayOf({
3904
+ $ref: "#/components/schemas/EmotionDefinition"
3905
+ })
3906
+ }
3907
+ }, "Emotion collection"),
2437
3908
  default: { $ref: "#/components/responses/Error" }
2438
3909
  }
2439
3910
  },
2440
3911
  post: {
2441
3912
  summary: "Create a custom Psyche emotion",
2442
3913
  responses: {
2443
- "201": jsonResponse({ type: "object", required: ["emotion"], properties: { emotion: { $ref: "#/components/schemas/EmotionDefinition" } } }, "Created emotion"),
3914
+ "201": jsonResponse({
3915
+ type: "object",
3916
+ required: ["emotion"],
3917
+ properties: {
3918
+ emotion: { $ref: "#/components/schemas/EmotionDefinition" }
3919
+ }
3920
+ }, "Created emotion"),
2444
3921
  default: { $ref: "#/components/responses/Error" }
2445
3922
  }
2446
3923
  }
@@ -2449,21 +3926,39 @@ export function buildOpenApiDocument() {
2449
3926
  get: {
2450
3927
  summary: "Get a Psyche emotion definition",
2451
3928
  responses: {
2452
- "200": jsonResponse({ type: "object", required: ["emotion"], properties: { emotion: { $ref: "#/components/schemas/EmotionDefinition" } } }, "Emotion detail"),
3929
+ "200": jsonResponse({
3930
+ type: "object",
3931
+ required: ["emotion"],
3932
+ properties: {
3933
+ emotion: { $ref: "#/components/schemas/EmotionDefinition" }
3934
+ }
3935
+ }, "Emotion detail"),
2453
3936
  default: { $ref: "#/components/responses/Error" }
2454
3937
  }
2455
3938
  },
2456
3939
  patch: {
2457
3940
  summary: "Update a custom Psyche emotion definition",
2458
3941
  responses: {
2459
- "200": jsonResponse({ type: "object", required: ["emotion"], properties: { emotion: { $ref: "#/components/schemas/EmotionDefinition" } } }, "Updated emotion"),
3942
+ "200": jsonResponse({
3943
+ type: "object",
3944
+ required: ["emotion"],
3945
+ properties: {
3946
+ emotion: { $ref: "#/components/schemas/EmotionDefinition" }
3947
+ }
3948
+ }, "Updated emotion"),
2460
3949
  default: { $ref: "#/components/responses/Error" }
2461
3950
  }
2462
3951
  },
2463
3952
  delete: {
2464
3953
  summary: "Delete a custom Psyche emotion definition",
2465
3954
  responses: {
2466
- "200": jsonResponse({ type: "object", required: ["emotion"], properties: { emotion: { $ref: "#/components/schemas/EmotionDefinition" } } }, "Deleted emotion"),
3955
+ "200": jsonResponse({
3956
+ type: "object",
3957
+ required: ["emotion"],
3958
+ properties: {
3959
+ emotion: { $ref: "#/components/schemas/EmotionDefinition" }
3960
+ }
3961
+ }, "Deleted emotion"),
2467
3962
  default: { $ref: "#/components/responses/Error" }
2468
3963
  }
2469
3964
  }
@@ -2472,14 +3967,28 @@ export function buildOpenApiDocument() {
2472
3967
  get: {
2473
3968
  summary: "List trigger reports",
2474
3969
  responses: {
2475
- "200": jsonResponse({ type: "object", required: ["reports"], properties: { reports: arrayOf({ $ref: "#/components/schemas/TriggerReport" }) } }, "Trigger report collection"),
3970
+ "200": jsonResponse({
3971
+ type: "object",
3972
+ required: ["reports"],
3973
+ properties: {
3974
+ reports: arrayOf({
3975
+ $ref: "#/components/schemas/TriggerReport"
3976
+ })
3977
+ }
3978
+ }, "Trigger report collection"),
2476
3979
  default: { $ref: "#/components/responses/Error" }
2477
3980
  }
2478
3981
  },
2479
3982
  post: {
2480
3983
  summary: "Create a trigger report",
2481
3984
  responses: {
2482
- "201": jsonResponse({ type: "object", required: ["report"], properties: { report: { $ref: "#/components/schemas/TriggerReport" } } }, "Created trigger report"),
3985
+ "201": jsonResponse({
3986
+ type: "object",
3987
+ required: ["report"],
3988
+ properties: {
3989
+ report: { $ref: "#/components/schemas/TriggerReport" }
3990
+ }
3991
+ }, "Created trigger report"),
2483
3992
  default: { $ref: "#/components/responses/Error" }
2484
3993
  }
2485
3994
  }
@@ -2503,14 +4012,26 @@ export function buildOpenApiDocument() {
2503
4012
  patch: {
2504
4013
  summary: "Update a trigger report",
2505
4014
  responses: {
2506
- "200": jsonResponse({ type: "object", required: ["report"], properties: { report: { $ref: "#/components/schemas/TriggerReport" } } }, "Updated trigger report"),
4015
+ "200": jsonResponse({
4016
+ type: "object",
4017
+ required: ["report"],
4018
+ properties: {
4019
+ report: { $ref: "#/components/schemas/TriggerReport" }
4020
+ }
4021
+ }, "Updated trigger report"),
2507
4022
  default: { $ref: "#/components/responses/Error" }
2508
4023
  }
2509
4024
  },
2510
4025
  delete: {
2511
4026
  summary: "Delete a trigger report",
2512
4027
  responses: {
2513
- "200": jsonResponse({ type: "object", required: ["report"], properties: { report: { $ref: "#/components/schemas/TriggerReport" } } }, "Deleted trigger report"),
4028
+ "200": jsonResponse({
4029
+ type: "object",
4030
+ required: ["report"],
4031
+ properties: {
4032
+ report: { $ref: "#/components/schemas/TriggerReport" }
4033
+ }
4034
+ }, "Deleted trigger report"),
2514
4035
  default: { $ref: "#/components/responses/Error" }
2515
4036
  }
2516
4037
  }
@@ -2518,15 +4039,69 @@ export function buildOpenApiDocument() {
2518
4039
  "/api/v1/notes": {
2519
4040
  get: {
2520
4041
  summary: "List notes linked to Forge entities",
4042
+ parameters: [
4043
+ {
4044
+ name: "linkedEntityType",
4045
+ in: "query",
4046
+ schema: { type: "string" }
4047
+ },
4048
+ { name: "linkedEntityId", in: "query", schema: { type: "string" } },
4049
+ {
4050
+ name: "anchorKey",
4051
+ in: "query",
4052
+ schema: { type: "string", nullable: true }
4053
+ },
4054
+ {
4055
+ name: "linkedTo",
4056
+ in: "query",
4057
+ schema: { type: "array", items: { type: "string" } }
4058
+ },
4059
+ {
4060
+ name: "tags",
4061
+ in: "query",
4062
+ schema: { type: "array", items: { type: "string" } }
4063
+ },
4064
+ {
4065
+ name: "textTerms",
4066
+ in: "query",
4067
+ schema: { type: "array", items: { type: "string" } }
4068
+ },
4069
+ { name: "author", in: "query", schema: { type: "string" } },
4070
+ {
4071
+ name: "updatedFrom",
4072
+ in: "query",
4073
+ schema: { type: "string", format: "date" }
4074
+ },
4075
+ {
4076
+ name: "updatedTo",
4077
+ in: "query",
4078
+ schema: { type: "string", format: "date" }
4079
+ },
4080
+ {
4081
+ name: "limit",
4082
+ in: "query",
4083
+ schema: { type: "integer", minimum: 1, maximum: 200 }
4084
+ }
4085
+ ],
2521
4086
  responses: {
2522
- "200": jsonResponse({ type: "object", required: ["notes"], properties: { notes: arrayOf({ $ref: "#/components/schemas/Note" }) } }, "Note collection"),
4087
+ "200": jsonResponse({
4088
+ type: "object",
4089
+ required: ["notes"],
4090
+ properties: {
4091
+ notes: arrayOf({ $ref: "#/components/schemas/Note" })
4092
+ }
4093
+ }, "Note collection"),
2523
4094
  default: { $ref: "#/components/responses/Error" }
2524
4095
  }
2525
4096
  },
2526
4097
  post: {
2527
4098
  summary: "Create a note linked to one or more Forge entities",
2528
4099
  responses: {
2529
- "201": jsonResponse({ type: "object", required: ["note"], properties: { note: { $ref: "#/components/schemas/Note" } } }, "Created note"),
4100
+ "201": jsonResponse({
4101
+ type: "object",
4102
+ required: ["note"],
4103
+ properties: { note: { $ref: "#/components/schemas/Note" } }
4104
+ }, "Created note"),
2530
4105
  default: { $ref: "#/components/responses/Error" }
2531
4106
  }
2532
4107
  }
@@ -2535,21 +4110,33 @@ export function buildOpenApiDocument() {
2535
4110
  get: {
2536
4111
  summary: "Get a note",
2537
4112
  responses: {
2538
- "200": jsonResponse({ type: "object", required: ["note"], properties: { note: { $ref: "#/components/schemas/Note" } } }, "Note"),
4113
+ "200": jsonResponse({
4114
+ type: "object",
4115
+ required: ["note"],
4116
+ properties: { note: { $ref: "#/components/schemas/Note" } }
4117
+ }, "Note"),
2539
4118
  default: { $ref: "#/components/responses/Error" }
2540
4119
  }
2541
4120
  },
2542
4121
  patch: {
2543
4122
  summary: "Update a note",
2544
4123
  responses: {
2545
- "200": jsonResponse({ type: "object", required: ["note"], properties: { note: { $ref: "#/components/schemas/Note" } } }, "Updated note"),
4124
+ "200": jsonResponse({
4125
+ type: "object",
4126
+ required: ["note"],
4127
+ properties: { note: { $ref: "#/components/schemas/Note" } }
4128
+ }, "Updated note"),
2546
4129
  default: { $ref: "#/components/responses/Error" }
2547
4130
  }
2548
4131
  },
2549
4132
  delete: {
2550
4133
  summary: "Delete a note",
2551
4134
  responses: {
2552
- "200": jsonResponse({ type: "object", required: ["note"], properties: { note: { $ref: "#/components/schemas/Note" } } }, "Deleted note"),
4135
+ "200": jsonResponse({
4136
+ type: "object",
4137
+ required: ["note"],
4138
+ properties: { note: { $ref: "#/components/schemas/Note" } }
4139
+ }, "Deleted note"),
2553
4140
  default: { $ref: "#/components/responses/Error" }
2554
4141
  }
2555
4142
  }
@@ -2562,7 +4149,9 @@ export function buildOpenApiDocument() {
2562
4149
  type: "object",
2563
4150
  required: ["projects"],
2564
4151
  properties: {
2565
- projects: arrayOf({ $ref: "#/components/schemas/ProjectSummary" })
4152
+ projects: arrayOf({
4153
+ $ref: "#/components/schemas/ProjectSummary"
4154
+ })
2566
4155
  }
2567
4156
  }, "Project collection"),
2568
4157
  default: { $ref: "#/components/responses/Error" }
@@ -2582,6 +4171,214 @@ export function buildOpenApiDocument() {
2582
4171
  }
2583
4172
  }
2584
4173
  },
4174
+ "/api/v1/calendar/overview": {
4175
+ get: {
4176
+ summary: "Read connected calendars, mirrored events, work blocks, and timeboxes",
4177
+ responses: {
4178
+ "200": jsonResponse({
4179
+ type: "object",
4180
+ required: ["calendar"],
4181
+ properties: {
4182
+ calendar: {
4183
+ $ref: "#/components/schemas/CalendarOverviewPayload"
4184
+ }
4185
+ }
4186
+ }, "Calendar overview"),
4187
+ default: { $ref: "#/components/responses/Error" }
4188
+ }
4189
+ }
4190
+ },
4191
+ "/api/v1/calendar/connections": {
4192
+ get: {
4193
+ summary: "List connected calendar providers",
4194
+ responses: {
4195
+ "200": jsonResponse({
4196
+ type: "object",
4197
+ required: ["providers", "connections"],
4198
+ properties: {
4199
+ providers: arrayOf({
4200
+ type: "object",
4201
+ additionalProperties: false,
4202
+ required: [
4203
+ "provider",
4204
+ "label",
4205
+ "supportsDedicatedForgeCalendar",
4206
+ "connectionHelp"
4207
+ ],
4208
+ properties: {
4209
+ provider: {
4210
+ type: "string",
4211
+ enum: ["google", "apple", "caldav"]
4212
+ },
4213
+ label: { type: "string" },
4214
+ supportsDedicatedForgeCalendar: { type: "boolean" },
4215
+ connectionHelp: { type: "string" }
4216
+ }
4217
+ }),
4218
+ connections: arrayOf({
4219
+ $ref: "#/components/schemas/CalendarConnection"
4220
+ })
4221
+ }
4222
+ }, "Calendar connections"),
4223
+ default: { $ref: "#/components/responses/Error" }
4224
+ }
4225
+ },
4226
+ post: {
4227
+ summary: "Create a Google, Apple, or custom CalDAV calendar connection",
4228
+ description: "Forge first discovers the writable calendars for the account, then stores the chosen mirrored calendars and dedicated Forge write calendar.",
4229
+ responses: {
4230
+ "201": jsonResponse({
4231
+ type: "object",
4232
+ required: ["connection"],
4233
+ properties: {
4234
+ connection: {
4235
+ $ref: "#/components/schemas/CalendarConnection"
4236
+ }
4237
+ }
4238
+ }, "Created calendar connection"),
4239
+ default: { $ref: "#/components/responses/Error" }
4240
+ }
4241
+ }
4242
+ },
4243
+ "/api/v1/calendar/connections/{id}/sync": {
4244
+ post: {
4245
+ summary: "Sync one connected calendar provider",
4246
+ responses: {
4247
+ "200": jsonResponse({
4248
+ type: "object",
4249
+ required: ["connection"],
4250
+ properties: {
4251
+ connection: {
4252
+ $ref: "#/components/schemas/CalendarConnection"
4253
+ }
4254
+ }
4255
+ }, "Synced calendar connection"),
4256
+ default: { $ref: "#/components/responses/Error" }
4257
+ }
4258
+ }
4259
+ },
4260
+ "/api/v1/calendar/work-block-templates": {
4261
+ get: {
4262
+ summary: "List recurring work-block templates",
4263
+ responses: {
4264
+ "200": jsonResponse({
4265
+ type: "object",
4266
+ required: ["templates"],
4267
+ properties: {
4268
+ templates: arrayOf({
4269
+ $ref: "#/components/schemas/WorkBlockTemplate"
4270
+ })
4271
+ }
4272
+ }, "Work-block templates"),
4273
+ default: { $ref: "#/components/responses/Error" }
4274
+ }
4275
+ },
4276
+ post: {
4277
+ summary: "Create a recurring work-block template",
4278
+ responses: {
4279
+ "201": jsonResponse({
4280
+ type: "object",
4281
+ required: ["template"],
4282
+ properties: {
4283
+ template: { $ref: "#/components/schemas/WorkBlockTemplate" }
4284
+ }
4285
+ }, "Created work-block template"),
4286
+ default: { $ref: "#/components/responses/Error" }
4287
+ }
4288
+ }
4289
+ },
4290
+ "/api/v1/calendar/timeboxes": {
4291
+ get: {
4292
+ summary: "List task timeboxes",
4293
+ responses: {
4294
+ "200": jsonResponse({
4295
+ type: "object",
4296
+ required: ["timeboxes"],
4297
+ properties: {
4298
+ timeboxes: arrayOf({
4299
+ $ref: "#/components/schemas/TaskTimebox"
4300
+ })
4301
+ }
4302
+ }, "Task timeboxes"),
4303
+ default: { $ref: "#/components/responses/Error" }
4304
+ }
4305
+ },
4306
+ post: {
4307
+ summary: "Create a planned task timebox",
4308
+ responses: {
4309
+ "201": jsonResponse({
4310
+ type: "object",
4311
+ required: ["timebox"],
4312
+ properties: {
4313
+ timebox: { $ref: "#/components/schemas/TaskTimebox" }
4314
+ }
4315
+ }, "Created task timebox"),
4316
+ default: { $ref: "#/components/responses/Error" }
4317
+ }
4318
+ }
4319
+ },
4320
+ "/api/v1/calendar/timeboxes/recommend": {
4321
+ post: {
4322
+ summary: "Suggest future timeboxes for a task",
4323
+ description: "Recommendations consider provider events, work blocks, scheduling rules, and planned duration.",
4324
+ responses: {
4325
+ "200": jsonResponse({
4326
+ type: "object",
4327
+ required: ["timeboxes"],
4328
+ properties: {
4329
+ timeboxes: arrayOf({
4330
+ $ref: "#/components/schemas/TaskTimebox"
4331
+ })
4332
+ }
4333
+ }, "Suggested task timeboxes"),
4334
+ default: { $ref: "#/components/responses/Error" }
4335
+ }
4336
+ }
4337
+ },
4338
+ "/api/v1/calendar/events": {
4339
+ post: {
4340
+ summary: "Create a native Forge calendar event",
4341
+ description: "Forge stores the event canonically first, then projects it to a connected writable calendar when a preferred calendar is selected.",
4342
+ responses: {
4343
+ "201": jsonResponse({
4344
+ type: "object",
4345
+ required: ["event"],
4346
+ properties: {
4347
+ event: { $ref: "#/components/schemas/CalendarEvent" }
4348
+ }
4349
+ }, "Created calendar event"),
4350
+ default: { $ref: "#/components/responses/Error" }
4351
+ }
4352
+ }
4353
+ },
4354
+ "/api/v1/calendar/events/{id}": {
4355
+ patch: {
4356
+ summary: "Update a Forge calendar event and sync remote projections",
4357
+ responses: {
4358
+ "200": jsonResponse({
4359
+ type: "object",
4360
+ required: ["event"],
4361
+ properties: {
4362
+ event: { $ref: "#/components/schemas/CalendarEvent" }
4363
+ }
4364
+ }, "Updated calendar event"),
4365
+ default: { $ref: "#/components/responses/Error" }
4366
+ }
4367
+ },
4368
+ delete: {
4369
+ summary: "Delete a Forge calendar event and remove projected remote copies",
4370
+ responses: {
4371
+ "200": jsonResponse({
4372
+ type: "object",
4373
+ required: ["event"],
4374
+ properties: {
4375
+ event: { $ref: "#/components/schemas/CalendarEvent" }
4376
+ }
4377
+ }, "Deleted calendar event"),
4378
+ default: { $ref: "#/components/responses/Error" }
4379
+ }
4380
+ }
4381
+ },
2585
4382
  "/api/v1/campaigns": {
2586
4383
  get: {
2587
4384
  deprecated: true,
@@ -2591,7 +4388,9 @@ export function buildOpenApiDocument() {
2591
4388
  type: "object",
2592
4389
  required: ["projects"],
2593
4390
  properties: {
2594
- projects: arrayOf({ $ref: "#/components/schemas/ProjectSummary" })
4391
+ projects: arrayOf({
4392
+ $ref: "#/components/schemas/ProjectSummary"
4393
+ })
2595
4394
  }
2596
4395
  }, "Project collection"),
2597
4396
  default: { $ref: "#/components/responses/Error" }
@@ -2614,6 +4413,7 @@ export function buildOpenApiDocument() {
2614
4413
  },
2615
4414
  patch: {
2616
4415
  summary: "Update a project",
4416
+ description: "Project lifecycle is status-driven. Set status to paused to suspend, completed to finish, or active to restart. Updating a project to completed auto-completes linked unfinished tasks through the normal task completion flow.",
2617
4417
  responses: {
2618
4418
  "200": jsonResponse({
2619
4419
  type: "object",
@@ -2628,6 +4428,7 @@ export function buildOpenApiDocument() {
2628
4428
  },
2629
4429
  delete: {
2630
4430
  summary: "Delete a project",
4431
+ description: "Project DELETE defaults to soft delete. Pass mode=hard only when permanent removal is intended.",
2631
4432
  responses: {
2632
4433
  "200": jsonResponse({
2633
4434
  type: "object",
@@ -2718,6 +4519,90 @@ export function buildOpenApiDocument() {
2718
4519
  }
2719
4520
  }
2720
4521
  },
4522
+ "/api/v1/habits": {
4523
+ get: {
4524
+ summary: "List habits with current streak and due-today state",
4525
+ responses: {
4526
+ "200": jsonResponse({
4527
+ type: "object",
4528
+ required: ["habits"],
4529
+ properties: {
4530
+ habits: arrayOf({ $ref: "#/components/schemas/Habit" })
4531
+ }
4532
+ }, "Habit collection")
4533
+ }
4534
+ },
4535
+ post: {
4536
+ summary: "Create a habit",
4537
+ responses: {
4538
+ "201": jsonResponse({
4539
+ type: "object",
4540
+ required: ["habit"],
4541
+ properties: {
4542
+ habit: { $ref: "#/components/schemas/Habit" }
4543
+ }
4544
+ }, "Created habit"),
4545
+ default: { $ref: "#/components/responses/Error" }
4546
+ }
4547
+ }
4548
+ },
4549
+ "/api/v1/habits/{id}": {
4550
+ get: {
4551
+ summary: "Get a habit",
4552
+ responses: {
4553
+ "200": jsonResponse({
4554
+ type: "object",
4555
+ required: ["habit"],
4556
+ properties: {
4557
+ habit: { $ref: "#/components/schemas/Habit" }
4558
+ }
4559
+ }, "Habit"),
4560
+ "404": { $ref: "#/components/responses/Error" }
4561
+ }
4562
+ },
4563
+ patch: {
4564
+ summary: "Update a habit",
4565
+ responses: {
4566
+ "200": jsonResponse({
4567
+ type: "object",
4568
+ required: ["habit"],
4569
+ properties: {
4570
+ habit: { $ref: "#/components/schemas/Habit" }
4571
+ }
4572
+ }, "Updated habit"),
4573
+ "404": { $ref: "#/components/responses/Error" }
4574
+ }
4575
+ },
4576
+ delete: {
4577
+ summary: "Delete a habit",
4578
+ responses: {
4579
+ "200": jsonResponse({
4580
+ type: "object",
4581
+ required: ["habit"],
4582
+ properties: {
4583
+ habit: { $ref: "#/components/schemas/Habit" }
4584
+ }
4585
+ }, "Deleted habit"),
4586
+ "404": { $ref: "#/components/responses/Error" }
4587
+ }
4588
+ }
4589
+ },
4590
+ "/api/v1/habits/{id}/check-ins": {
4591
+ post: {
4592
+ summary: "Record a habit outcome for one day",
4593
+ responses: {
4594
+ "200": jsonResponse({
4595
+ type: "object",
4596
+ required: ["habit", "metrics"],
4597
+ properties: {
4598
+ habit: { $ref: "#/components/schemas/Habit" },
4599
+ metrics: { $ref: "#/components/schemas/XpMetricsPayload" }
4600
+ }
4601
+ }, "Habit check-in result"),
4602
+ "404": { $ref: "#/components/responses/Error" }
4603
+ }
4604
+ }
4605
+ },
2721
4606
  "/api/v1/tags": {
2722
4607
  get: {
2723
4608
  summary: "List tags",
@@ -2839,6 +4724,23 @@ export function buildOpenApiDocument() {
2839
4724
  }
2840
4725
  }
2841
4726
  },
4727
+ "/api/v1/work-adjustments": {
4728
+ post: {
4729
+ summary: "Add or remove tracked work minutes on an existing task or project and return fresh XP state",
4730
+ requestBody: {
4731
+ required: true,
4732
+ content: {
4733
+ "application/json": {
4734
+ schema: { $ref: "#/components/schemas/WorkAdjustmentInput" }
4735
+ }
4736
+ }
4737
+ },
4738
+ responses: {
4739
+ "201": jsonResponse({ $ref: "#/components/schemas/WorkAdjustmentResult" }, "Created work adjustment and refreshed XP state"),
4740
+ "404": { $ref: "#/components/responses/Error" }
4741
+ }
4742
+ }
4743
+ },
2842
4744
  "/api/v1/tasks/{id}": {
2843
4745
  get: {
2844
4746
  summary: "Get a task",
@@ -2939,9 +4841,20 @@ export function buildOpenApiDocument() {
2939
4841
  summary: "List task timers with optional task and active-state filters",
2940
4842
  parameters: [
2941
4843
  { name: "taskId", in: "query", schema: { type: "string" } },
2942
- { name: "status", in: "query", schema: { type: "string", enum: ["active", "completed", "released", "timed_out"] } },
4844
+ {
4845
+ name: "status",
4846
+ in: "query",
4847
+ schema: {
4848
+ type: "string",
4849
+ enum: ["active", "completed", "released", "timed_out"]
4850
+ }
4851
+ },
2943
4852
  { name: "active", in: "query", schema: { type: "boolean" } },
2944
- { name: "limit", in: "query", schema: { type: "integer", minimum: 1, maximum: 100 } }
4853
+ {
4854
+ name: "limit",
4855
+ in: "query",
4856
+ schema: { type: "integer", minimum: 1, maximum: 100 }
4857
+ }
2945
4858
  ],
2946
4859
  responses: {
2947
4860
  "200": jsonResponse({
@@ -3054,7 +4967,9 @@ export function buildOpenApiDocument() {
3054
4967
  type: "object",
3055
4968
  required: ["activity"],
3056
4969
  properties: {
3057
- activity: arrayOf({ $ref: "#/components/schemas/ActivityEvent" })
4970
+ activity: arrayOf({
4971
+ $ref: "#/components/schemas/ActivityEvent"
4972
+ })
3058
4973
  }
3059
4974
  }, "Activity archive")
3060
4975
  }
@@ -3088,9 +5003,15 @@ export function buildOpenApiDocument() {
3088
5003
  additionalProperties: false,
3089
5004
  required: ["profile", "achievements", "milestoneRewards"],
3090
5005
  properties: {
3091
- profile: { $ref: "#/components/schemas/GamificationProfile" },
3092
- achievements: arrayOf({ $ref: "#/components/schemas/AchievementSignal" }),
3093
- milestoneRewards: arrayOf({ $ref: "#/components/schemas/MilestoneReward" })
5006
+ profile: {
5007
+ $ref: "#/components/schemas/GamificationProfile"
5008
+ },
5009
+ achievements: arrayOf({
5010
+ $ref: "#/components/schemas/AchievementSignal"
5011
+ }),
5012
+ milestoneRewards: arrayOf({
5013
+ $ref: "#/components/schemas/MilestoneReward"
5014
+ })
3094
5015
  }
3095
5016
  }
3096
5017
  }
@@ -3166,7 +5087,11 @@ export function buildOpenApiDocument() {
3166
5087
  delete: {
3167
5088
  summary: "Soft delete or permanently delete a stored insight",
3168
5089
  parameters: [
3169
- { name: "mode", in: "query", schema: { type: "string", enum: ["soft", "hard"] } },
5090
+ {
5091
+ name: "mode",
5092
+ in: "query",
5093
+ schema: { type: "string", enum: ["soft", "hard"] }
5094
+ },
3170
5095
  { name: "reason", in: "query", schema: { type: "string" } }
3171
5096
  ],
3172
5097
  responses: {
@@ -3203,7 +5128,9 @@ export function buildOpenApiDocument() {
3203
5128
  type: "object",
3204
5129
  required: ["approvalRequests"],
3205
5130
  properties: {
3206
- approvalRequests: arrayOf({ $ref: "#/components/schemas/ApprovalRequest" })
5131
+ approvalRequests: arrayOf({
5132
+ $ref: "#/components/schemas/ApprovalRequest"
5133
+ })
3207
5134
  }
3208
5135
  }, "Approval requests")
3209
5136
  }
@@ -3217,7 +5144,9 @@ export function buildOpenApiDocument() {
3217
5144
  type: "object",
3218
5145
  required: ["approvalRequest"],
3219
5146
  properties: {
3220
- approvalRequest: { $ref: "#/components/schemas/ApprovalRequest" }
5147
+ approvalRequest: {
5148
+ $ref: "#/components/schemas/ApprovalRequest"
5149
+ }
3221
5150
  }
3222
5151
  }, "Approved request")
3223
5152
  }
@@ -3231,7 +5160,9 @@ export function buildOpenApiDocument() {
3231
5160
  type: "object",
3232
5161
  required: ["approvalRequest"],
3233
5162
  properties: {
3234
- approvalRequest: { $ref: "#/components/schemas/ApprovalRequest" }
5163
+ approvalRequest: {
5164
+ $ref: "#/components/schemas/ApprovalRequest"
5165
+ }
3235
5166
  }
3236
5167
  }, "Rejected request")
3237
5168
  }
@@ -3245,7 +5176,9 @@ export function buildOpenApiDocument() {
3245
5176
  type: "object",
3246
5177
  required: ["agents"],
3247
5178
  properties: {
3248
- agents: arrayOf({ $ref: "#/components/schemas/AgentIdentity" })
5179
+ agents: arrayOf({
5180
+ $ref: "#/components/schemas/AgentIdentity"
5181
+ })
3249
5182
  }
3250
5183
  }, "Agent identities")
3251
5184
  }
@@ -3259,7 +5192,9 @@ export function buildOpenApiDocument() {
3259
5192
  type: "object",
3260
5193
  required: ["onboarding"],
3261
5194
  properties: {
3262
- onboarding: { $ref: "#/components/schemas/AgentOnboardingPayload" }
5195
+ onboarding: {
5196
+ $ref: "#/components/schemas/AgentOnboardingPayload"
5197
+ }
3263
5198
  }
3264
5199
  }, "Agent onboarding payload")
3265
5200
  }
@@ -3288,7 +5223,9 @@ export function buildOpenApiDocument() {
3288
5223
  required: ["action", "approvalRequest"],
3289
5224
  properties: {
3290
5225
  action: { $ref: "#/components/schemas/AgentAction" },
3291
- approvalRequest: nullable({ $ref: "#/components/schemas/ApprovalRequest" })
5226
+ approvalRequest: nullable({
5227
+ $ref: "#/components/schemas/ApprovalRequest"
5228
+ })
3292
5229
  }
3293
5230
  }, "Executed agent action"),
3294
5231
  "202": jsonResponse({
@@ -3296,7 +5233,9 @@ export function buildOpenApiDocument() {
3296
5233
  required: ["action", "approvalRequest"],
3297
5234
  properties: {
3298
5235
  action: { $ref: "#/components/schemas/AgentAction" },
3299
- approvalRequest: nullable({ $ref: "#/components/schemas/ApprovalRequest" })
5236
+ approvalRequest: nullable({
5237
+ $ref: "#/components/schemas/ApprovalRequest"
5238
+ })
3300
5239
  }
3301
5240
  }, "Pending approval agent action")
3302
5241
  }
@@ -3352,7 +5291,9 @@ export function buildOpenApiDocument() {
3352
5291
  type: "object",
3353
5292
  required: ["ledger"],
3354
5293
  properties: {
3355
- ledger: arrayOf({ $ref: "#/components/schemas/RewardLedgerEvent" })
5294
+ ledger: arrayOf({
5295
+ $ref: "#/components/schemas/RewardLedgerEvent"
5296
+ })
3356
5297
  }
3357
5298
  }, "Reward ledger")
3358
5299
  }
@@ -3381,7 +5322,9 @@ export function buildOpenApiDocument() {
3381
5322
  type: "object",
3382
5323
  required: ["events"],
3383
5324
  properties: {
3384
- events: arrayOf({ $ref: "#/components/schemas/EventLogEntry" })
5325
+ events: arrayOf({
5326
+ $ref: "#/components/schemas/EventLogEntry"
5327
+ })
3385
5328
  }
3386
5329
  }, "Event log")
3387
5330
  }
@@ -3396,7 +5339,9 @@ export function buildOpenApiDocument() {
3396
5339
  required: ["sessionEvent", "rewardEvent"],
3397
5340
  properties: {
3398
5341
  sessionEvent: { type: "object", additionalProperties: true },
3399
- rewardEvent: nullable({ $ref: "#/components/schemas/RewardLedgerEvent" })
5342
+ rewardEvent: nullable({
5343
+ $ref: "#/components/schemas/RewardLedgerEvent"
5344
+ })
3400
5345
  }
3401
5346
  }, "Recorded session event")
3402
5347
  }
@@ -3416,6 +5361,91 @@ export function buildOpenApiDocument() {
3416
5361
  }
3417
5362
  }
3418
5363
  },
5364
+ "/api/v1/reviews/weekly/finalize": {
5365
+ post: {
5366
+ summary: "Finalize the current weekly review cycle",
5367
+ responses: {
5368
+ "200": jsonResponse({
5369
+ type: "object",
5370
+ required: ["review", "closure", "reward", "metrics"],
5371
+ properties: {
5372
+ review: { $ref: "#/components/schemas/WeeklyReviewPayload" },
5373
+ closure: {
5374
+ type: "object",
5375
+ required: [
5376
+ "id",
5377
+ "weekKey",
5378
+ "weekStartDate",
5379
+ "weekEndDate",
5380
+ "windowLabel",
5381
+ "actor",
5382
+ "source",
5383
+ "rewardId",
5384
+ "activityEventId",
5385
+ "createdAt"
5386
+ ],
5387
+ properties: {
5388
+ id: { type: "string" },
5389
+ weekKey: { type: "string" },
5390
+ weekStartDate: { type: "string" },
5391
+ weekEndDate: { type: "string" },
5392
+ windowLabel: { type: "string" },
5393
+ actor: nullable({ type: "string" }),
5394
+ source: {
5395
+ type: "string",
5396
+ enum: ["ui", "openclaw", "agent", "system"]
5397
+ },
5398
+ rewardId: { type: "string" },
5399
+ activityEventId: { type: "string" },
5400
+ createdAt: { type: "string", format: "date-time" }
5401
+ }
5402
+ },
5403
+ reward: { $ref: "#/components/schemas/RewardLedgerEvent" },
5404
+ metrics: { $ref: "#/components/schemas/XpMetricsPayload" }
5405
+ }
5406
+ }, "Existing weekly review closure"),
5407
+ "201": jsonResponse({
5408
+ type: "object",
5409
+ required: ["review", "closure", "reward", "metrics"],
5410
+ properties: {
5411
+ review: { $ref: "#/components/schemas/WeeklyReviewPayload" },
5412
+ closure: {
5413
+ type: "object",
5414
+ required: [
5415
+ "id",
5416
+ "weekKey",
5417
+ "weekStartDate",
5418
+ "weekEndDate",
5419
+ "windowLabel",
5420
+ "actor",
5421
+ "source",
5422
+ "rewardId",
5423
+ "activityEventId",
5424
+ "createdAt"
5425
+ ],
5426
+ properties: {
5427
+ id: { type: "string" },
5428
+ weekKey: { type: "string" },
5429
+ weekStartDate: { type: "string" },
5430
+ weekEndDate: { type: "string" },
5431
+ windowLabel: { type: "string" },
5432
+ actor: nullable({ type: "string" }),
5433
+ source: {
5434
+ type: "string",
5435
+ enum: ["ui", "openclaw", "agent", "system"]
5436
+ },
5437
+ rewardId: { type: "string" },
5438
+ activityEventId: { type: "string" },
5439
+ createdAt: { type: "string", format: "date-time" }
5440
+ }
5441
+ },
5442
+ reward: { $ref: "#/components/schemas/RewardLedgerEvent" },
5443
+ metrics: { $ref: "#/components/schemas/XpMetricsPayload" }
5444
+ }
5445
+ }, "Created weekly review closure")
5446
+ }
5447
+ }
5448
+ },
3419
5449
  "/api/v1/settings": {
3420
5450
  get: {
3421
5451
  summary: "Get local operator settings",
@@ -3472,7 +5502,9 @@ export function buildOpenApiDocument() {
3472
5502
  type: "object",
3473
5503
  required: ["results"],
3474
5504
  properties: {
3475
- results: arrayOf({ $ref: "#/components/schemas/BatchEntityResult" })
5505
+ results: arrayOf({
5506
+ $ref: "#/components/schemas/BatchEntityResult"
5507
+ })
3476
5508
  }
3477
5509
  }, "Batch create results")
3478
5510
  }
@@ -3486,7 +5518,9 @@ export function buildOpenApiDocument() {
3486
5518
  type: "object",
3487
5519
  required: ["results"],
3488
5520
  properties: {
3489
- results: arrayOf({ $ref: "#/components/schemas/BatchEntityResult" })
5521
+ results: arrayOf({
5522
+ $ref: "#/components/schemas/BatchEntityResult"
5523
+ })
3490
5524
  }
3491
5525
  }, "Batch update results")
3492
5526
  }
@@ -3500,7 +5534,9 @@ export function buildOpenApiDocument() {
3500
5534
  type: "object",
3501
5535
  required: ["results"],
3502
5536
  properties: {
3503
- results: arrayOf({ $ref: "#/components/schemas/BatchEntityResult" })
5537
+ results: arrayOf({
5538
+ $ref: "#/components/schemas/BatchEntityResult"
5539
+ })
3504
5540
  }
3505
5541
  }, "Batch delete results")
3506
5542
  }
@@ -3514,7 +5550,9 @@ export function buildOpenApiDocument() {
3514
5550
  type: "object",
3515
5551
  required: ["results"],
3516
5552
  properties: {
3517
- results: arrayOf({ $ref: "#/components/schemas/BatchEntityResult" })
5553
+ results: arrayOf({
5554
+ $ref: "#/components/schemas/BatchEntityResult"
5555
+ })
3518
5556
  }
3519
5557
  }, "Batch restore results")
3520
5558
  }
@@ -3528,7 +5566,9 @@ export function buildOpenApiDocument() {
3528
5566
  type: "object",
3529
5567
  required: ["results"],
3530
5568
  properties: {
3531
- results: arrayOf({ $ref: "#/components/schemas/BatchEntityResult" })
5569
+ results: arrayOf({
5570
+ $ref: "#/components/schemas/BatchEntityResult"
5571
+ })
3532
5572
  }
3533
5573
  }, "Batch search results")
3534
5574
  }
@@ -3542,7 +5582,9 @@ export function buildOpenApiDocument() {
3542
5582
  type: "object",
3543
5583
  required: ["token"],
3544
5584
  properties: {
3545
- token: { $ref: "#/components/schemas/AgentTokenMutationResult" }
5585
+ token: {
5586
+ $ref: "#/components/schemas/AgentTokenMutationResult"
5587
+ }
3546
5588
  }
3547
5589
  }, "Created agent token")
3548
5590
  }