forge-openclaw-plugin 0.2.19 → 0.2.21

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 (82) hide show
  1. package/README.md +133 -2
  2. package/dist/assets/board-_C6oMy5w.js +6 -0
  3. package/dist/assets/{board-8L3uX7_O.js.map → board-_C6oMy5w.js.map} +1 -1
  4. package/dist/assets/index-B4A6TooJ.js +63 -0
  5. package/dist/assets/index-B4A6TooJ.js.map +1 -0
  6. package/dist/assets/index-D6Xs_2mo.css +1 -0
  7. package/dist/assets/{motion-1GAqqi8M.js → motion-D4sZgCHd.js} +2 -2
  8. package/dist/assets/{motion-1GAqqi8M.js.map → motion-D4sZgCHd.js.map} +1 -1
  9. package/dist/assets/{table-DBGlgRjk.js → table-BWzTaky1.js} +2 -2
  10. package/dist/assets/{table-DBGlgRjk.js.map → table-BWzTaky1.js.map} +1 -1
  11. package/dist/assets/{ui-iTluWjC4.js → ui-BzK4azQb.js} +7 -7
  12. package/dist/assets/{ui-iTluWjC4.js.map → ui-BzK4azQb.js.map} +1 -1
  13. package/dist/assets/vendor-DT3pnAKJ.css +1 -0
  14. package/dist/assets/vendor-De38P6YR.js +729 -0
  15. package/dist/assets/vendor-De38P6YR.js.map +1 -0
  16. package/dist/assets/viz-C6hfyqzu.js +34 -0
  17. package/dist/assets/viz-C6hfyqzu.js.map +1 -0
  18. package/dist/index.html +9 -9
  19. package/dist/openclaw/parity.d.ts +1 -1
  20. package/dist/openclaw/parity.js +29 -2
  21. package/dist/openclaw/routes.js +207 -24
  22. package/dist/openclaw/tools.js +324 -35
  23. package/dist/server/app.js +2080 -92
  24. package/dist/server/db.js +3 -0
  25. package/dist/server/health.js +1284 -0
  26. package/dist/server/managers/platform/background-job-manager.js +138 -2
  27. package/dist/server/managers/platform/llm-manager.js +126 -0
  28. package/dist/server/managers/platform/openai-responses-provider.js +773 -0
  29. package/dist/server/managers/runtime.js +6 -1
  30. package/dist/server/openapi.js +718 -0
  31. package/dist/server/preferences-seeds.js +409 -0
  32. package/dist/server/preferences-types.js +368 -0
  33. package/dist/server/psyche-types.js +42 -18
  34. package/dist/server/repositories/activity-events.js +53 -4
  35. package/dist/server/repositories/calendar.js +89 -15
  36. package/dist/server/repositories/collaboration.js +8 -3
  37. package/dist/server/repositories/diagnostic-logs.js +243 -0
  38. package/dist/server/repositories/entity-ownership.js +92 -0
  39. package/dist/server/repositories/goals.js +7 -2
  40. package/dist/server/repositories/habits.js +122 -16
  41. package/dist/server/repositories/notes.js +119 -41
  42. package/dist/server/repositories/preferences.js +1765 -0
  43. package/dist/server/repositories/projects.js +18 -7
  44. package/dist/server/repositories/psyche.js +84 -27
  45. package/dist/server/repositories/rewards.js +112 -4
  46. package/dist/server/repositories/strategies.js +450 -0
  47. package/dist/server/repositories/tags.js +11 -6
  48. package/dist/server/repositories/task-runs.js +10 -2
  49. package/dist/server/repositories/tasks.js +99 -17
  50. package/dist/server/repositories/users.js +417 -0
  51. package/dist/server/repositories/wiki-memory.js +3366 -0
  52. package/dist/server/services/context.js +20 -18
  53. package/dist/server/services/dashboard.js +29 -6
  54. package/dist/server/services/entity-crud.js +21 -3
  55. package/dist/server/services/insights.js +9 -7
  56. package/dist/server/services/projects.js +2 -1
  57. package/dist/server/services/psyche.js +10 -9
  58. package/dist/server/types.js +594 -30
  59. package/openclaw.plugin.json +1 -1
  60. package/package.json +1 -1
  61. package/server/migrations/015_multi_user_and_strategies.sql +244 -0
  62. package/server/migrations/016_health_companion.sql +158 -0
  63. package/server/migrations/016_strategy_contracts_and_user_graph.sql +22 -0
  64. package/server/migrations/017_preferences.sql +131 -0
  65. package/server/migrations/018_preference_catalogs.sql +31 -0
  66. package/server/migrations/019_wiki_memory.sql +255 -0
  67. package/server/migrations/020_wiki_page_hierarchy.sql +11 -0
  68. package/server/migrations/021_hide_evidence_from_wiki_index.sql +3 -0
  69. package/server/migrations/022_wiki_ingest_background.sql +85 -0
  70. package/server/migrations/023_diagnostic_logs.sql +28 -0
  71. package/skills/forge-openclaw/SKILL.md +126 -34
  72. package/skills/forge-openclaw/entity_conversation_playbooks.md +337 -0
  73. package/skills/forge-openclaw/psyche_entity_playbooks.md +404 -0
  74. package/dist/assets/board-8L3uX7_O.js +0 -6
  75. package/dist/assets/index-Cj1IBH_w.js +0 -36
  76. package/dist/assets/index-Cj1IBH_w.js.map +0 -1
  77. package/dist/assets/index-DQT6EbuS.css +0 -1
  78. package/dist/assets/vendor-BvM2F9Dp.js +0 -503
  79. package/dist/assets/vendor-BvM2F9Dp.js.map +0 -1
  80. package/dist/assets/vendor-CRS-psbw.css +0 -1
  81. package/dist/assets/viz-CNeunkfu.js +0 -34
  82. package/dist/assets/viz-CNeunkfu.js.map +0 -1
@@ -14,6 +14,9 @@ export const goalHorizonSchema = z.enum(["quarter", "year", "lifetime"]);
14
14
  export const projectStatusSchema = z.enum(["active", "paused", "completed"]);
15
15
  export const tagKindSchema = z.enum(["value", "category", "execution"]);
16
16
  export const taskDueFilterSchema = z.enum(["overdue", "today", "week"]);
17
+ export const userKindSchema = z.enum(["human", "bot"]);
18
+ export const userAccessLevelSchema = z.enum(["view", "manage"]);
19
+ export const strategyStatusSchema = z.enum(["active", "paused", "completed"]);
17
20
  export const taskRunStatusSchema = z.enum([
18
21
  "active",
19
22
  "completed",
@@ -81,6 +84,7 @@ export const activityEntityTypeSchema = z.enum([
81
84
  "habit",
82
85
  "goal",
83
86
  "project",
87
+ "strategy",
84
88
  "domain",
85
89
  "psyche_value",
86
90
  "behavior_pattern",
@@ -113,6 +117,19 @@ export const activitySourceSchema = z.enum([
113
117
  "agent",
114
118
  "system"
115
119
  ]);
120
+ export const diagnosticLogLevelSchema = z.enum([
121
+ "debug",
122
+ "info",
123
+ "warning",
124
+ "error"
125
+ ]);
126
+ export const diagnosticLogSourceSchema = z.enum([
127
+ "ui",
128
+ "openclaw",
129
+ "agent",
130
+ "system",
131
+ "server"
132
+ ]);
116
133
  export const agentTrustLevelSchema = z.enum([
117
134
  "standard",
118
135
  "trusted",
@@ -166,6 +183,7 @@ export const crudEntityTypeSchema = z.enum([
166
183
  "goal",
167
184
  "project",
168
185
  "task",
186
+ "strategy",
169
187
  "habit",
170
188
  "tag",
171
189
  "note",
@@ -200,6 +218,14 @@ export const rewardableEntityTypeSchema = z.enum([
200
218
  "trigger_report"
201
219
  ]);
202
220
  export const deleteModeSchema = z.enum(["soft", "hard"]);
221
+ export const noteKindSchema = z.enum(["evidence", "wiki"]);
222
+ export const wikiSpaceVisibilitySchema = z.enum(["personal", "shared"]);
223
+ export const wikiSearchModeSchema = z.enum([
224
+ "text",
225
+ "semantic",
226
+ "entity",
227
+ "hybrid"
228
+ ]);
203
229
  export const rewardRuleFamilySchema = z.enum([
204
230
  "completion",
205
231
  "consistency",
@@ -239,6 +265,13 @@ const dateOnlySchema = trimmedString.refine(isValidDateOnly, {
239
265
  const dateTimeSchema = trimmedString.refine(isValidDateTime, {
240
266
  message: "Expected a valid ISO date-time string"
241
267
  });
268
+ const flexibleCalendarQueryDateSchema = trimmedString
269
+ .refine((value) => isValidDateOnly(value) || isValidDateTime(value), {
270
+ message: "Expected a valid ISO date-time string or YYYY-MM-DD date"
271
+ })
272
+ .transform((value) => isValidDateOnly(value)
273
+ ? `${value}T00:00:00.000Z`
274
+ : new Date(value).toISOString());
242
275
  const uniqueStringArraySchema = z
243
276
  .array(nonEmptyTrimmedString)
244
277
  .superRefine((values, context) => {
@@ -280,12 +313,85 @@ export const calendarContextConflictSchema = z.object({
280
313
  startsAt: z.string(),
281
314
  endsAt: z.string()
282
315
  });
316
+ export const userSummarySchema = z.object({
317
+ id: z.string(),
318
+ kind: userKindSchema,
319
+ handle: nonEmptyTrimmedString,
320
+ displayName: nonEmptyTrimmedString,
321
+ description: trimmedString,
322
+ accentColor: z.string(),
323
+ createdAt: z.string(),
324
+ updatedAt: z.string()
325
+ });
326
+ export const userAccessRightsSchema = z.object({
327
+ discoverable: z.boolean().default(true),
328
+ canListUsers: z.boolean().default(true),
329
+ canReadProfile: z.boolean().default(true),
330
+ canReadEntities: z.boolean().default(true),
331
+ canSearchEntities: z.boolean().default(true),
332
+ canLinkEntities: z.boolean().default(true),
333
+ canCoordinate: z.boolean().default(true),
334
+ canAffectEntities: z.boolean().default(true),
335
+ canManageStrategies: z.boolean().default(true),
336
+ canCreateOnBehalf: z.boolean().default(true),
337
+ canViewMetrics: z.boolean().default(true),
338
+ canViewActivity: z.boolean().default(true)
339
+ });
340
+ export const userAccessGrantConfigSchema = z.object({
341
+ self: z.boolean().default(false),
342
+ mutable: z.boolean().default(false),
343
+ linkedEntities: z.boolean().default(true),
344
+ rights: userAccessRightsSchema.default({})
345
+ });
346
+ export const userAccessGrantSchema = z.object({
347
+ id: z.string(),
348
+ subjectUserId: z.string(),
349
+ targetUserId: z.string(),
350
+ accessLevel: userAccessLevelSchema,
351
+ config: userAccessGrantConfigSchema,
352
+ createdAt: z.string(),
353
+ updatedAt: z.string(),
354
+ subjectUser: userSummarySchema.nullable().default(null),
355
+ targetUser: userSummarySchema.nullable().default(null)
356
+ });
357
+ export const updateUserAccessGrantSchema = z.object({
358
+ accessLevel: userAccessLevelSchema.optional(),
359
+ rights: userAccessRightsSchema.partial().optional()
360
+ });
361
+ export const userOwnershipSummarySchema = z.object({
362
+ userId: z.string(),
363
+ totalOwnedEntities: z.number().int().nonnegative(),
364
+ entityCounts: z.record(z.string(), z.number().int().nonnegative())
365
+ });
366
+ export const userXpSummarySchema = z.object({
367
+ userId: z.string(),
368
+ totalXp: z.number().int(),
369
+ weeklyXp: z.number().int(),
370
+ rewardEventCount: z.number().int().nonnegative(),
371
+ lastRewardAt: z.string().nullable()
372
+ });
373
+ export const userDirectoryPayloadSchema = z.object({
374
+ users: z.array(userSummarySchema),
375
+ grants: z.array(userAccessGrantSchema),
376
+ ownership: z.array(userOwnershipSummarySchema),
377
+ xp: z.array(userXpSummarySchema),
378
+ posture: z.object({
379
+ accessModel: z.enum(["permissive", "directional_graph"]),
380
+ summary: z.string(),
381
+ futureReady: z.boolean()
382
+ })
383
+ });
384
+ const ownershipShape = {
385
+ userId: z.string().nullable().default(null),
386
+ user: userSummarySchema.nullable().default(null)
387
+ };
283
388
  export const tagSchema = z.object({
284
389
  id: z.string(),
285
390
  name: nonEmptyTrimmedString,
286
391
  kind: tagKindSchema,
287
392
  color: z.string(),
288
- description: z.string()
393
+ description: z.string(),
394
+ ...ownershipShape
289
395
  });
290
396
  export const taskTimeSummarySchema = z.object({
291
397
  totalTrackedSeconds: z.number().int().nonnegative(),
@@ -351,15 +457,29 @@ const uniqueNoteTagArraySchema = z
351
457
  });
352
458
  export const noteSchema = z.object({
353
459
  id: z.string(),
460
+ kind: noteKindSchema.default("evidence"),
461
+ title: nonEmptyTrimmedString,
462
+ slug: nonEmptyTrimmedString,
463
+ spaceId: nonEmptyTrimmedString,
464
+ parentSlug: trimmedString.nullable().default(null),
465
+ indexOrder: z.number().int().default(0),
466
+ showInIndex: z.boolean().default(true),
467
+ aliases: uniqueStringArraySchema.default([]),
468
+ summary: trimmedString.default(""),
354
469
  contentMarkdown: nonEmptyTrimmedString,
355
470
  contentPlain: trimmedString,
356
471
  author: z.string().nullable(),
357
472
  source: activitySourceSchema,
473
+ sourcePath: trimmedString.default(""),
474
+ frontmatter: z.record(z.string(), z.unknown()).default({}),
475
+ revisionHash: trimmedString.default(""),
476
+ lastSyncedAt: dateTimeSchema.nullable().default(null),
358
477
  createdAt: z.string(),
359
478
  updatedAt: z.string(),
360
- links: z.array(noteLinkSchema).min(1),
479
+ links: z.array(noteLinkSchema).default([]),
361
480
  tags: uniqueNoteTagArraySchema.default([]),
362
- destroyAt: dateTimeSchema.nullable().default(null)
481
+ destroyAt: dateTimeSchema.nullable().default(null),
482
+ ...ownershipShape
363
483
  });
364
484
  export const noteSummarySchema = z.object({
365
485
  count: z.number().int().nonnegative(),
@@ -377,7 +497,8 @@ export const goalSchema = z.object({
377
497
  themeColor: z.string(),
378
498
  createdAt: z.string(),
379
499
  updatedAt: z.string(),
380
- tagIds: uniqueStringArraySchema.default([])
500
+ tagIds: uniqueStringArraySchema.default([]),
501
+ ...ownershipShape
381
502
  });
382
503
  export const projectSchema = z.object({
383
504
  id: z.string(),
@@ -400,7 +521,8 @@ export const projectSchema = z.object({
400
521
  blockAvailability: []
401
522
  }),
402
523
  createdAt: z.string(),
403
- updatedAt: z.string()
524
+ updatedAt: z.string(),
525
+ ...ownershipShape
404
526
  });
405
527
  export const taskSchema = z.object({
406
528
  id: z.string(),
@@ -428,6 +550,7 @@ export const taskSchema = z.object({
428
550
  createdAt: z.string(),
429
551
  updatedAt: z.string(),
430
552
  tagIds: z.array(z.string()).default([]),
553
+ ...ownershipShape,
431
554
  time: taskTimeSummarySchema.default({
432
555
  totalTrackedSeconds: 0,
433
556
  totalCreditedSeconds: 0,
@@ -461,7 +584,8 @@ export const taskRunSchema = z.object({
461
584
  releasedAt: z.string().nullable(),
462
585
  timedOutAt: z.string().nullable(),
463
586
  overrideReason: trimmedString.nullable().default(null),
464
- updatedAt: z.string()
587
+ updatedAt: z.string(),
588
+ ...ownershipShape
465
589
  });
466
590
  export const calendarConnectionSchema = z.object({
467
591
  id: z.string(),
@@ -554,6 +678,25 @@ export const calendarEventSchema = z.object({
554
678
  title: nonEmptyTrimmedString,
555
679
  description: trimmedString,
556
680
  location: trimmedString,
681
+ place: z
682
+ .object({
683
+ label: trimmedString,
684
+ address: trimmedString,
685
+ timezone: trimmedString,
686
+ latitude: z.number().nullable(),
687
+ longitude: z.number().nullable(),
688
+ source: trimmedString,
689
+ externalPlaceId: trimmedString
690
+ })
691
+ .default({
692
+ label: "",
693
+ address: "",
694
+ timezone: "",
695
+ latitude: null,
696
+ longitude: null,
697
+ source: "",
698
+ externalPlaceId: ""
699
+ }),
557
700
  startAt: z.string(),
558
701
  endAt: z.string(),
559
702
  timezone: nonEmptyTrimmedString,
@@ -566,7 +709,8 @@ export const calendarEventSchema = z.object({
566
709
  remoteUpdatedAt: z.string().nullable(),
567
710
  deletedAt: z.string().nullable(),
568
711
  createdAt: z.string(),
569
- updatedAt: z.string()
712
+ updatedAt: z.string(),
713
+ ...ownershipShape
570
714
  });
571
715
  export const workBlockTemplateSchema = z
572
716
  .object({
@@ -582,7 +726,8 @@ export const workBlockTemplateSchema = z
582
726
  endsOn: dateOnlySchema.nullable().default(null),
583
727
  blockingState: z.enum(["allowed", "blocked"]),
584
728
  createdAt: z.string(),
585
- updatedAt: z.string()
729
+ updatedAt: z.string(),
730
+ ...ownershipShape
586
731
  })
587
732
  .superRefine((value, context) => {
588
733
  if (value.endMinute <= value.startMinute) {
@@ -629,7 +774,8 @@ export const taskTimeboxSchema = z.object({
629
774
  endsAt: z.string(),
630
775
  overrideReason: trimmedString.nullable(),
631
776
  createdAt: z.string(),
632
- updatedAt: z.string()
777
+ updatedAt: z.string(),
778
+ ...ownershipShape
633
779
  });
634
780
  export const calendarOverviewPayloadSchema = z.object({
635
781
  generatedAt: z.string(),
@@ -679,6 +825,38 @@ export const habitSchema = z.object({
679
825
  linkedBehaviorTitles: z.array(z.string()).default([]),
680
826
  rewardXp: z.number().int().positive(),
681
827
  penaltyXp: z.number().int().positive(),
828
+ generatedHealthEventTemplate: z
829
+ .object({
830
+ enabled: z.boolean().default(false),
831
+ workoutType: trimmedString.default("workout"),
832
+ title: trimmedString.default(""),
833
+ durationMinutes: z
834
+ .number()
835
+ .int()
836
+ .positive()
837
+ .max(24 * 60)
838
+ .default(45),
839
+ xpReward: z.number().int().min(0).max(500).default(0),
840
+ tags: uniqueStringArraySchema.default([]),
841
+ links: z
842
+ .array(z.object({
843
+ entityType: trimmedString,
844
+ entityId: nonEmptyTrimmedString,
845
+ relationshipType: trimmedString.default("context")
846
+ }))
847
+ .default([]),
848
+ notesTemplate: trimmedString.default("")
849
+ })
850
+ .default({
851
+ enabled: false,
852
+ workoutType: "workout",
853
+ title: "",
854
+ durationMinutes: 45,
855
+ xpReward: 0,
856
+ tags: [],
857
+ links: [],
858
+ notesTemplate: ""
859
+ }),
682
860
  createdAt: z.string(),
683
861
  updatedAt: z.string(),
684
862
  lastCheckInAt: z.string().nullable(),
@@ -686,7 +864,8 @@ export const habitSchema = z.object({
686
864
  streakCount: z.number().int().nonnegative(),
687
865
  completionRate: z.number().min(0).max(100),
688
866
  dueToday: z.boolean(),
689
- checkIns: z.array(habitCheckInSchema).default([])
867
+ checkIns: z.array(habitCheckInSchema).default([]),
868
+ ...ownershipShape
690
869
  });
691
870
  export const activityEventSchema = z.object({
692
871
  id: z.string(),
@@ -698,7 +877,8 @@ export const activityEventSchema = z.object({
698
877
  actor: z.string().nullable(),
699
878
  source: activitySourceSchema,
700
879
  metadata: z.record(z.string(), z.union([z.string(), z.number(), z.boolean(), z.null()])),
701
- createdAt: z.string()
880
+ createdAt: z.string(),
881
+ ...ownershipShape
702
882
  });
703
883
  export const dashboardGoalSchema = goalSchema.extend({
704
884
  progress: z.number().min(0).max(100),
@@ -1072,6 +1252,22 @@ export const eventLogEntrySchema = z.object({
1072
1252
  metadata: z.record(z.string(), z.union([z.string(), z.number(), z.boolean(), z.null()])),
1073
1253
  createdAt: z.string()
1074
1254
  });
1255
+ export const diagnosticLogEntrySchema = z.object({
1256
+ id: z.string(),
1257
+ level: diagnosticLogLevelSchema,
1258
+ source: diagnosticLogSourceSchema,
1259
+ scope: z.string(),
1260
+ eventKey: z.string(),
1261
+ message: z.string(),
1262
+ route: z.string().nullable(),
1263
+ functionName: z.string().nullable(),
1264
+ requestId: z.string().nullable(),
1265
+ entityType: z.string().nullable(),
1266
+ entityId: z.string().nullable(),
1267
+ jobId: z.string().nullable(),
1268
+ details: z.record(z.string(), z.unknown()),
1269
+ createdAt: z.string()
1270
+ });
1075
1271
  export const insightEvidenceSchema = z.object({
1076
1272
  entityType: z.string(),
1077
1273
  entityId: z.string(),
@@ -1095,7 +1291,8 @@ export const insightSchema = z.object({
1095
1291
  ctaLabel: z.string(),
1096
1292
  evidence: z.array(insightEvidenceSchema),
1097
1293
  createdAt: z.string(),
1098
- updatedAt: z.string()
1294
+ updatedAt: z.string(),
1295
+ ...ownershipShape
1099
1296
  });
1100
1297
  export const insightFeedbackSchema = z.object({
1101
1298
  id: z.string(),
@@ -1307,28 +1504,70 @@ function parseLinkedEntityQueryValue(raw) {
1307
1504
  };
1308
1505
  }
1309
1506
  export const createNoteSchema = z.object({
1507
+ kind: noteKindSchema.default("evidence"),
1508
+ title: trimmedString.optional(),
1509
+ slug: trimmedString.optional(),
1510
+ spaceId: trimmedString.optional(),
1511
+ parentSlug: trimmedString.nullable().optional(),
1512
+ indexOrder: z.number().int().default(0),
1513
+ showInIndex: z.boolean().optional(),
1514
+ aliases: uniqueStringArraySchema.default([]),
1515
+ summary: trimmedString.default(""),
1310
1516
  contentMarkdown: nonEmptyTrimmedString,
1311
1517
  author: trimmedString.nullable().default(null),
1312
- links: z.array(createNoteLinkSchema).min(1),
1518
+ links: z.array(createNoteLinkSchema).default([]),
1313
1519
  tags: uniqueNoteTagArraySchema.default([]),
1314
- destroyAt: dateTimeSchema.nullable().default(null)
1520
+ destroyAt: dateTimeSchema.nullable().default(null),
1521
+ sourcePath: trimmedString.default(""),
1522
+ frontmatter: z.record(z.string(), z.unknown()).default({}),
1523
+ revisionHash: trimmedString.default(""),
1524
+ lastSyncedAt: dateTimeSchema.nullable().optional(),
1525
+ userId: nonEmptyTrimmedString.nullable().optional()
1315
1526
  });
1316
1527
  export const nestedCreateNoteSchema = z.object({
1528
+ kind: noteKindSchema.default("evidence"),
1529
+ title: trimmedString.optional(),
1530
+ slug: trimmedString.optional(),
1531
+ spaceId: trimmedString.optional(),
1532
+ parentSlug: trimmedString.nullable().optional(),
1533
+ indexOrder: z.number().int().default(0),
1534
+ showInIndex: z.boolean().optional(),
1535
+ aliases: uniqueStringArraySchema.default([]),
1536
+ summary: trimmedString.default(""),
1317
1537
  contentMarkdown: nonEmptyTrimmedString,
1318
1538
  author: trimmedString.nullable().default(null),
1319
1539
  links: z.array(createNoteLinkSchema).default([]),
1320
1540
  tags: uniqueNoteTagArraySchema.default([]),
1321
- destroyAt: dateTimeSchema.nullable().default(null)
1541
+ destroyAt: dateTimeSchema.nullable().default(null),
1542
+ sourcePath: trimmedString.default(""),
1543
+ frontmatter: z.record(z.string(), z.unknown()).default({})
1322
1544
  });
1323
1545
  export const updateNoteSchema = z.object({
1546
+ kind: noteKindSchema.optional(),
1547
+ title: trimmedString.optional(),
1548
+ slug: trimmedString.optional(),
1549
+ spaceId: trimmedString.optional(),
1550
+ parentSlug: trimmedString.nullable().optional(),
1551
+ indexOrder: z.number().int().optional(),
1552
+ showInIndex: z.boolean().optional(),
1553
+ aliases: uniqueStringArraySchema.optional(),
1554
+ summary: trimmedString.optional(),
1324
1555
  contentMarkdown: nonEmptyTrimmedString.optional(),
1325
1556
  author: trimmedString.nullable().optional(),
1326
- links: z.array(createNoteLinkSchema).min(1).optional(),
1557
+ links: z.array(createNoteLinkSchema).optional(),
1327
1558
  tags: uniqueNoteTagArraySchema.optional(),
1328
- destroyAt: dateTimeSchema.nullable().optional()
1559
+ destroyAt: dateTimeSchema.nullable().optional(),
1560
+ sourcePath: trimmedString.optional(),
1561
+ frontmatter: z.record(z.string(), z.unknown()).optional(),
1562
+ revisionHash: trimmedString.optional(),
1563
+ lastSyncedAt: dateTimeSchema.nullable().optional(),
1564
+ userId: nonEmptyTrimmedString.nullable().optional()
1329
1565
  });
1330
1566
  export const notesListQuerySchema = z
1331
1567
  .object({
1568
+ kind: noteKindSchema.optional(),
1569
+ spaceId: trimmedString.optional(),
1570
+ slug: trimmedString.optional(),
1332
1571
  linkedEntityType: crudEntityTypeSchema.optional(),
1333
1572
  linkedEntityId: nonEmptyTrimmedString.optional(),
1334
1573
  anchorKey: trimmedString.nullable().optional(),
@@ -1355,6 +1594,7 @@ export const notesListQuerySchema = z
1355
1594
  })),
1356
1595
  tags: repeatedTrimmedStringQuerySchema,
1357
1596
  textTerms: repeatedTrimmedStringQuerySchema,
1597
+ userIds: repeatedTrimmedStringQuerySchema,
1358
1598
  updatedFrom: dateOnlySchema.optional(),
1359
1599
  updatedTo: dateOnlySchema.optional(),
1360
1600
  limit: z.coerce.number().int().positive().max(200).optional()
@@ -1385,12 +1625,14 @@ export const taskListQuerySchema = z.object({
1385
1625
  projectId: nonEmptyTrimmedString.optional(),
1386
1626
  tagId: nonEmptyTrimmedString.optional(),
1387
1627
  due: taskDueFilterSchema.optional(),
1628
+ userIds: repeatedTrimmedStringQuerySchema.optional(),
1388
1629
  limit: z.coerce.number().int().positive().max(100).optional()
1389
1630
  });
1390
1631
  export const taskRunListQuerySchema = z.object({
1391
1632
  taskId: nonEmptyTrimmedString.optional(),
1392
1633
  status: taskRunStatusSchema.optional(),
1393
1634
  active: z.coerce.boolean().optional(),
1635
+ userIds: repeatedTrimmedStringQuerySchema.optional(),
1394
1636
  limit: z.coerce.number().int().positive().max(100).optional()
1395
1637
  });
1396
1638
  export const activityListQuerySchema = z.object({
@@ -1398,16 +1640,26 @@ export const activityListQuerySchema = z.object({
1398
1640
  entityId: nonEmptyTrimmedString.optional(),
1399
1641
  source: activitySourceSchema.optional(),
1400
1642
  includeCorrected: z.coerce.boolean().optional(),
1643
+ userIds: repeatedTrimmedStringQuerySchema.optional(),
1644
+ limit: z.coerce.number().int().positive().max(100).optional()
1645
+ });
1646
+ export const goalListQuerySchema = z.object({
1647
+ status: goalStatusSchema.optional(),
1648
+ horizon: goalHorizonSchema.optional(),
1649
+ tagId: nonEmptyTrimmedString.optional(),
1650
+ userIds: repeatedTrimmedStringQuerySchema.optional(),
1401
1651
  limit: z.coerce.number().int().positive().max(100).optional()
1402
1652
  });
1403
1653
  export const projectListQuerySchema = z.object({
1404
1654
  goalId: nonEmptyTrimmedString.optional(),
1405
1655
  status: projectStatusSchema.optional(),
1656
+ userIds: repeatedTrimmedStringQuerySchema.optional(),
1406
1657
  limit: z.coerce.number().int().positive().max(100).optional()
1407
1658
  });
1408
1659
  export const calendarOverviewQuerySchema = z.object({
1409
- from: z.string().datetime().optional(),
1410
- to: z.string().datetime().optional()
1660
+ from: flexibleCalendarQueryDateSchema.optional(),
1661
+ to: flexibleCalendarQueryDateSchema.optional(),
1662
+ userIds: repeatedTrimmedStringQuerySchema.optional()
1411
1663
  });
1412
1664
  export const createCalendarConnectionSchema = z.discriminatedUnion("provider", [
1413
1665
  z.object({
@@ -1500,7 +1752,8 @@ const workBlockTemplateMutationShape = {
1500
1752
  endMinute: integerMinuteSchema,
1501
1753
  startsOn: dateOnlySchema.nullable().optional(),
1502
1754
  endsOn: dateOnlySchema.nullable().optional(),
1503
- blockingState: z.enum(["allowed", "blocked"]).default("blocked")
1755
+ blockingState: z.enum(["allowed", "blocked"]).default("blocked"),
1756
+ userId: nonEmptyTrimmedString.nullable().optional()
1504
1757
  };
1505
1758
  export const createWorkBlockTemplateSchema = z
1506
1759
  .object(workBlockTemplateMutationShape)
@@ -1534,7 +1787,8 @@ export const updateWorkBlockTemplateSchema = z
1534
1787
  endMinute: integerMinuteSchema.optional(),
1535
1788
  startsOn: dateOnlySchema.nullable().optional(),
1536
1789
  endsOn: dateOnlySchema.nullable().optional(),
1537
- blockingState: z.enum(["allowed", "blocked"]).optional()
1790
+ blockingState: z.enum(["allowed", "blocked"]).optional(),
1791
+ userId: nonEmptyTrimmedString.nullable().optional()
1538
1792
  })
1539
1793
  .superRefine((value, context) => {
1540
1794
  if (value.startMinute !== undefined &&
@@ -1567,7 +1821,8 @@ export const createTaskTimeboxSchema = z
1567
1821
  endsAt: z.string().datetime(),
1568
1822
  source: calendarTimeboxSourceSchema.default("manual"),
1569
1823
  status: calendarTimeboxStatusSchema.default("planned"),
1570
- overrideReason: trimmedString.nullable().default(null)
1824
+ overrideReason: trimmedString.nullable().default(null),
1825
+ userId: nonEmptyTrimmedString.nullable().optional()
1571
1826
  })
1572
1827
  .superRefine((value, context) => {
1573
1828
  if (Date.parse(value.endsAt) <= Date.parse(value.startsAt)) {
@@ -1583,12 +1838,13 @@ export const updateTaskTimeboxSchema = z.object({
1583
1838
  startsAt: z.string().datetime().optional(),
1584
1839
  endsAt: z.string().datetime().optional(),
1585
1840
  status: calendarTimeboxStatusSchema.optional(),
1586
- overrideReason: trimmedString.nullable().optional()
1841
+ overrideReason: trimmedString.nullable().optional(),
1842
+ userId: nonEmptyTrimmedString.nullable().optional()
1587
1843
  });
1588
1844
  export const recommendTaskTimeboxesSchema = z.object({
1589
1845
  taskId: nonEmptyTrimmedString,
1590
- from: z.string().datetime().optional(),
1591
- to: z.string().datetime().optional(),
1846
+ from: flexibleCalendarQueryDateSchema.optional(),
1847
+ to: flexibleCalendarQueryDateSchema.optional(),
1592
1848
  limit: z.coerce.number().int().positive().max(12).optional()
1593
1849
  });
1594
1850
  export const updateCalendarEventSchema = z
@@ -1596,6 +1852,17 @@ export const updateCalendarEventSchema = z
1596
1852
  title: nonEmptyTrimmedString.optional(),
1597
1853
  description: trimmedString.optional(),
1598
1854
  location: trimmedString.optional(),
1855
+ place: z
1856
+ .object({
1857
+ label: trimmedString.optional(),
1858
+ address: trimmedString.optional(),
1859
+ timezone: trimmedString.optional(),
1860
+ latitude: z.number().nullable().optional(),
1861
+ longitude: z.number().nullable().optional(),
1862
+ source: trimmedString.optional(),
1863
+ externalPlaceId: trimmedString.optional()
1864
+ })
1865
+ .optional(),
1599
1866
  startAt: z.string().datetime().optional(),
1600
1867
  endAt: z.string().datetime().optional(),
1601
1868
  timezone: nonEmptyTrimmedString.optional(),
@@ -1604,6 +1871,7 @@ export const updateCalendarEventSchema = z
1604
1871
  eventType: trimmedString.optional(),
1605
1872
  categories: z.array(trimmedString).optional(),
1606
1873
  preferredCalendarId: nonEmptyTrimmedString.nullable().optional(),
1874
+ userId: nonEmptyTrimmedString.nullable().optional(),
1607
1875
  links: z
1608
1876
  .array(z.object({
1609
1877
  entityType: crudEntityTypeSchema,
@@ -1628,6 +1896,25 @@ export const createCalendarEventSchema = z
1628
1896
  title: nonEmptyTrimmedString,
1629
1897
  description: trimmedString.default(""),
1630
1898
  location: trimmedString.default(""),
1899
+ place: z
1900
+ .object({
1901
+ label: trimmedString.default(""),
1902
+ address: trimmedString.default(""),
1903
+ timezone: trimmedString.default(""),
1904
+ latitude: z.number().nullable().default(null),
1905
+ longitude: z.number().nullable().default(null),
1906
+ source: trimmedString.default(""),
1907
+ externalPlaceId: trimmedString.default("")
1908
+ })
1909
+ .default({
1910
+ label: "",
1911
+ address: "",
1912
+ timezone: "",
1913
+ latitude: null,
1914
+ longitude: null,
1915
+ source: "",
1916
+ externalPlaceId: ""
1917
+ }),
1631
1918
  startAt: z.string().datetime(),
1632
1919
  endAt: z.string().datetime(),
1633
1920
  timezone: nonEmptyTrimmedString.default("UTC"),
@@ -1636,6 +1923,7 @@ export const createCalendarEventSchema = z
1636
1923
  eventType: trimmedString.default(""),
1637
1924
  categories: z.array(trimmedString).default([]),
1638
1925
  preferredCalendarId: nonEmptyTrimmedString.nullable().optional(),
1926
+ userId: nonEmptyTrimmedString.nullable().optional(),
1639
1927
  links: z
1640
1928
  .array(z.object({
1641
1929
  entityType: crudEntityTypeSchema,
@@ -1657,6 +1945,7 @@ export const habitListQuerySchema = z.object({
1657
1945
  status: habitStatusSchema.optional(),
1658
1946
  polarity: habitPolaritySchema.optional(),
1659
1947
  dueToday: z.coerce.boolean().optional(),
1948
+ userIds: repeatedTrimmedStringQuerySchema.optional(),
1660
1949
  limit: z.coerce.number().int().positive().max(100).optional()
1661
1950
  });
1662
1951
  export const createGoalSchema = z.object({
@@ -1670,7 +1959,8 @@ export const createGoalSchema = z.object({
1670
1959
  .regex(/^#[0-9a-fA-F]{6}$/)
1671
1960
  .default("#c8a46b"),
1672
1961
  tagIds: uniqueStringArraySchema.default([]),
1673
- notes: z.array(nestedCreateNoteSchema).default([])
1962
+ notes: z.array(nestedCreateNoteSchema).default([]),
1963
+ userId: nonEmptyTrimmedString.nullable().optional()
1674
1964
  });
1675
1965
  export const updateGoalSchema = createGoalSchema.partial();
1676
1966
  export const createTagSchema = z.object({
@@ -1680,7 +1970,8 @@ export const createTagSchema = z.object({
1680
1970
  .string()
1681
1971
  .regex(/^#[0-9a-fA-F]{6}$/)
1682
1972
  .default("#71717a"),
1683
- description: trimmedString.default("")
1973
+ description: trimmedString.default(""),
1974
+ userId: nonEmptyTrimmedString.nullable().optional()
1684
1975
  });
1685
1976
  export const updateTagSchema = createTagSchema.partial();
1686
1977
  export const createProjectSchema = z.object({
@@ -1705,7 +1996,8 @@ export const createProjectSchema = z.object({
1705
1996
  allowAvailability: [],
1706
1997
  blockAvailability: []
1707
1998
  }),
1708
- notes: z.array(nestedCreateNoteSchema).default([])
1999
+ notes: z.array(nestedCreateNoteSchema).default([]),
2000
+ userId: nonEmptyTrimmedString.nullable().optional()
1709
2001
  });
1710
2002
  export const updateProjectSchema = createProjectSchema.partial();
1711
2003
  export const taskMutationShape = {
@@ -1714,6 +2006,7 @@ export const taskMutationShape = {
1714
2006
  status: taskStatusSchema.default("backlog"),
1715
2007
  priority: taskPrioritySchema.default("medium"),
1716
2008
  owner: nonEmptyTrimmedString.default("Albert"),
2009
+ userId: nonEmptyTrimmedString.nullable().optional(),
1717
2010
  goalId: nonEmptyTrimmedString.nullable().default(null),
1718
2011
  projectId: nonEmptyTrimmedString.nullable().default(null),
1719
2012
  dueDate: dateOnlySchema.nullable().default(null),
@@ -1752,7 +2045,40 @@ const habitMutationShape = {
1752
2045
  linkedReportIds: uniqueStringArraySchema.default([]),
1753
2046
  linkedBehaviorId: nonEmptyTrimmedString.nullable().default(null),
1754
2047
  rewardXp: z.number().int().min(1).max(100).default(12),
1755
- penaltyXp: z.number().int().min(1).max(100).default(8)
2048
+ penaltyXp: z.number().int().min(1).max(100).default(8),
2049
+ generatedHealthEventTemplate: z
2050
+ .object({
2051
+ enabled: z.boolean().default(false),
2052
+ workoutType: trimmedString.default("workout"),
2053
+ title: trimmedString.default(""),
2054
+ durationMinutes: z
2055
+ .number()
2056
+ .int()
2057
+ .positive()
2058
+ .max(24 * 60)
2059
+ .default(45),
2060
+ xpReward: z.number().int().min(0).max(500).default(0),
2061
+ tags: uniqueStringArraySchema.default([]),
2062
+ links: z
2063
+ .array(z.object({
2064
+ entityType: trimmedString,
2065
+ entityId: nonEmptyTrimmedString,
2066
+ relationshipType: trimmedString.default("context")
2067
+ }))
2068
+ .default([]),
2069
+ notesTemplate: trimmedString.default("")
2070
+ })
2071
+ .default({
2072
+ enabled: false,
2073
+ workoutType: "workout",
2074
+ title: "",
2075
+ durationMinutes: 45,
2076
+ xpReward: 0,
2077
+ tags: [],
2078
+ links: [],
2079
+ notesTemplate: ""
2080
+ }),
2081
+ userId: nonEmptyTrimmedString.nullable().optional()
1756
2082
  };
1757
2083
  export const createHabitSchema = z
1758
2084
  .object(habitMutationShape)
@@ -1785,7 +2111,31 @@ export const updateHabitSchema = z
1785
2111
  linkedReportIds: uniqueStringArraySchema.optional(),
1786
2112
  linkedBehaviorId: nonEmptyTrimmedString.nullable().optional(),
1787
2113
  rewardXp: z.number().int().min(1).max(100).optional(),
1788
- penaltyXp: z.number().int().min(1).max(100).optional()
2114
+ penaltyXp: z.number().int().min(1).max(100).optional(),
2115
+ generatedHealthEventTemplate: z
2116
+ .object({
2117
+ enabled: z.boolean().optional(),
2118
+ workoutType: trimmedString.optional(),
2119
+ title: trimmedString.optional(),
2120
+ durationMinutes: z
2121
+ .number()
2122
+ .int()
2123
+ .positive()
2124
+ .max(24 * 60)
2125
+ .optional(),
2126
+ xpReward: z.number().int().min(0).max(500).optional(),
2127
+ tags: uniqueStringArraySchema.optional(),
2128
+ links: z
2129
+ .array(z.object({
2130
+ entityType: trimmedString,
2131
+ entityId: nonEmptyTrimmedString,
2132
+ relationshipType: trimmedString.default("context")
2133
+ }))
2134
+ .optional(),
2135
+ notesTemplate: trimmedString.optional()
2136
+ })
2137
+ .optional(),
2138
+ userId: nonEmptyTrimmedString.nullable().optional()
1789
2139
  })
1790
2140
  .superRefine((value, context) => {
1791
2141
  if (value.frequency === "weekly" &&
@@ -1804,6 +2154,7 @@ export const updateTaskSchema = z.object({
1804
2154
  status: taskStatusSchema.optional(),
1805
2155
  priority: taskPrioritySchema.optional(),
1806
2156
  owner: nonEmptyTrimmedString.optional(),
2157
+ userId: nonEmptyTrimmedString.nullable().optional(),
1807
2158
  goalId: nonEmptyTrimmedString.nullable().optional(),
1808
2159
  projectId: nonEmptyTrimmedString.nullable().optional(),
1809
2160
  dueDate: dateOnlySchema.nullable().optional(),
@@ -1930,6 +2281,33 @@ export const eventsListQuerySchema = z.object({
1930
2281
  eventKind: nonEmptyTrimmedString.optional(),
1931
2282
  limit: z.coerce.number().int().positive().max(200).optional()
1932
2283
  });
2284
+ export const diagnosticLogListQuerySchema = z.object({
2285
+ level: diagnosticLogLevelSchema.optional(),
2286
+ source: diagnosticLogSourceSchema.optional(),
2287
+ scope: nonEmptyTrimmedString.optional(),
2288
+ route: nonEmptyTrimmedString.optional(),
2289
+ entityType: nonEmptyTrimmedString.optional(),
2290
+ entityId: nonEmptyTrimmedString.optional(),
2291
+ jobId: nonEmptyTrimmedString.optional(),
2292
+ search: nonEmptyTrimmedString.optional(),
2293
+ beforeCreatedAt: nonEmptyTrimmedString.optional(),
2294
+ beforeId: nonEmptyTrimmedString.optional(),
2295
+ limit: z.coerce.number().int().positive().max(500).optional()
2296
+ });
2297
+ export const createDiagnosticLogSchema = z.object({
2298
+ level: diagnosticLogLevelSchema.default("info"),
2299
+ source: diagnosticLogSourceSchema.optional(),
2300
+ scope: nonEmptyTrimmedString,
2301
+ eventKey: trimmedString.default(""),
2302
+ message: nonEmptyTrimmedString,
2303
+ route: trimmedString.nullable().optional(),
2304
+ functionName: trimmedString.nullable().optional(),
2305
+ requestId: trimmedString.nullable().optional(),
2306
+ entityType: trimmedString.nullable().optional(),
2307
+ entityId: trimmedString.nullable().optional(),
2308
+ jobId: trimmedString.nullable().optional(),
2309
+ details: z.record(z.string(), z.unknown()).default({})
2310
+ });
1933
2311
  export const rewardsLedgerQuerySchema = z.object({
1934
2312
  entityType: nonEmptyTrimmedString.optional(),
1935
2313
  entityId: nonEmptyTrimmedString.optional(),
@@ -1989,6 +2367,190 @@ const crudEntityLinkSchema = z.object({
1989
2367
  entityType: crudEntityTypeSchema,
1990
2368
  id: nonEmptyTrimmedString
1991
2369
  });
2370
+ const strategyGraphNodeEntityTypeSchema = z.enum(["project", "task"]);
2371
+ function validateStrategyGraph(graph, context) {
2372
+ const nodeIds = new Set();
2373
+ for (const node of graph.nodes) {
2374
+ if (nodeIds.has(node.id)) {
2375
+ context.addIssue({
2376
+ code: z.ZodIssueCode.custom,
2377
+ path: ["nodes"],
2378
+ message: `Strategy graph node ${node.id} is duplicated`
2379
+ });
2380
+ return;
2381
+ }
2382
+ nodeIds.add(node.id);
2383
+ }
2384
+ const outgoing = new Map();
2385
+ const incomingCount = new Map();
2386
+ for (const nodeId of nodeIds) {
2387
+ outgoing.set(nodeId, []);
2388
+ incomingCount.set(nodeId, 0);
2389
+ }
2390
+ for (const edge of graph.edges) {
2391
+ if (!nodeIds.has(edge.from) || !nodeIds.has(edge.to)) {
2392
+ context.addIssue({
2393
+ code: z.ZodIssueCode.custom,
2394
+ path: ["edges"],
2395
+ message: `Strategy graph edge ${edge.from} -> ${edge.to} references a missing node`
2396
+ });
2397
+ return;
2398
+ }
2399
+ if (edge.from === edge.to) {
2400
+ context.addIssue({
2401
+ code: z.ZodIssueCode.custom,
2402
+ path: ["edges"],
2403
+ message: "Strategy graph edges cannot point back to the same node"
2404
+ });
2405
+ return;
2406
+ }
2407
+ outgoing.get(edge.from).push(edge.to);
2408
+ incomingCount.set(edge.to, (incomingCount.get(edge.to) ?? 0) + 1);
2409
+ }
2410
+ const queue = Array.from(nodeIds).filter((nodeId) => (incomingCount.get(nodeId) ?? 0) === 0);
2411
+ if (queue.length === 0) {
2412
+ context.addIssue({
2413
+ code: z.ZodIssueCode.custom,
2414
+ path: ["edges"],
2415
+ message: "Strategy graph needs at least one starting node"
2416
+ });
2417
+ return;
2418
+ }
2419
+ let visited = 0;
2420
+ while (queue.length > 0) {
2421
+ const nodeId = queue.shift();
2422
+ visited += 1;
2423
+ for (const nextId of outgoing.get(nodeId) ?? []) {
2424
+ const nextIncoming = (incomingCount.get(nextId) ?? 0) - 1;
2425
+ incomingCount.set(nextId, nextIncoming);
2426
+ if (nextIncoming === 0) {
2427
+ queue.push(nextId);
2428
+ }
2429
+ }
2430
+ }
2431
+ if (visited !== nodeIds.size) {
2432
+ context.addIssue({
2433
+ code: z.ZodIssueCode.custom,
2434
+ path: ["edges"],
2435
+ message: "Strategy graph must stay directed and acyclic"
2436
+ });
2437
+ return;
2438
+ }
2439
+ const terminalCount = Array.from(nodeIds).filter((nodeId) => (outgoing.get(nodeId) ?? []).length === 0).length;
2440
+ if (terminalCount === 0) {
2441
+ context.addIssue({
2442
+ code: z.ZodIssueCode.custom,
2443
+ path: ["edges"],
2444
+ message: "Strategy graph needs at least one terminal end-state node"
2445
+ });
2446
+ }
2447
+ }
2448
+ export const strategyLinkedEntitySchema = z.object({
2449
+ entityType: crudEntityTypeSchema,
2450
+ entityId: nonEmptyTrimmedString
2451
+ });
2452
+ export const strategyGraphNodeSchema = z.object({
2453
+ id: nonEmptyTrimmedString,
2454
+ entityType: strategyGraphNodeEntityTypeSchema,
2455
+ entityId: nonEmptyTrimmedString,
2456
+ title: trimmedString.default(""),
2457
+ branchLabel: trimmedString.default(""),
2458
+ notes: trimmedString.default("")
2459
+ });
2460
+ export const strategyGraphEdgeSchema = z.object({
2461
+ from: nonEmptyTrimmedString,
2462
+ to: nonEmptyTrimmedString,
2463
+ label: trimmedString.default(""),
2464
+ condition: trimmedString.default("")
2465
+ });
2466
+ export const strategyGraphSchema = z
2467
+ .object({
2468
+ nodes: z.array(strategyGraphNodeSchema).min(1),
2469
+ edges: z.array(strategyGraphEdgeSchema).default([])
2470
+ })
2471
+ .superRefine((graph, context) => validateStrategyGraph(graph, context));
2472
+ export const strategyMetricSchema = z.object({
2473
+ alignmentScore: z.number().int().min(0).max(100),
2474
+ planCoverageScore: z.number().int().min(0).max(100),
2475
+ sequencingScore: z.number().int().min(0).max(100),
2476
+ scopeDisciplineScore: z.number().int().min(0).max(100),
2477
+ qualityScore: z.number().int().min(0).max(100),
2478
+ targetProgressScore: z.number().int().min(0).max(100),
2479
+ completedNodeCount: z.number().int().nonnegative(),
2480
+ startedNodeCount: z.number().int().nonnegative(),
2481
+ readyNodeCount: z.number().int().nonnegative(),
2482
+ totalNodeCount: z.number().int().positive(),
2483
+ completedTargetCount: z.number().int().nonnegative(),
2484
+ totalTargetCount: z.number().int().nonnegative(),
2485
+ offPlanEntityCount: z.number().int().nonnegative().default(0),
2486
+ offPlanActiveEntityCount: z.number().int().nonnegative().default(0),
2487
+ offPlanCompletedEntityCount: z.number().int().nonnegative().default(0),
2488
+ activeNodeIds: z.array(z.string()).default([]),
2489
+ nextNodeIds: z.array(z.string()).default([]),
2490
+ blockedNodeIds: z.array(z.string()).default([]),
2491
+ outOfOrderNodeIds: z.array(z.string()).default([])
2492
+ });
2493
+ export const strategySchema = z.object({
2494
+ id: z.string(),
2495
+ title: nonEmptyTrimmedString,
2496
+ overview: trimmedString,
2497
+ endStateDescription: trimmedString,
2498
+ status: strategyStatusSchema,
2499
+ targetGoalIds: uniqueStringArraySchema.default([]),
2500
+ targetProjectIds: uniqueStringArraySchema.default([]),
2501
+ linkedEntities: z.array(strategyLinkedEntitySchema).default([]),
2502
+ graph: strategyGraphSchema,
2503
+ metrics: strategyMetricSchema,
2504
+ isLocked: z.boolean().default(false),
2505
+ lockedAt: z.string().nullable().default(null),
2506
+ lockedByUserId: z.string().nullable().default(null),
2507
+ lockedByUser: userSummarySchema.nullable().default(null),
2508
+ createdAt: z.string(),
2509
+ updatedAt: z.string(),
2510
+ ...ownershipShape
2511
+ });
2512
+ export const strategyListQuerySchema = z.object({
2513
+ status: strategyStatusSchema.optional(),
2514
+ userIds: repeatedTrimmedStringQuerySchema.optional(),
2515
+ limit: z.coerce.number().int().positive().max(100).optional()
2516
+ });
2517
+ export const createUserSchema = z.object({
2518
+ kind: userKindSchema,
2519
+ handle: nonEmptyTrimmedString,
2520
+ displayName: nonEmptyTrimmedString,
2521
+ description: trimmedString.default(""),
2522
+ accentColor: z
2523
+ .string()
2524
+ .regex(/^#[0-9a-fA-F]{6}$/)
2525
+ .default("#c0c1ff")
2526
+ });
2527
+ export const updateUserSchema = createUserSchema.partial();
2528
+ export const createStrategySchema = z.object({
2529
+ title: nonEmptyTrimmedString,
2530
+ overview: trimmedString.default(""),
2531
+ endStateDescription: trimmedString.default(""),
2532
+ status: strategyStatusSchema.default("active"),
2533
+ targetGoalIds: uniqueStringArraySchema.default([]),
2534
+ targetProjectIds: uniqueStringArraySchema.default([]),
2535
+ linkedEntities: z.array(strategyLinkedEntitySchema).default([]),
2536
+ graph: strategyGraphSchema,
2537
+ userId: nonEmptyTrimmedString.nullable().optional(),
2538
+ isLocked: z.boolean().default(false),
2539
+ lockedByUserId: nonEmptyTrimmedString.nullable().optional()
2540
+ });
2541
+ export const updateStrategySchema = z.object({
2542
+ title: nonEmptyTrimmedString.optional(),
2543
+ overview: trimmedString.optional(),
2544
+ endStateDescription: trimmedString.optional(),
2545
+ status: strategyStatusSchema.optional(),
2546
+ targetGoalIds: uniqueStringArraySchema.optional(),
2547
+ targetProjectIds: uniqueStringArraySchema.optional(),
2548
+ linkedEntities: z.array(strategyLinkedEntitySchema).optional(),
2549
+ graph: strategyGraphSchema.optional(),
2550
+ userId: nonEmptyTrimmedString.nullable().optional(),
2551
+ isLocked: z.boolean().optional(),
2552
+ lockedByUserId: nonEmptyTrimmedString.nullable().optional()
2553
+ });
1992
2554
  export const batchCreateEntitiesSchema = z.object({
1993
2555
  atomic: z.boolean().default(false),
1994
2556
  operations: z
@@ -2040,6 +2602,7 @@ export const batchSearchEntitiesSchema = z.object({
2040
2602
  ids: uniqueStringArraySchema.optional(),
2041
2603
  status: uniqueStringArraySchema.optional(),
2042
2604
  linkedTo: crudEntityLinkSchema.optional(),
2605
+ userIds: uniqueStringArraySchema.optional(),
2043
2606
  includeDeleted: z.boolean().default(false),
2044
2607
  limit: z.number().int().positive().max(200).default(25),
2045
2608
  clientRef: trimmedString.optional()
@@ -2058,6 +2621,7 @@ export const operatorLogWorkSchema = z
2058
2621
  goalId: nonEmptyTrimmedString.nullable().optional(),
2059
2622
  projectId: nonEmptyTrimmedString.nullable().optional(),
2060
2623
  owner: nonEmptyTrimmedString.optional(),
2624
+ userId: nonEmptyTrimmedString.nullable().optional(),
2061
2625
  status: taskStatusSchema.optional(),
2062
2626
  priority: taskPrioritySchema.optional(),
2063
2627
  dueDate: dateOnlySchema.nullable().optional(),