@burdenoff/microfe-planmagnet 2026.1002.2 → 2026.1008.1

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 (165) hide show
  1. package/dist/generated/wspace-operations.d.ts +574 -0
  2. package/dist/generated/wspace-operations.d.ts.map +1 -1
  3. package/dist/generated/wspace-types.d.ts +486 -16
  4. package/dist/generated/wspace-types.d.ts.map +1 -1
  5. package/dist/index.js +8 -8
  6. package/dist/planmagnet/PlanMagnetRoot.d.ts.map +1 -1
  7. package/dist/planmagnet/PlanMagnetRoot.js +174 -168
  8. package/dist/planmagnet/PlanMagnetRoot.js.map +1 -1
  9. package/dist/planmagnet/PlanMagnetRoutes.d.ts.map +1 -1
  10. package/dist/planmagnet/PlanMagnetRoutes.js +63 -59
  11. package/dist/planmagnet/PlanMagnetRoutes.js.map +1 -1
  12. package/dist/planmagnet/board/BulkActions.d.ts.map +1 -1
  13. package/dist/planmagnet/board/BulkActions.js +106 -55
  14. package/dist/planmagnet/board/BulkActions.js.map +1 -1
  15. package/dist/planmagnet/controls/Pickers.d.ts +3 -3
  16. package/dist/planmagnet/controls/Pickers.js.map +1 -1
  17. package/dist/planmagnet/dashboards/DashboardUI.d.ts +0 -4
  18. package/dist/planmagnet/dashboards/DashboardUI.d.ts.map +1 -1
  19. package/dist/planmagnet/dashboards/DashboardUI.js +6 -13
  20. package/dist/planmagnet/dashboards/DashboardUI.js.map +1 -1
  21. package/dist/planmagnet/dashboards/cards/SprintCapacityCard.d.ts.map +1 -1
  22. package/dist/planmagnet/dashboards/cards/SprintCapacityCard.js +70 -59
  23. package/dist/planmagnet/dashboards/cards/SprintCapacityCard.js.map +1 -1
  24. package/dist/planmagnet/forecast/ResourceForecastCard.js +1 -1
  25. package/dist/planmagnet/forecast/ResourceForecastCard.js.map +1 -1
  26. package/dist/planmagnet/index.d.ts +1 -1
  27. package/dist/planmagnet/index.d.ts.map +1 -1
  28. package/dist/planmagnet/pages/DashboardsProjectManagerPagePage.d.ts +3 -3
  29. package/dist/planmagnet/pages/DashboardsProjectManagerPagePage.d.ts.map +1 -1
  30. package/dist/planmagnet/pages/DashboardsProjectManagerPagePage.js +26 -19
  31. package/dist/planmagnet/pages/DashboardsProjectManagerPagePage.js.map +1 -1
  32. package/dist/planmagnet/pages/DashboardsTeamUtilizationPagePage.d.ts +2 -2
  33. package/dist/planmagnet/pages/DashboardsTeamUtilizationPagePage.d.ts.map +1 -1
  34. package/dist/planmagnet/pages/DashboardsTeamUtilizationPagePage.js +18 -12
  35. package/dist/planmagnet/pages/DashboardsTeamUtilizationPagePage.js.map +1 -1
  36. package/dist/planmagnet/pages/ProductsCustomerSatisfactionPagePage.d.ts +2 -0
  37. package/dist/planmagnet/pages/ProductsCustomerSatisfactionPagePage.d.ts.map +1 -0
  38. package/dist/planmagnet/pages/ProductsCustomerSatisfactionPagePage.js +251 -0
  39. package/dist/planmagnet/pages/ProductsCustomerSatisfactionPagePage.js.map +1 -0
  40. package/dist/planmagnet/pages/ProductsProductDetailPagePage.d.ts.map +1 -1
  41. package/dist/planmagnet/pages/ProductsProductDetailPagePage.js +94 -92
  42. package/dist/planmagnet/pages/ProductsProductDetailPagePage.js.map +1 -1
  43. package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.d.ts.map +1 -1
  44. package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.js +116 -114
  45. package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.js.map +1 -1
  46. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.d.ts.map +1 -1
  47. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js +174 -159
  48. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js.map +1 -1
  49. package/dist/planmagnet/pages/TasksCreateTaskPagePage.d.ts.map +1 -1
  50. package/dist/planmagnet/pages/TasksCreateTaskPagePage.js +159 -145
  51. package/dist/planmagnet/pages/TasksCreateTaskPagePage.js.map +1 -1
  52. package/dist/planmagnet/pages/TasksEditTaskPagePage.d.ts.map +1 -1
  53. package/dist/planmagnet/pages/TasksEditTaskPagePage.js +161 -143
  54. package/dist/planmagnet/pages/TasksEditTaskPagePage.js.map +1 -1
  55. package/dist/planmagnet/pages/TasksTaskDetailPagePage.d.ts.map +1 -1
  56. package/dist/planmagnet/pages/TasksTaskDetailPagePage.js +157 -155
  57. package/dist/planmagnet/pages/TasksTaskDetailPagePage.js.map +1 -1
  58. package/dist/planmagnet/pages/TeamInviteMemberPagePage.d.ts.map +1 -1
  59. package/dist/planmagnet/pages/TeamInviteMemberPagePage.js +142 -82
  60. package/dist/planmagnet/pages/TeamInviteMemberPagePage.js.map +1 -1
  61. package/dist/planmagnet/pages/analytics/DeliveryKpisCard.d.ts.map +1 -1
  62. package/dist/planmagnet/pages/analytics/DeliveryKpisCard.js +97 -99
  63. package/dist/planmagnet/pages/analytics/DeliveryKpisCard.js.map +1 -1
  64. package/dist/planmagnet/product/FeatureLinkPanels.js +66 -66
  65. package/dist/planmagnet/product/ProductFeatureControls.js +38 -38
  66. package/dist/planmagnet/product/ProductFeatureLinkCard.js +8 -8
  67. package/dist/planmagnet/product/ProductLineControls.js +83 -83
  68. package/dist/planmagnet/product/ProductTeamsPanel.js +6 -6
  69. package/dist/planmagnet/product/routes.d.ts +6 -0
  70. package/dist/planmagnet/product/routes.d.ts.map +1 -1
  71. package/dist/planmagnet/product/routes.js +2 -2
  72. package/dist/planmagnet/product/routes.js.map +1 -1
  73. package/dist/planmagnet/satisfaction/DeliverySatisfactionSection.d.ts +20 -0
  74. package/dist/planmagnet/satisfaction/DeliverySatisfactionSection.d.ts.map +1 -0
  75. package/dist/planmagnet/satisfaction/DeliverySatisfactionSection.js +55 -0
  76. package/dist/planmagnet/satisfaction/DeliverySatisfactionSection.js.map +1 -0
  77. package/dist/planmagnet/satisfaction/SatisfactionFigures.d.ts +30 -0
  78. package/dist/planmagnet/satisfaction/SatisfactionFigures.d.ts.map +1 -0
  79. package/dist/planmagnet/satisfaction/SatisfactionFigures.js +282 -0
  80. package/dist/planmagnet/satisfaction/SatisfactionFigures.js.map +1 -0
  81. package/dist/planmagnet/satisfaction/SatisfactionImportDialog.d.ts +9 -0
  82. package/dist/planmagnet/satisfaction/SatisfactionImportDialog.d.ts.map +1 -0
  83. package/dist/planmagnet/satisfaction/SatisfactionImportDialog.js +390 -0
  84. package/dist/planmagnet/satisfaction/SatisfactionImportDialog.js.map +1 -0
  85. package/dist/planmagnet/satisfaction/SatisfactionLinkFields.d.ts +17 -0
  86. package/dist/planmagnet/satisfaction/SatisfactionLinkFields.d.ts.map +1 -0
  87. package/dist/planmagnet/satisfaction/SatisfactionLinkFields.js +77 -0
  88. package/dist/planmagnet/satisfaction/SatisfactionLinkFields.js.map +1 -0
  89. package/dist/planmagnet/satisfaction/SatisfactionReleaseSelect.d.ts +18 -0
  90. package/dist/planmagnet/satisfaction/SatisfactionReleaseSelect.d.ts.map +1 -0
  91. package/dist/planmagnet/satisfaction/SatisfactionReleaseSelect.js +87 -0
  92. package/dist/planmagnet/satisfaction/SatisfactionReleaseSelect.js.map +1 -0
  93. package/dist/planmagnet/satisfaction/SatisfactionResponseDialog.d.ts +13 -0
  94. package/dist/planmagnet/satisfaction/SatisfactionResponseDialog.d.ts.map +1 -0
  95. package/dist/planmagnet/satisfaction/SatisfactionResponseDialog.js +326 -0
  96. package/dist/planmagnet/satisfaction/SatisfactionResponseDialog.js.map +1 -0
  97. package/dist/planmagnet/satisfaction/SatisfactionResponsesTable.d.ts +23 -0
  98. package/dist/planmagnet/satisfaction/SatisfactionResponsesTable.d.ts.map +1 -0
  99. package/dist/planmagnet/satisfaction/SatisfactionResponsesTable.js +258 -0
  100. package/dist/planmagnet/satisfaction/SatisfactionResponsesTable.js.map +1 -0
  101. package/dist/planmagnet/satisfaction/SatisfactionSummaryCard.d.ts +6 -0
  102. package/dist/planmagnet/satisfaction/SatisfactionSummaryCard.d.ts.map +1 -0
  103. package/dist/planmagnet/satisfaction/SatisfactionSummaryCard.js +56 -0
  104. package/dist/planmagnet/satisfaction/SatisfactionSummaryCard.js.map +1 -0
  105. package/dist/planmagnet/satisfaction/SatisfactionWindowPicker.d.ts +16 -0
  106. package/dist/planmagnet/satisfaction/SatisfactionWindowPicker.d.ts.map +1 -0
  107. package/dist/planmagnet/satisfaction/SatisfactionWindowPicker.js +102 -0
  108. package/dist/planmagnet/satisfaction/SatisfactionWindowPicker.js.map +1 -0
  109. package/dist/planmagnet/satisfaction/satisfaction.d.ts +154 -0
  110. package/dist/planmagnet/satisfaction/satisfaction.d.ts.map +1 -0
  111. package/dist/planmagnet/satisfaction/satisfaction.js +210 -0
  112. package/dist/planmagnet/satisfaction/satisfaction.js.map +1 -0
  113. package/dist/planmagnet/satisfaction/satisfactionCsv.d.ts +108 -0
  114. package/dist/planmagnet/satisfaction/satisfactionCsv.d.ts.map +1 -0
  115. package/dist/planmagnet/satisfaction/satisfactionCsv.js +211 -0
  116. package/dist/planmagnet/satisfaction/satisfactionCsv.js.map +1 -0
  117. package/dist/planmagnet/satisfaction/satisfactionForm.d.ts +90 -0
  118. package/dist/planmagnet/satisfaction/satisfactionForm.d.ts.map +1 -0
  119. package/dist/planmagnet/satisfaction/satisfactionForm.js +90 -0
  120. package/dist/planmagnet/satisfaction/satisfactionForm.js.map +1 -0
  121. package/dist/planmagnet/satisfaction/satisfactionOperations.d.ts +116 -0
  122. package/dist/planmagnet/satisfaction/satisfactionOperations.d.ts.map +1 -0
  123. package/dist/planmagnet/satisfaction/satisfactionOperations.js +86 -0
  124. package/dist/planmagnet/satisfaction/satisfactionOperations.js.map +1 -0
  125. package/dist/planmagnet/satisfaction/useSatisfactionAccess.d.ts +20 -0
  126. package/dist/planmagnet/satisfaction/useSatisfactionAccess.d.ts.map +1 -0
  127. package/dist/planmagnet/satisfaction/useSatisfactionAccess.js +31 -0
  128. package/dist/planmagnet/satisfaction/useSatisfactionAccess.js.map +1 -0
  129. package/dist/planmagnet/skills/RequiredSkillsEditor.d.ts +35 -0
  130. package/dist/planmagnet/skills/RequiredSkillsEditor.d.ts.map +1 -0
  131. package/dist/planmagnet/skills/RequiredSkillsEditor.js +124 -0
  132. package/dist/planmagnet/skills/RequiredSkillsEditor.js.map +1 -0
  133. package/dist/planmagnet/skills/SkillChips.d.ts +30 -0
  134. package/dist/planmagnet/skills/SkillChips.d.ts.map +1 -0
  135. package/dist/planmagnet/skills/SkillChips.js +57 -0
  136. package/dist/planmagnet/skills/SkillChips.js.map +1 -0
  137. package/dist/planmagnet/skills/SkillCoverageCard.d.ts +24 -0
  138. package/dist/planmagnet/skills/SkillCoverageCard.d.ts.map +1 -0
  139. package/dist/planmagnet/skills/SkillCoverageCard.js +256 -0
  140. package/dist/planmagnet/skills/SkillCoverageCard.js.map +1 -0
  141. package/dist/planmagnet/skills/WorkItemRequiredSkills.d.ts +10 -0
  142. package/dist/planmagnet/skills/WorkItemRequiredSkills.d.ts.map +1 -0
  143. package/dist/planmagnet/skills/WorkItemRequiredSkills.js +65 -0
  144. package/dist/planmagnet/skills/WorkItemRequiredSkills.js.map +1 -0
  145. package/dist/planmagnet/skills/skillOperations.d.ts +52 -0
  146. package/dist/planmagnet/skills/skillOperations.d.ts.map +1 -0
  147. package/dist/planmagnet/skills/skillOperations.js +44 -0
  148. package/dist/planmagnet/skills/skillOperations.js.map +1 -0
  149. package/dist/planmagnet/skills/skillTags.d.ts +103 -0
  150. package/dist/planmagnet/skills/skillTags.d.ts.map +1 -0
  151. package/dist/planmagnet/skills/skillTags.js +115 -0
  152. package/dist/planmagnet/skills/skillTags.js.map +1 -0
  153. package/dist/planmagnet/skills/useRequiredSkillsDraft.d.ts +28 -0
  154. package/dist/planmagnet/skills/useRequiredSkillsDraft.d.ts.map +1 -0
  155. package/dist/planmagnet/skills/useRequiredSkillsDraft.js +30 -0
  156. package/dist/planmagnet/skills/useRequiredSkillsDraft.js.map +1 -0
  157. package/dist/planmagnet/team/PendingInvitations.d.ts +27 -0
  158. package/dist/planmagnet/team/PendingInvitations.d.ts.map +1 -0
  159. package/dist/planmagnet/team/PendingInvitations.js +220 -0
  160. package/dist/planmagnet/team/PendingInvitations.js.map +1 -0
  161. package/dist/planmagnet/team/invitationEmail.d.ts +35 -0
  162. package/dist/planmagnet/team/invitationEmail.d.ts.map +1 -0
  163. package/dist/planmagnet/team/invitationEmail.js +73 -0
  164. package/dist/planmagnet/team/invitationEmail.js.map +1 -0
  165. package/package.json +1 -1
@@ -850,6 +850,8 @@ export type Mutation = {
850
850
  planmagnetCreateCompetitor: Competitor;
851
851
  /** Create a new custom field definition */
852
852
  planmagnetCreateCustomFieldDefinition: CustomFieldDefinition;
853
+ /** Records one response (source MANUAL). See PlanmagnetCreateCustomerSatisfactionResponseInput for the rules. */
854
+ planmagnetCreateCustomerSatisfactionResponse: PlanmagnetCustomerSatisfactionResponse;
853
855
  /** Create a new dependency between work items */
854
856
  planmagnetCreateDependency: WorkItemDependency;
855
857
  planmagnetCreateDoc: PlanmagnetDoc;
@@ -947,6 +949,8 @@ export type Mutation = {
947
949
  planmagnetDeleteCompetitor: Scalars['Boolean']['output'];
948
950
  /** Delete a custom field definition */
949
951
  planmagnetDeleteCustomFieldDefinition: Scalars['Boolean']['output'];
952
+ /** Soft delete — the response stops counting in every figure. Unknown, deleted or other-workspace id: NOT_FOUND. */
953
+ planmagnetDeleteCustomerSatisfactionResponse: Scalars['Boolean']['output'];
950
954
  /** Remove a dependency */
951
955
  planmagnetDeleteDependency: Scalars['Boolean']['output'];
952
956
  planmagnetDeleteDoc: Scalars['Boolean']['output'];
@@ -1092,6 +1096,12 @@ export type Mutation = {
1092
1096
  * are computed and returned without writing to the database.
1093
1097
  */
1094
1098
  planmagnetGenerateReleaseNotes: PlanmagnetGenerateReleaseNotesPayload;
1099
+ /**
1100
+ * Imports a batch (source IMPORT). All or nothing: when any row is refused nothing is written, and the
1101
+ * BAD_USER_INPUT lists every refused row in `extensions.rowErrors` ({ row (1-based position in `rows`), field, code,
1102
+ * i18nKey, message }). Idempotent on externalId — see PlanmagnetCustomerSatisfactionImportResult.
1103
+ */
1104
+ planmagnetImportCustomerSatisfactionResponses: PlanmagnetCustomerSatisfactionImportResult;
1095
1105
  /**
1096
1106
  * Import issues exported from an external tool (e.g. a Linear CSV/JSON export)
1097
1107
  * into a project as WorkItems. Idempotent — already-imported issues are skipped.
@@ -1309,7 +1319,8 @@ export type Mutation = {
1309
1319
  /**
1310
1320
  * Set (create, or replace the target of) the CrewFoundry identity override for one workspace member (CWF-30).
1311
1321
  * Validates `platformUserId` is a real member of this workspace and `crewEmployeeId` a real employee in this
1312
- * workspace's CrewFoundry roster before saving.
1322
+ * workspace's CrewFoundry roster (all of it, every page) before saving. Refused SERVICE_UNAVAILABLE, saving
1323
+ * nothing, while the CrewFoundry roster cannot be read.
1313
1324
  */
1314
1325
  planmagnetSetMemberIdentityOverride: PlanmagnetMemberIdentityOverride;
1315
1326
  /** Tick (records who and when) or untick (clears both) a checklist item */
@@ -1406,6 +1417,8 @@ export type Mutation = {
1406
1417
  planmagnetUpdateCompetitor: Competitor;
1407
1418
  /** Update a custom field definition */
1408
1419
  planmagnetUpdateCustomFieldDefinition: CustomFieldDefinition;
1420
+ /** Unknown, deleted or other-workspace id: NOT_FOUND. */
1421
+ planmagnetUpdateCustomerSatisfactionResponse: PlanmagnetCustomerSatisfactionResponse;
1409
1422
  /** Update an existing dependency */
1410
1423
  planmagnetUpdateDependency: WorkItemDependency;
1411
1424
  planmagnetUpdateDoc: PlanmagnetDoc;
@@ -1614,6 +1627,9 @@ export type MutationPlanmagnetCreateCompetitorArgs = {
1614
1627
  export type MutationPlanmagnetCreateCustomFieldDefinitionArgs = {
1615
1628
  input: PlanmagnetCreateCustomFieldDefinitionInput;
1616
1629
  };
1630
+ export type MutationPlanmagnetCreateCustomerSatisfactionResponseArgs = {
1631
+ input: PlanmagnetCreateCustomerSatisfactionResponseInput;
1632
+ };
1617
1633
  export type MutationPlanmagnetCreateDependencyArgs = {
1618
1634
  input: PlanmagnetCreateDependencyInput;
1619
1635
  };
@@ -1740,6 +1756,9 @@ export type MutationPlanmagnetDeleteCompetitorArgs = {
1740
1756
  export type MutationPlanmagnetDeleteCustomFieldDefinitionArgs = {
1741
1757
  id: Scalars['ID']['input'];
1742
1758
  };
1759
+ export type MutationPlanmagnetDeleteCustomerSatisfactionResponseArgs = {
1760
+ id: Scalars['ID']['input'];
1761
+ };
1743
1762
  export type MutationPlanmagnetDeleteDependencyArgs = {
1744
1763
  id: Scalars['ID']['input'];
1745
1764
  };
@@ -1881,6 +1900,9 @@ export type MutationPlanmagnetGenerateReleaseNotesArgs = {
1881
1900
  id: Scalars['ID']['input'];
1882
1901
  persist?: InputMaybe<Scalars['Boolean']['input']>;
1883
1902
  };
1903
+ export type MutationPlanmagnetImportCustomerSatisfactionResponsesArgs = {
1904
+ input: PlanmagnetImportCustomerSatisfactionResponsesInput;
1905
+ };
1884
1906
  export type MutationPlanmagnetImportExternalIssuesArgs = {
1885
1907
  input: PlanmagnetImportExternalIssuesInput;
1886
1908
  };
@@ -2199,6 +2221,10 @@ export type MutationPlanmagnetUpdateCustomFieldDefinitionArgs = {
2199
2221
  id: Scalars['ID']['input'];
2200
2222
  input: PlanmagnetUpdateCustomFieldDefinitionInput;
2201
2223
  };
2224
+ export type MutationPlanmagnetUpdateCustomerSatisfactionResponseArgs = {
2225
+ id: Scalars['ID']['input'];
2226
+ input: PlanmagnetUpdateCustomerSatisfactionResponseInput;
2227
+ };
2202
2228
  export type MutationPlanmagnetUpdateDependencyArgs = {
2203
2229
  id: Scalars['ID']['input'];
2204
2230
  input: PlanmagnetUpdateDependencyInput;
@@ -3054,6 +3080,11 @@ export type PlanmagnetBulkUpdateWorkItemsInput = {
3054
3080
  /** Group every selected item under this milestone (all must be in its project), or null to remove them from theirs */
3055
3081
  milestoneId?: InputMaybe<Scalars['String']['input']>;
3056
3082
  priority?: InputMaybe<WorkItemPriority>;
3083
+ /**
3084
+ * Replaces every selected item's required skills (same rules as on create); null or [] clears them, leaving it out
3085
+ * keeps them
3086
+ */
3087
+ requiredSkills?: InputMaybe<Array<Scalars['String']['input']>>;
3057
3088
  sprintId?: InputMaybe<Scalars['String']['input']>;
3058
3089
  status?: InputMaybe<WorkItemStatus>;
3059
3090
  };
@@ -3276,6 +3307,31 @@ export type PlanmagnetCreateCustomFieldDefinitionInput = {
3276
3307
  sortOrder?: InputMaybe<Scalars['Int']['input']>;
3277
3308
  validationRules?: InputMaybe<Scalars['JSON']['input']>;
3278
3309
  };
3310
+ /**
3311
+ * Shared rules (create and every import row): `score` on the metric type's scale (CSAT 1-5, NPS 0-10); `respondedAt`
3312
+ * not in the future (a date picked as today in any time zone is accepted) and not before 2000-01-01; at least one of
3313
+ * productId/releaseId/projectId, each a live row of this workspace (else NOT_FOUND); a release that belongs to a product
3314
+ * must belong to the given productId (else BAD_USER_INPUT); an anonymous response takes no respondent name or email
3315
+ * (else BAD_USER_INPUT). An archived product still takes responses.
3316
+ */
3317
+ export type PlanmagnetCreateCustomerSatisfactionResponseInput = {
3318
+ /** At most 5000 characters. Blank is stored as null. */
3319
+ comment?: InputMaybe<Scalars['String']['input']>;
3320
+ /** Optional (at most 200 characters). Another live MANUAL response with the same externalId is CONFLICT. */
3321
+ externalId?: InputMaybe<Scalars['String']['input']>;
3322
+ /** Defaults to false. */
3323
+ isAnonymous?: InputMaybe<Scalars['Boolean']['input']>;
3324
+ metricType: PlanmagnetSatisfactionMetricType;
3325
+ productId?: InputMaybe<Scalars['ID']['input']>;
3326
+ projectId?: InputMaybe<Scalars['ID']['input']>;
3327
+ releaseId?: InputMaybe<Scalars['ID']['input']>;
3328
+ respondedAt: Scalars['DateTime']['input'];
3329
+ /** At most 254 characters. */
3330
+ respondentEmail?: InputMaybe<Scalars['String']['input']>;
3331
+ /** At most 200 characters. */
3332
+ respondentName?: InputMaybe<Scalars['String']['input']>;
3333
+ score: Scalars['Int']['input'];
3334
+ };
3279
3335
  export type PlanmagnetCreateDependencyInput = {
3280
3336
  description?: InputMaybe<Scalars['String']['input']>;
3281
3337
  lagMinutes?: InputMaybe<Scalars['Int']['input']>;
@@ -3636,6 +3692,11 @@ export type PlanmagnetCreateWorkItemInput = {
3636
3692
  priority?: InputMaybe<WorkItemPriority>;
3637
3693
  projectId: Scalars['String']['input'];
3638
3694
  reporterId?: InputMaybe<Scalars['String']['input']>;
3695
+ /**
3696
+ * Skills this item needs: normalized (trimmed, whitespace collapsed, case-insensitive duplicates dropped keeping the
3697
+ * first spelling); at most 20, each 1 to 64 characters. An empty or over-long skill is refused, not dropped
3698
+ */
3699
+ requiredSkills?: InputMaybe<Array<Scalars['String']['input']>>;
3639
3700
  sortOrder?: InputMaybe<Scalars['Int']['input']>;
3640
3701
  sprintId?: InputMaybe<Scalars['String']['input']>;
3641
3702
  status?: InputMaybe<WorkItemStatus>;
@@ -3676,6 +3737,20 @@ export type PlanmagnetCriticalPath = {
3676
3737
  */
3677
3738
  totalDurationMinutes: Scalars['Int']['output'];
3678
3739
  };
3740
+ /** CSAT over a scope and window. `score` is exact (no server-side rounding). */
3741
+ export type PlanmagnetCsatScore = {
3742
+ __typename?: 'PlanmagnetCsatScore';
3743
+ /** 5: fewer responses than this give no score. */
3744
+ minimumResponses: Scalars['Int']['output'];
3745
+ /** True when responseCount < minimumResponses (score is then null). */
3746
+ notEnoughResponses: Scalars['Boolean']['output'];
3747
+ /** CSAT responses counted. */
3748
+ responseCount: Scalars['Int']['output'];
3749
+ /** Of those, the 4s and 5s. */
3750
+ satisfiedCount: Scalars['Int']['output'];
3751
+ /** satisfiedCount * 100 / responseCount, 0-100. Null when responseCount < minimumResponses — never 0. */
3752
+ score?: Maybe<Scalars['Float']['output']>;
3753
+ };
3679
3754
  /** Cumulative flow diagram data for a project over a date range. */
3680
3755
  export type PlanmagnetCumulativeFlow = {
3681
3756
  __typename?: 'PlanmagnetCumulativeFlow';
@@ -3706,6 +3781,118 @@ export type PlanmagnetCustomFieldValueList = {
3706
3781
  pageInfo: PlanmagnetPageInfo;
3707
3782
  totalCount: Scalars['Int']['output'];
3708
3783
  };
3784
+ /**
3785
+ * Customer satisfaction for one scope and window — CSAT and NPS side by side, each with its own response count and its
3786
+ * own minimum. The scope fields echo the filter (null = not filtered on).
3787
+ */
3788
+ export type PlanmagnetCustomerSatisfaction = {
3789
+ __typename?: 'PlanmagnetCustomerSatisfaction';
3790
+ /** The default delivery KPI. */
3791
+ csat: PlanmagnetCsatScore;
3792
+ nps: PlanmagnetNpsScore;
3793
+ productId?: Maybe<Scalars['ID']['output']>;
3794
+ projectId?: Maybe<Scalars['ID']['output']>;
3795
+ releaseId?: Maybe<Scalars['ID']['output']>;
3796
+ window: PlanmagnetSatisfactionWindow;
3797
+ workspaceId: Scalars['ID']['output'];
3798
+ };
3799
+ /**
3800
+ * Which responses a figure (or a list) covers. Filters combine (AND). `productId` matches responses linked to that
3801
+ * product, and responses linked to one of its releases that name no product of their own (read through the release at
3802
+ * query time). `releaseId` and `projectId` match that link only.
3803
+ */
3804
+ export type PlanmagnetCustomerSatisfactionFilter = {
3805
+ productId?: InputMaybe<Scalars['ID']['input']>;
3806
+ projectId?: InputMaybe<Scalars['ID']['input']>;
3807
+ releaseId?: InputMaybe<Scalars['ID']['input']>;
3808
+ /** Defaults to the trailing 90 days. */
3809
+ window?: InputMaybe<PlanmagnetSatisfactionWindowInput>;
3810
+ };
3811
+ export type PlanmagnetCustomerSatisfactionImportResult = {
3812
+ __typename?: 'PlanmagnetCustomerSatisfactionImportResult';
3813
+ /** Responses written by this call. */
3814
+ createdCount: Scalars['Int']['output'];
3815
+ /**
3816
+ * Rows whose externalId this workspace had already imported — including a response deleted since, which stays
3817
+ * deleted. Skipped: never updated, never duplicated.
3818
+ */
3819
+ skippedCount: Scalars['Int']['output'];
3820
+ /** The skipped rows' externalIds, in row order. */
3821
+ skippedExternalIds: Array<Scalars['String']['output']>;
3822
+ };
3823
+ /**
3824
+ * One row of an import — the create rules, plus a required externalId (the key that makes re-importing the same file a
3825
+ * no-op).
3826
+ */
3827
+ export type PlanmagnetCustomerSatisfactionImportRow = {
3828
+ comment?: InputMaybe<Scalars['String']['input']>;
3829
+ /** 1-200 characters, unique within the import. */
3830
+ externalId: Scalars['String']['input'];
3831
+ isAnonymous?: InputMaybe<Scalars['Boolean']['input']>;
3832
+ metricType: PlanmagnetSatisfactionMetricType;
3833
+ productId?: InputMaybe<Scalars['ID']['input']>;
3834
+ projectId?: InputMaybe<Scalars['ID']['input']>;
3835
+ releaseId?: InputMaybe<Scalars['ID']['input']>;
3836
+ respondedAt: Scalars['DateTime']['input'];
3837
+ respondentEmail?: InputMaybe<Scalars['String']['input']>;
3838
+ respondentName?: InputMaybe<Scalars['String']['input']>;
3839
+ score: Scalars['Int']['input'];
3840
+ };
3841
+ /**
3842
+ * One customer's answer. Links to a product, a release and/or a project — at least one. Deleting (soft) a linked
3843
+ * product, release or project leaves the response in place: it is the customer's answer, and the link reads as null.
3844
+ */
3845
+ export type PlanmagnetCustomerSatisfactionResponse = {
3846
+ __typename?: 'PlanmagnetCustomerSatisfactionResponse';
3847
+ /** Plain text, at most 5000 characters. Never rendered as HTML server-side. */
3848
+ comment?: Maybe<Scalars['String']['output']>;
3849
+ createdAt: Scalars['DateTime']['output'];
3850
+ createdBy: Scalars['String']['output'];
3851
+ deletedAt?: Maybe<Scalars['DateTime']['output']>;
3852
+ /** The answer's id in the system it came from. Unique per workspace and source among live responses. */
3853
+ externalId?: Maybe<Scalars['String']['output']>;
3854
+ id: Scalars['ID']['output'];
3855
+ /** When true, no respondent identity is stored — respondentName and respondentEmail are always null. */
3856
+ isAnonymous: Scalars['Boolean']['output'];
3857
+ metricType: PlanmagnetSatisfactionMetricType;
3858
+ /** Null if there is no product link, or that product has since been deleted. */
3859
+ product?: Maybe<Product>;
3860
+ productId?: Maybe<Scalars['String']['output']>;
3861
+ /** Null if there is no project link, or that project has since been deleted. */
3862
+ project?: Maybe<PlanmagnetProject>;
3863
+ projectId?: Maybe<Scalars['String']['output']>;
3864
+ /** Null if there is no release link, or that release has since been deleted. */
3865
+ release?: Maybe<Release>;
3866
+ releaseId?: Maybe<Scalars['String']['output']>;
3867
+ /** When the customer answered — what every window filters on. */
3868
+ respondedAt: Scalars['DateTime']['output'];
3869
+ /** The respondent's email as recorded, or null. Never set on an anonymous response. */
3870
+ respondentEmail?: Maybe<Scalars['String']['output']>;
3871
+ /** The respondent's name as recorded, or null. Never set on an anonymous response. */
3872
+ respondentName?: Maybe<Scalars['String']['output']>;
3873
+ /** CSAT 1-5, NPS 0-10. */
3874
+ score: Scalars['Int']['output'];
3875
+ source: PlanmagnetSatisfactionResponseSource;
3876
+ updatedAt: Scalars['DateTime']['output'];
3877
+ updatedBy?: Maybe<Scalars['String']['output']>;
3878
+ workspaceId: Scalars['String']['output'];
3879
+ };
3880
+ export type PlanmagnetCustomerSatisfactionResponseFilter = {
3881
+ metricType?: InputMaybe<PlanmagnetSatisfactionMetricType>;
3882
+ /** Same product rule as PlanmagnetCustomerSatisfactionFilter.productId. */
3883
+ productId?: InputMaybe<Scalars['ID']['input']>;
3884
+ projectId?: InputMaybe<Scalars['ID']['input']>;
3885
+ releaseId?: InputMaybe<Scalars['ID']['input']>;
3886
+ source?: InputMaybe<PlanmagnetSatisfactionResponseSource>;
3887
+ /** Omitted: every response, whenever it was given. */
3888
+ window?: InputMaybe<PlanmagnetSatisfactionWindowInput>;
3889
+ };
3890
+ export type PlanmagnetCustomerSatisfactionResponseList = {
3891
+ __typename?: 'PlanmagnetCustomerSatisfactionResponseList';
3892
+ items: Array<PlanmagnetCustomerSatisfactionResponse>;
3893
+ pageInfo: PlanmagnetPageInfo;
3894
+ totalCount: Scalars['Int']['output'];
3895
+ };
3709
3896
  /**
3710
3897
  * Cycle-time distribution for a project over a date range. Only work items
3711
3898
  * with a recorded transition INTO DONE within the range are counted — an item
@@ -3771,13 +3958,20 @@ export type PlanmagnetDeliveryForecast = {
3771
3958
  };
3772
3959
  /**
3773
3960
  * On-time delivery and scope-adherence KPIs across sprints, releases and milestones COMPLETED within a date
3774
- * range (default: the trailing 30 days), for a workspace or one project (ANR-21).
3775
- *
3776
- * `customerSatisfaction` is deliberately NOT a field here: PlanMagnet has no survey/NPS/CSAT data source to
3777
- * back it, and a placeholder that always read null or zero would be worse than its absence.
3961
+ * range (default: the trailing 30 days), for a workspace or one project (ANR-21), plus customer satisfaction
3962
+ * (CSAT, the default delivery KPI, and NPS) from recorded customer responses — see `customerSatisfaction`.
3778
3963
  */
3779
3964
  export type PlanmagnetDeliveryKpis = {
3780
3965
  __typename?: 'PlanmagnetDeliveryKpis';
3966
+ /**
3967
+ * ANR-21: CSAT (the default delivery KPI) and NPS from customer-satisfaction responses about this scope — the
3968
+ * workspace, or responses linked to `projectId` — exactly as planmagnetCustomerSatisfaction computes them (a
3969
+ * score needs at least 5 responses per metric; below that it is null, never 0). Its window: when this query was
3970
+ * given startDate and/or endDate, the same UTC days as every other KPI here (startDate..endDate); when it was
3971
+ * given neither, the satisfaction default — the trailing 90 days — not this query's 30-day default.
3972
+ * `customerSatisfaction.window` always states which. Computed only when selected.
3973
+ */
3974
+ customerSatisfaction: PlanmagnetCustomerSatisfaction;
3781
3975
  endDate: Scalars['DateTime']['output'];
3782
3976
  /** Milestones (status COMPLETED) whose completedDate fell in range. */
3783
3977
  milestoneCount: Scalars['Int']['output'];
@@ -4220,6 +4414,10 @@ export type PlanmagnetGenerateReleaseNotesPayload = {
4220
4414
  markdown: Scalars['String']['output'];
4221
4415
  release: Release;
4222
4416
  };
4417
+ export type PlanmagnetImportCustomerSatisfactionResponsesInput = {
4418
+ /** 1 to 500 rows, parsed from a CSV by the client. */
4419
+ rows: Array<PlanmagnetCustomerSatisfactionImportRow>;
4420
+ };
4223
4421
  /**
4224
4422
  * Import issues exported from an external tool (e.g. Linear) as WorkItems.
4225
4423
  * The caller supplies the exported payload directly (no external API credentials).
@@ -4607,6 +4805,24 @@ export type PlanmagnetNoEpicWorkBreakdown = {
4607
4805
  openCount: Scalars['Int']['output'];
4608
4806
  openPoints: Scalars['Int']['output'];
4609
4807
  };
4808
+ /** NPS over a scope and window. `score` is exact (no server-side rounding) and is never an average of the answers. */
4809
+ export type PlanmagnetNpsScore = {
4810
+ __typename?: 'PlanmagnetNpsScore';
4811
+ /** 0s to 6s. */
4812
+ detractorCount: Scalars['Int']['output'];
4813
+ /** 5: fewer responses than this give no score. */
4814
+ minimumResponses: Scalars['Int']['output'];
4815
+ /** True when responseCount < minimumResponses (score is then null). */
4816
+ notEnoughResponses: Scalars['Boolean']['output'];
4817
+ /** 7s and 8s. */
4818
+ passiveCount: Scalars['Int']['output'];
4819
+ /** 9s and 10s. */
4820
+ promoterCount: Scalars['Int']['output'];
4821
+ /** NPS responses counted (promoters + passives + detractors). */
4822
+ responseCount: Scalars['Int']['output'];
4823
+ /** (promoterCount - detractorCount) * 100 / responseCount, -100 to 100. Null when responseCount < minimumResponses. */
4824
+ score?: Maybe<Scalars['Float']['output']>;
4825
+ };
4610
4826
  /**
4611
4827
  * A workspace-scoped goal for a given time period. `progress` is the average
4612
4828
  * of its non-deleted KeyResults' progress (0 when it has none).
@@ -5277,24 +5493,50 @@ export declare enum PlanmagnetQualityTrendDirection {
5277
5493
  /** recentDefectRatio is at least 10% above priorDefectRatio. */
5278
5494
  Worsening = "WORSENING"
5279
5495
  }
5280
- /** Workspace-level quota usage and limits for PlanMagnet. */
5496
+ /**
5497
+ * Workspace-level quota usage and limits for PlanMagnet. Each limit is the one
5498
+ * enforced for that quota: the sum of the workspace's active billing assignments
5499
+ * for it. A limit is null when none is known: an assignment is unlimited, the
5500
+ * workspace holds no assignment for the quota, or billing could not be reached.
5501
+ */
5281
5502
  export type PlanmagnetQuotaOverview = {
5282
5503
  __typename?: 'PlanmagnetQuotaOverview';
5283
5504
  /** Number of active automation rules in the workspace */
5284
5505
  automationRuleCount: Scalars['Int']['output'];
5285
- /** Monthly automation run quota limit (null when unlimited or unassigned) */
5506
+ /**
5507
+ * Automation runs the workspace may execute per month
5508
+ * (`planmagnet.automation.runs_monthly`, the limit the run gate checks). Null
5509
+ * when unlimited, unassigned, or billing could not be reached. Unlike the other
5510
+ * limits, unassigned does not mean uncapped: the run gate refuses every run
5511
+ * while the workspace holds no assignment for this quota.
5512
+ */
5286
5513
  automationRunsMonthlyLimit?: Maybe<Scalars['Int']['output']>;
5287
5514
  /** Number of active boards across all projects */
5288
5515
  boardCount: Scalars['Int']['output'];
5289
- /** Board quota limit (null when unlimited or unassigned) */
5516
+ /**
5517
+ * Most active boards the workspace may hold (`planmagnet.boards.count`, the
5518
+ * limit board creation is checked against). Null when unlimited, unassigned, or
5519
+ * billing could not be reached; board creation is not capped in any of those
5520
+ * cases.
5521
+ */
5290
5522
  boardLimit?: Maybe<Scalars['Int']['output']>;
5291
5523
  /** Number of active editor seats in the workspace (BOFF-5094) */
5292
5524
  editorCount: Scalars['Int']['output'];
5293
- /** Editor quota limit (null when unlimited or unassigned) */
5525
+ /**
5526
+ * Most editor seats the workspace may hold (`planmagnet.editors.count`, the
5527
+ * limit editor grants are checked against). Null when unlimited, unassigned, or
5528
+ * billing could not be reached; editor grants are not capped in any of those
5529
+ * cases.
5530
+ */
5294
5531
  editorLimit?: Maybe<Scalars['Int']['output']>;
5295
5532
  /** Number of active projects in the workspace */
5296
5533
  projectCount: Scalars['Int']['output'];
5297
- /** Project quota limit (null when unlimited or unassigned) */
5534
+ /**
5535
+ * Most active projects the workspace may hold (`planmagnet.projects.count`,
5536
+ * the limit project creation is checked against). Null when unlimited,
5537
+ * unassigned, or billing could not be reached; project creation is not capped
5538
+ * in any of those cases.
5539
+ */
5298
5540
  projectLimit?: Maybe<Scalars['Int']['output']>;
5299
5541
  /** Workspace identifier */
5300
5542
  workspaceId: Scalars['ID']['output'];
@@ -5989,6 +6231,48 @@ export type PlanmagnetRoadmapVersionSummary = {
5989
6231
  note?: Maybe<Scalars['String']['output']>;
5990
6232
  roadmapId: Scalars['ID']['output'];
5991
6233
  };
6234
+ /**
6235
+ * CSAT: a 1-5 answer, 4-5 counted as satisfied. NPS: a 0-10 answer, 9-10 promoters, 7-8 passives, 0-6 detractors.
6236
+ * TEXT-backed in Prisma; this enum (and the service) is the only validator.
6237
+ */
6238
+ export declare enum PlanmagnetSatisfactionMetricType {
6239
+ Csat = "CSAT",
6240
+ Nps = "NPS"
6241
+ }
6242
+ /**
6243
+ * Where a response came from: MANUAL (entered one at a time by a team member) or IMPORT (a batch from a file). Set by
6244
+ * the mutation used — never by the caller.
6245
+ */
6246
+ export declare enum PlanmagnetSatisfactionResponseSource {
6247
+ Import = "IMPORT",
6248
+ Manual = "MANUAL"
6249
+ }
6250
+ export type PlanmagnetSatisfactionWindow = {
6251
+ __typename?: 'PlanmagnetSatisfactionWindow';
6252
+ /** The start of the first UTC day counted. */
6253
+ from: Scalars['DateTime']['output'];
6254
+ preset: PlanmagnetSatisfactionWindowPreset;
6255
+ /** The end (23:59:59.999) of the last UTC day counted. */
6256
+ to: Scalars['DateTime']['output'];
6257
+ };
6258
+ /** The window a figure covers. Responses count when their respondedAt is in [from, to], both ends included. */
6259
+ export type PlanmagnetSatisfactionWindowInput = {
6260
+ /** CUSTOM only (required there). Any other preset with from/to is BAD_USER_INPUT. */
6261
+ from?: InputMaybe<Scalars['DateTime']['input']>;
6262
+ /** Defaults to LAST_90_DAYS. */
6263
+ preset?: InputMaybe<PlanmagnetSatisfactionWindowPreset>;
6264
+ /** CUSTOM only (required there). Not before `from`. */
6265
+ to?: InputMaybe<Scalars['DateTime']['input']>;
6266
+ };
6267
+ /** A satisfaction window: the N UTC calendar days ending today (today included), or CUSTOM. */
6268
+ export declare enum PlanmagnetSatisfactionWindowPreset {
6269
+ /** From the start of `from`'s UTC day to the end of `to`'s — both required. */
6270
+ Custom = "CUSTOM",
6271
+ Last_30Days = "LAST_30_DAYS",
6272
+ Last_90Days = "LAST_90_DAYS",
6273
+ Last_180Days = "LAST_180_DAYS",
6274
+ Last_365Days = "LAST_365_DAYS"
6275
+ }
5992
6276
  export type PlanmagnetSaveRoadmapVersionInput = {
5993
6277
  /** At most 120 characters */
5994
6278
  name: Scalars['String']['input'];
@@ -6032,6 +6316,108 @@ export type PlanmagnetSharedReport = {
6032
6316
  /** FORBIDDEN widgets stay FORBIDDEN — exactly as the run recorded them; this endpoint grants no new access. */
6033
6317
  widgets: Array<PlanmagnetWidgetRunResult>;
6034
6318
  };
6319
+ /** One skill's coverage in the requested scope. */
6320
+ export type PlanmagnetSkillCoverage = {
6321
+ __typename?: 'PlanmagnetSkillCoverage';
6322
+ /** The part of openDemand that has an assignee — anyone, qualified or not */
6323
+ assignedDemand: PlanmagnetSkillDemand;
6324
+ /** Open work items in scope (not DONE or CANCELLED, not deleted, in a live project) that require the skill */
6325
+ openDemand: PlanmagnetSkillDemand;
6326
+ /** The number of qualifiedMembers */
6327
+ qualifiedMemberCount: Scalars['Int']['output'];
6328
+ /** Qualified members, ordered by name. Empty when status is UNKNOWN */
6329
+ qualifiedMembers: Array<PlanmagnetSkillQualifiedMember>;
6330
+ /**
6331
+ * The skill tag, in the first spelling found — open work items (oldest first) before CrewFoundry. Matching ignores
6332
+ * case and surrounding/repeated whitespace
6333
+ */
6334
+ skill: Scalars['String']['output'];
6335
+ status: PlanmagnetSkillCoverageStatus;
6336
+ /** Qualified members assigned none of this skill's open demand in scope (assignedDemandCount = 0) */
6337
+ unassignedQualifiedCount: Scalars['Int']['output'];
6338
+ };
6339
+ /**
6340
+ * Narrows planmagnetSkillCoverage. Every field is optional; the ones given are AND-ed together. A given id must be a
6341
+ * live project / team / sprint of this workspace (NOT_FOUND otherwise).
6342
+ */
6343
+ export type PlanmagnetSkillCoverageFilter = {
6344
+ /** Only open work items of this project */
6345
+ projectId?: InputMaybe<Scalars['ID']['input']>;
6346
+ /** Only open work items in this sprint */
6347
+ sprintId?: InputMaybe<Scalars['ID']['input']>;
6348
+ /**
6349
+ * Only open work items of this team's live projects — and only this team's live members (who are active workspace
6350
+ * members) count as qualified. Without a team, every active workspace member counts
6351
+ */
6352
+ teamId?: InputMaybe<Scalars['ID']['input']>;
6353
+ };
6354
+ /**
6355
+ * Skill coverage for a workspace, optionally narrowed (ANR-07 skill view, ANR-28 skill utilization). Utilization is
6356
+ * counts and story points only — hours-based skill utilization is NOT computed until CrewFoundry has a per-person
6357
+ * capacity baseline (CWF-28).
6358
+ */
6359
+ export type PlanmagnetSkillCoverageResult = {
6360
+ __typename?: 'PlanmagnetSkillCoverageResult';
6361
+ /**
6362
+ * True when the CrewFoundry roster could not be read in full (unreachable, or failing part-way through paging).
6363
+ * Qualified members are then not counted and every skill with open demand is UNKNOWN. An empty roster is NOT
6364
+ * unavailable
6365
+ */
6366
+ crewfoundryUnavailable: Scalars['Boolean']['output'];
6367
+ /**
6368
+ * True when the workspace member directory (or the members' e-mail identities) could not be read in full. Qualified
6369
+ * members are then not counted and every skill with open demand is UNKNOWN
6370
+ */
6371
+ membersUnavailable: Scalars['Boolean']['output'];
6372
+ /**
6373
+ * One row per skill that open work in scope requires or a qualified member has: UNCOVERED first, then UNKNOWN,
6374
+ * COVERED and NO_DEMAND; within each, most open work items first, then by skill
6375
+ */
6376
+ skills: Array<PlanmagnetSkillCoverage>;
6377
+ /**
6378
+ * True when more than 5,000 open work items in scope require a skill: the demand figures then cover the 5,000
6379
+ * oldest only
6380
+ */
6381
+ truncated: Scalars['Boolean']['output'];
6382
+ };
6383
+ /** How well a skill's open demand is covered by qualified members. */
6384
+ export declare enum PlanmagnetSkillCoverageStatus {
6385
+ /** Open work in scope requires the skill and at least one qualified member exists */
6386
+ Covered = "COVERED",
6387
+ /** No open work in scope requires the skill — it is listed because a qualified member has it */
6388
+ NoDemand = "NO_DEMAND",
6389
+ /** Open work in scope requires the skill and no qualified member exists */
6390
+ Uncovered = "UNCOVERED",
6391
+ /**
6392
+ * Open work in scope requires the skill, but qualified members could not be counted: CrewFoundry or the workspace
6393
+ * member directory could not be read (see crewfoundryUnavailable / membersUnavailable). Never reported as UNCOVERED
6394
+ */
6395
+ Unknown = "UNKNOWN"
6396
+ }
6397
+ /**
6398
+ * Open work items requiring a skill: how many, and the sum of their story points (an item with no estimate counts as
6399
+ * 0 — the same rule as planmagnetWorkItemCounts and the sprint analytics).
6400
+ */
6401
+ export type PlanmagnetSkillDemand = {
6402
+ __typename?: 'PlanmagnetSkillDemand';
6403
+ storyPoints: Scalars['Int']['output'];
6404
+ workItemCount: Scalars['Int']['output'];
6405
+ };
6406
+ /**
6407
+ * A workspace member whose matched, ACTIVE CrewFoundry employee record lists the skill. The member is matched the
6408
+ * same way sprint capacity matches an assignee: the CWF-30 identity override first, else the workspace e-mail.
6409
+ */
6410
+ export type PlanmagnetSkillQualifiedMember = {
6411
+ __typename?: 'PlanmagnetSkillQualifiedMember';
6412
+ /** Platform actor id (the same value as WorkItem.assigneeId) */
6413
+ actorId: Scalars['String']['output'];
6414
+ /** Open work items in scope that require this skill and are assigned to this member */
6415
+ assignedDemandCount: Scalars['Int']['output'];
6416
+ /** The matched CrewFoundry CrewEmployee.id */
6417
+ employeeId: Scalars['ID']['output'];
6418
+ /** The CrewFoundry employee's full name */
6419
+ employeeName: Scalars['String']['output'];
6420
+ };
6035
6421
  export declare enum PlanmagnetSortDirection {
6036
6422
  Asc = "ASC",
6037
6423
  Desc = "DESC"
@@ -6053,11 +6439,12 @@ export type PlanmagnetSprintBurndown = {
6053
6439
  export type PlanmagnetSprintCapacity = {
6054
6440
  __typename?: 'PlanmagnetSprintCapacity';
6055
6441
  /**
6056
- * True when the CrewFoundry roster lookup itself returned nothing — either
6057
- * a live lookup failure (service unreachable/timeout) or a workspace with no
6058
- * CrewFoundry data. `members`/`unmatchedAssigneeIds` cannot distinguish the
6059
- * two cases from PlanMagnet's side; this flag exists so callers can render
6060
- * "capacity data unavailable" instead of silently showing an empty list.
6442
+ * True when the CrewFoundry roster could not be read in full — the service
6443
+ * unreachable or timing out, or failing part-way through paging the roster.
6444
+ * Callers render "capacity data unavailable" instead of an empty list. A
6445
+ * workspace whose CrewFoundry roster is readable but EMPTY is NOT unavailable:
6446
+ * its assignees are listed in `unmatchedAssigneeIds`, like any other assignee
6447
+ * with no matching CrewFoundry employee.
6061
6448
  */
6062
6449
  crewfoundryUnavailable: Scalars['Boolean']['output'];
6063
6450
  /**
@@ -6113,6 +6500,12 @@ export type PlanmagnetSprintCapacityMember = {
6113
6500
  employeeName: Scalars['String']['output'];
6114
6501
  /** CrewFoundry position/title */
6115
6502
  position: Scalars['String']['output'];
6503
+ /**
6504
+ * The employee's skill tags as CrewFoundry records them (tidied: trimmed, whitespace collapsed, case-insensitive
6505
+ * duplicates dropped). Read-only — CrewFoundry is canonical for person skills and PlanMagnet never writes them;
6506
+ * edit them in CrewFoundry. Empty when CrewFoundry lists none.
6507
+ */
6508
+ skills: Array<Scalars['String']['output']>;
6116
6509
  /**
6117
6510
  * `billableHours / allocatedHours * 100`, rounded to 1 decimal place. Null
6118
6511
  * when `allocatedHours` is 0 (nothing to divide by).
@@ -6685,6 +7078,34 @@ export type PlanmagnetUpdateCustomFieldDefinitionInput = {
6685
7078
  sortOrder?: InputMaybe<Scalars['Int']['input']>;
6686
7079
  validationRules?: InputMaybe<Scalars['JSON']['input']>;
6687
7080
  };
7081
+ /**
7082
+ * `source` and `externalId` are absent: they identify where the answer came from and never change. An omitted field
7083
+ * keeps its value. A new metricType is checked against the stored score (and a new score against the stored type).
7084
+ * Sending any of productId/releaseId/projectId re-checks the whole resulting link set (null clears a link; one must
7085
+ * remain). isAnonymous true clears any stored respondent identity.
7086
+ */
7087
+ export type PlanmagnetUpdateCustomerSatisfactionResponseInput = {
7088
+ /** Null clears it. */
7089
+ comment?: InputMaybe<Scalars['String']['input']>;
7090
+ /** Cannot be cleared. */
7091
+ isAnonymous?: InputMaybe<Scalars['Boolean']['input']>;
7092
+ /** Cannot be cleared. */
7093
+ metricType?: InputMaybe<PlanmagnetSatisfactionMetricType>;
7094
+ /** Null clears it. */
7095
+ productId?: InputMaybe<Scalars['ID']['input']>;
7096
+ /** Null clears it. */
7097
+ projectId?: InputMaybe<Scalars['ID']['input']>;
7098
+ /** Null clears it. */
7099
+ releaseId?: InputMaybe<Scalars['ID']['input']>;
7100
+ /** Cannot be cleared. */
7101
+ respondedAt?: InputMaybe<Scalars['DateTime']['input']>;
7102
+ /** Null clears it. */
7103
+ respondentEmail?: InputMaybe<Scalars['String']['input']>;
7104
+ /** Null clears it. */
7105
+ respondentName?: InputMaybe<Scalars['String']['input']>;
7106
+ /** Cannot be cleared. */
7107
+ score?: InputMaybe<Scalars['Int']['input']>;
7108
+ };
6688
7109
  export type PlanmagnetUpdateDependencyInput = {
6689
7110
  description?: InputMaybe<Scalars['String']['input']>;
6690
7111
  lagMinutes?: InputMaybe<Scalars['Int']['input']>;
@@ -7073,6 +7494,8 @@ export type PlanmagnetUpdateWorkItemInput = {
7073
7494
  parentId?: InputMaybe<Scalars['String']['input']>;
7074
7495
  priority?: InputMaybe<WorkItemPriority>;
7075
7496
  reporterId?: InputMaybe<Scalars['String']['input']>;
7497
+ /** Replaces the item's required skills (same rules as on create); null or [] clears them, leaving it out keeps them */
7498
+ requiredSkills?: InputMaybe<Array<Scalars['String']['input']>>;
7076
7499
  sortOrder?: InputMaybe<Scalars['Int']['input']>;
7077
7500
  sprintId?: InputMaybe<Scalars['String']['input']>;
7078
7501
  status?: InputMaybe<WorkItemStatus>;
@@ -8074,6 +8497,15 @@ export type Query = {
8074
8497
  planmagnetCustomFieldDefinitions: PlanmagnetCustomFieldDefinitionList;
8075
8498
  /** List custom field values */
8076
8499
  planmagnetCustomFieldValues: PlanmagnetCustomFieldValueList;
8500
+ /**
8501
+ * CSAT and NPS for the workspace, or one product/release/project (see PlanmagnetCustomerSatisfactionFilter), over a
8502
+ * window — default the trailing 90 days. Computed in the database from live responses only.
8503
+ */
8504
+ planmagnetCustomerSatisfaction: PlanmagnetCustomerSatisfaction;
8505
+ /** Null when it does not exist in this workspace or was deleted. */
8506
+ planmagnetCustomerSatisfactionResponse?: Maybe<PlanmagnetCustomerSatisfactionResponse>;
8507
+ /** Live responses, newest answer first. Same filter rules as planmagnetCustomerSatisfaction. */
8508
+ planmagnetCustomerSatisfactionResponses: PlanmagnetCustomerSatisfactionResponseList;
8077
8509
  /**
8078
8510
  * Cycle-time distribution for a project's work items that reached DONE
8079
8511
  * within a date range (defaults to the trailing 90 days).
@@ -8160,7 +8592,10 @@ export type Query = {
8160
8592
  * project/sprint-scoped and feed planmagnetAnalytics.projectMetrics instead — see PlanmagnetAnalytics). Backed
8161
8593
  * by planmagnetDeliveryKpis, the one query in this module already scoped to the whole workspace. `category`
8162
8594
  * narrows to one named metric (sprintOnTimeRate | releaseOnTimeRate | milestoneOnTimeRate |
8163
- * scopeAdherenceRate); omitted, every metric with a real (non-null-denominator) value is returned.
8595
+ * scopeAdherenceRate); omitted, every metric with a real (non-null-denominator) value is returned. Customer
8596
+ * satisfaction is deliberately not a row here: a CSAT/NPS figure is always shown with its response count and
8597
+ * window (owner decision 2026-10-02), which a PlanmagnetMetric row cannot carry — read
8598
+ * planmagnetDeliveryKpis.customerSatisfaction or planmagnetCustomerSatisfaction instead.
8164
8599
  */
8165
8600
  planmagnetMetrics: Array<PlanmagnetMetric>;
8166
8601
  /** Get a single milestone by ID */
@@ -8352,6 +8787,12 @@ export type Query = {
8352
8787
  * nothing a possessor of a valid-looking token could not already infer.
8353
8788
  */
8354
8789
  planmagnetSharedReport?: Maybe<PlanmagnetSharedReport>;
8790
+ /**
8791
+ * Skill coverage (ANR-07, ANR-28): per skill, the open work requiring it, how much of that is assigned, and which
8792
+ * active workspace members are qualified by their CrewFoundry skills (read-only — PlanMagnet never writes
8793
+ * CrewFoundry). Hours-based skill utilization is not computed until CWF-28 adds a per-person capacity baseline.
8794
+ */
8795
+ planmagnetSkillCoverage: PlanmagnetSkillCoverageResult;
8355
8796
  /** Get a single sprint by ID */
8356
8797
  planmagnetSprint?: Maybe<Sprint>;
8357
8798
  /**
@@ -8564,6 +9005,18 @@ export type QueryPlanmagnetCustomFieldValuesArgs = {
8564
9005
  pagination?: InputMaybe<PlanmagnetPaginationInput>;
8565
9006
  workspaceId: Scalars['ID']['input'];
8566
9007
  };
9008
+ export type QueryPlanmagnetCustomerSatisfactionArgs = {
9009
+ filter?: InputMaybe<PlanmagnetCustomerSatisfactionFilter>;
9010
+ workspaceId: Scalars['ID']['input'];
9011
+ };
9012
+ export type QueryPlanmagnetCustomerSatisfactionResponseArgs = {
9013
+ id: Scalars['ID']['input'];
9014
+ };
9015
+ export type QueryPlanmagnetCustomerSatisfactionResponsesArgs = {
9016
+ filter?: InputMaybe<PlanmagnetCustomerSatisfactionResponseFilter>;
9017
+ pagination?: InputMaybe<PlanmagnetPaginationInput>;
9018
+ workspaceId: Scalars['ID']['input'];
9019
+ };
8567
9020
  export type QueryPlanmagnetCycleTimeArgs = {
8568
9021
  endDate?: InputMaybe<Scalars['DateTime']['input']>;
8569
9022
  projectId: Scalars['ID']['input'];
@@ -8887,6 +9340,10 @@ export type QueryPlanmagnetSharedReportArgs = {
8887
9340
  password?: InputMaybe<Scalars['String']['input']>;
8888
9341
  token: Scalars['String']['input'];
8889
9342
  };
9343
+ export type QueryPlanmagnetSkillCoverageArgs = {
9344
+ filter?: InputMaybe<PlanmagnetSkillCoverageFilter>;
9345
+ workspaceId: Scalars['ID']['input'];
9346
+ };
8890
9347
  export type QueryPlanmagnetSprintArgs = {
8891
9348
  id: Scalars['ID']['input'];
8892
9349
  };
@@ -9627,6 +10084,12 @@ export type UniversalTag = {
9627
10084
  */
9628
10085
  export type WorkItem = {
9629
10086
  __typename?: 'WorkItem';
10087
+ /**
10088
+ * For an EPIC: the union of its own requiredSkills and those of its live (not deleted) direct children, in that
10089
+ * order, case-insensitive duplicates dropped keeping the first spelling. Computed on every read and never copied onto
10090
+ * the epic, so it cannot drift from the children. For every other type: exactly requiredSkills. Read-only.
10091
+ */
10092
+ aggregatedRequiredSkills: Array<Scalars['String']['output']>;
9630
10093
  /** Assigned actor ID */
9631
10094
  assigneeId?: Maybe<Scalars['String']['output']>;
9632
10095
  /** Children work items */
@@ -9703,6 +10166,13 @@ export type WorkItem = {
9703
10166
  projectId: Scalars['String']['output'];
9704
10167
  /** Reporter actor ID */
9705
10168
  reporterId?: Maybe<Scalars['String']['output']>;
10169
+ /**
10170
+ * Skills this work item needs (ANR-07, ANR-28, CWF-29) — PlanMagnet's own free-text tags, normalized on every write:
10171
+ * trimmed, inner whitespace collapsed, case-insensitive duplicates dropped keeping the first spelling, at most 20
10172
+ * tags of at most 64 characters each. Matched case-insensitively against CrewFoundry person skills, which PlanMagnet
10173
+ * only reads (see planmagnetSkillCoverage). Empty when none are set.
10174
+ */
10175
+ requiredSkills: Array<Scalars['String']['output']>;
9706
10176
  /** Sort order within lists */
9707
10177
  sortOrder: Scalars['Int']['output'];
9708
10178
  /** Sprint reference */