exponential-sdk 1.11.0 → 1.12.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.
package/dist/index.d.ts CHANGED
@@ -41,6 +41,77 @@ type ActionCreateInput$1 = {
41
41
  effortEstimate?: number;
42
42
  blockedByIds?: string[];
43
43
  };
44
+ type GoalStatusInput = 'planned' | 'active' | 'completed' | 'archived';
45
+ /** Reads and `updateGoalStatus` also accept `on-hold`; `updateGoal` does not. */
46
+ type GoalQueryStatusInput = GoalStatusInput | 'on-hold';
47
+ type GoalCreateProcedureInput = {
48
+ title: string;
49
+ description?: string;
50
+ whyThisGoal?: string;
51
+ notes?: string;
52
+ dueDate?: Date;
53
+ period?: string;
54
+ status?: GoalStatusInput;
55
+ lifeDomainId?: number;
56
+ projectId?: string;
57
+ outcomeIds?: string[];
58
+ driUserId?: string;
59
+ workspaceId?: string;
60
+ parentGoalId?: number;
61
+ icon?: string | null;
62
+ iconColor?: string | null;
63
+ };
64
+ type GoalUpdateProcedureInput = {
65
+ id: number;
66
+ title?: string;
67
+ description?: string | null;
68
+ whyThisGoal?: string | null;
69
+ notes?: string | null;
70
+ dueDate?: Date | null;
71
+ period?: string | null;
72
+ status?: GoalStatusInput;
73
+ lifeDomainId?: number | null;
74
+ projectId?: string | null;
75
+ projectIds?: string[];
76
+ outcomeIds?: string[];
77
+ driUserId?: string | null;
78
+ workspaceId?: string | null;
79
+ parentGoalId?: number | null;
80
+ displayOrder?: number;
81
+ icon?: string | null;
82
+ iconColor?: string | null;
83
+ };
84
+ type KeyResultStatusInput = 'not-started' | 'on-track' | 'at-risk' | 'off-track' | 'achieved';
85
+ type KeyResultUnitInput = 'percent' | 'count' | 'currency' | 'hours' | 'custom';
86
+ type KeyResultCreateProcedureInput = {
87
+ goalId: number;
88
+ title: string;
89
+ description?: string;
90
+ targetValue: number;
91
+ startValue?: number;
92
+ currentValue?: number;
93
+ unit?: KeyResultUnitInput;
94
+ unitLabel?: string;
95
+ period: string;
96
+ periodStart?: Date;
97
+ periodEnd?: Date;
98
+ driUserId?: string;
99
+ workspaceId?: string;
100
+ };
101
+ type KeyResultUpdateProcedureInput = {
102
+ id: string;
103
+ title?: string;
104
+ description?: string;
105
+ targetValue?: number;
106
+ currentValue?: number;
107
+ startValue?: number;
108
+ unit?: KeyResultUnitInput;
109
+ unitLabel?: string;
110
+ status?: KeyResultStatusInput;
111
+ confidence?: number;
112
+ driUserId?: string;
113
+ goalId?: number;
114
+ };
44
115
  type ActionUpdateInput$1 = {
45
116
  id: string;
46
117
  name?: string;
@@ -126,6 +197,140 @@ interface TrpcClient {
126
197
  }) => Promise<unknown[]>;
127
198
  };
128
199
  };
200
+ goal: {
201
+ getById: {
202
+ query: (input: {
203
+ id: number;
204
+ }) => Promise<unknown>;
205
+ };
206
+ getAllMyGoals: {
207
+ query: (input?: {
208
+ workspaceId?: string;
209
+ period?: string;
210
+ status?: GoalQueryStatusInput;
211
+ }) => Promise<unknown[]>;
212
+ };
213
+ getGoalTree: {
214
+ query: (input?: {
215
+ workspaceId?: string;
216
+ status?: GoalQueryStatusInput;
217
+ }) => Promise<unknown[]>;
218
+ };
219
+ getProjectGoals: {
220
+ query: (input: {
221
+ projectId: string;
222
+ }) => Promise<unknown[]>;
223
+ };
224
+ createGoal: {
225
+ mutate: (input: GoalCreateProcedureInput) => Promise<unknown>;
226
+ };
227
+ /**
228
+ * Partial update — only the keys present are written, and an explicit null
229
+ * clears. Every nullable field is therefore `T | null | undefined`.
230
+ */
231
+ updateGoal: {
232
+ mutate: (input: GoalUpdateProcedureInput) => Promise<unknown>;
233
+ };
234
+ /** Status-only write; the only path that accepts `on-hold`. */
235
+ updateGoalStatus: {
236
+ mutate: (input: {
237
+ id: number;
238
+ status: GoalQueryStatusInput;
239
+ }) => Promise<unknown>;
240
+ };
241
+ /** Single-column re-parent; validates no-self / no-cycle / depth-5. */
242
+ setParent: {
243
+ mutate: (input: {
244
+ id: number;
245
+ parentGoalId: number | null;
246
+ }) => Promise<unknown>;
247
+ };
248
+ deleteGoal: {
249
+ mutate: (input: {
250
+ id: number;
251
+ }) => Promise<unknown>;
252
+ };
253
+ };
254
+ okr: {
255
+ getAll: {
256
+ query: (input?: {
257
+ workspaceId?: string;
258
+ goalId?: number;
259
+ period?: string;
260
+ status?: KeyResultStatusInput;
261
+ onlyMine?: boolean;
262
+ }) => Promise<unknown[]>;
263
+ };
264
+ getByObjective: {
265
+ query: (input: {
266
+ workspaceId?: string;
267
+ period?: string;
268
+ includePairedPeriod?: boolean;
269
+ onlyMine?: boolean;
270
+ }) => Promise<unknown[]>;
271
+ };
272
+ getById: {
273
+ query: (input: {
274
+ id: string;
275
+ }) => Promise<unknown>;
276
+ };
277
+ getByIds: {
278
+ query: (input: {
279
+ ids: string[];
280
+ }) => Promise<unknown[]>;
281
+ };
282
+ create: {
283
+ mutate: (input: KeyResultCreateProcedureInput) => Promise<unknown>;
284
+ };
285
+ update: {
286
+ mutate: (input: KeyResultUpdateProcedureInput) => Promise<unknown>;
287
+ };
288
+ checkIn: {
289
+ mutate: (input: {
290
+ keyResultId: string;
291
+ newValue: number;
292
+ notes?: string;
293
+ }) => Promise<unknown>;
294
+ };
295
+ delete: {
296
+ mutate: (input: {
297
+ id: string;
298
+ }) => Promise<unknown>;
299
+ };
300
+ linkProject: {
301
+ mutate: (input: {
302
+ keyResultId: string;
303
+ projectId: string;
304
+ }) => Promise<unknown>;
305
+ };
306
+ unlinkProject: {
307
+ mutate: (input: {
308
+ keyResultId: string;
309
+ projectId: string;
310
+ }) => Promise<unknown>;
311
+ };
312
+ linkFeature: {
313
+ mutate: (input: {
314
+ keyResultId: string;
315
+ featureId: string;
316
+ }) => Promise<unknown>;
317
+ };
318
+ unlinkFeature: {
319
+ mutate: (input: {
320
+ keyResultId: string;
321
+ featureId: string;
322
+ }) => Promise<unknown>;
323
+ };
324
+ getPeriods: {
325
+ query: () => Promise<unknown[]>;
326
+ };
327
+ getStats: {
328
+ query: (input: {
329
+ workspaceId?: string;
330
+ period?: string;
331
+ }) => Promise<unknown>;
332
+ };
333
+ };
129
334
  goalComment: {
130
335
  getComments: {
131
336
  query: (input: {
@@ -1215,6 +1420,558 @@ declare class GoalCommentsApi {
1215
1420
  }>;
1216
1421
  }
1217
1422
 
1423
+ type KeyResultStatus = 'not-started' | 'on-track' | 'at-risk' | 'off-track' | 'achieved';
1424
+ type KeyResultUnit = 'percent' | 'count' | 'currency' | 'hours' | 'custom';
1425
+ interface KeyResultCheckIn {
1426
+ id: string;
1427
+ keyResultId: string;
1428
+ previousValue: number;
1429
+ newValue: number;
1430
+ notes: string | null;
1431
+ createdById: string | null;
1432
+ createdAt: Date;
1433
+ createdBy?: {
1434
+ id: string;
1435
+ name: string | null;
1436
+ image?: string | null;
1437
+ } | null;
1438
+ }
1439
+ interface KeyResultProjectLink {
1440
+ keyResultId: string;
1441
+ projectId: string;
1442
+ project?: {
1443
+ id: string;
1444
+ name: string;
1445
+ status?: string | null;
1446
+ };
1447
+ }
1448
+ interface KeyResultFeatureLink {
1449
+ keyResultId: string;
1450
+ featureId: string;
1451
+ feature?: {
1452
+ id: string;
1453
+ name: string;
1454
+ status?: string | null;
1455
+ /** Done/total ticket counts, or null for a feature with no tickets. */
1456
+ ticketProgress?: {
1457
+ done: number;
1458
+ total: number;
1459
+ } | null;
1460
+ };
1461
+ }
1462
+ interface KeyResult {
1463
+ /** cuid — unlike the objective's integer `goalId`. */
1464
+ id: string;
1465
+ goalId: number;
1466
+ title: string;
1467
+ description: string | null;
1468
+ status: string;
1469
+ /** Manual status override. When set it wins over `status`. */
1470
+ statusOverride?: string | null;
1471
+ startValue: number;
1472
+ currentValue: number;
1473
+ targetValue: number;
1474
+ unit: string;
1475
+ unitLabel?: string | null;
1476
+ confidence?: number | null;
1477
+ period: string;
1478
+ periodStart?: Date | null;
1479
+ periodEnd?: Date | null;
1480
+ userId: string;
1481
+ driUserId: string | null;
1482
+ workspaceId: string | null;
1483
+ createdAt: Date;
1484
+ updatedAt: Date;
1485
+ goal?: {
1486
+ id: number;
1487
+ title: string;
1488
+ period?: string | null;
1489
+ } | null;
1490
+ checkIns?: KeyResultCheckIn[];
1491
+ projects?: KeyResultProjectLink[];
1492
+ features?: KeyResultFeatureLink[];
1493
+ driUser?: {
1494
+ id: string;
1495
+ name: string | null;
1496
+ email?: string | null;
1497
+ image?: string | null;
1498
+ } | null;
1499
+ }
1500
+ /**
1501
+ * One objective with its key results, as returned by
1502
+ * `goals.keyResults.byObjective()` — the richest OKR read, and workspace-scoped
1503
+ * rather than user-scoped. This is the shape `exponential okrs list` renders.
1504
+ */
1505
+ interface ObjectiveWithKeyResults {
1506
+ id: number;
1507
+ title: string;
1508
+ description: string | null;
1509
+ status: string;
1510
+ period: string | null;
1511
+ health: string | null;
1512
+ workspaceId: string | null;
1513
+ driUserId: string | null;
1514
+ parentGoalId: number | null;
1515
+ /**
1516
+ * Not returned by the procedure — attached by callers that already know which
1517
+ * workspace they queried, so a cross-workspace list can label each row.
1518
+ */
1519
+ workspace?: {
1520
+ id: string;
1521
+ name: string;
1522
+ slug: string;
1523
+ } | null;
1524
+ keyResults: KeyResult[];
1525
+ /** Manual progress override if set, else the mean of the key results, else 0. */
1526
+ progress: number;
1527
+ statusCounts: {
1528
+ 'on-track': number;
1529
+ 'at-risk': number;
1530
+ 'off-track': number;
1531
+ achieved: number;
1532
+ };
1533
+ lifeDomain?: {
1534
+ id: number;
1535
+ title: string;
1536
+ color?: string | null;
1537
+ } | null;
1538
+ driUser?: {
1539
+ id: string;
1540
+ name: string | null;
1541
+ email?: string | null;
1542
+ image?: string | null;
1543
+ } | null;
1544
+ }
1545
+
1546
+ interface KeyResultListOptions {
1547
+ /**
1548
+ * Scope to a workspace. With it the list is workspace-**wide** — every
1549
+ * member's key results, not just yours. Without it you get your own.
1550
+ */
1551
+ workspaceId?: string;
1552
+ /** Objective id — an integer, unlike the key result's own cuid. */
1553
+ goalId?: number;
1554
+ period?: string;
1555
+ status?: KeyResultStatus;
1556
+ /** Narrow a workspace-scoped list back to the key results you own. */
1557
+ onlyMine?: boolean;
1558
+ }
1559
+ interface KeyResultByObjectiveOptions {
1560
+ workspaceId?: string;
1561
+ period?: string;
1562
+ /** Also include the period's parent annual period (Q3-2026 → Annual-2026). */
1563
+ includePairedPeriod?: boolean;
1564
+ onlyMine?: boolean;
1565
+ }
1566
+ interface KeyResultCreateInput {
1567
+ /** Objective (integer id) the key result hangs off. */
1568
+ goalId: number;
1569
+ title: string;
1570
+ targetValue: number;
1571
+ /** Free-form, e.g. `"Q3-2026"`. */
1572
+ period: string;
1573
+ description?: string;
1574
+ startValue?: number;
1575
+ currentValue?: number;
1576
+ unit?: KeyResultUnit;
1577
+ unitLabel?: string;
1578
+ driUserId?: string;
1579
+ /**
1580
+ * Omit to inherit the objective's workspace — {@link KeyResultsApi.create}
1581
+ * resolves it before writing. Pass one explicitly only to override.
1582
+ */
1583
+ workspaceId?: string;
1584
+ }
1585
+ interface KeyResultUpdateInput {
1586
+ /** cuid. */
1587
+ id: string;
1588
+ title?: string;
1589
+ description?: string;
1590
+ targetValue?: number;
1591
+ currentValue?: number;
1592
+ startValue?: number;
1593
+ unit?: KeyResultUnit;
1594
+ unitLabel?: string;
1595
+ status?: KeyResultStatus;
1596
+ /** 0–100. */
1597
+ confidence?: number;
1598
+ driUserId?: string;
1599
+ /** Move the key result to a different objective. */
1600
+ goalId?: number;
1601
+ }
1602
+ interface KeyResultCheckInInput {
1603
+ /** cuid. */
1604
+ id: string;
1605
+ /** The new current value. */
1606
+ value: number;
1607
+ note?: string;
1608
+ }
1609
+ /**
1610
+ * Key results — the measurable half of an OKR.
1611
+ *
1612
+ * Reachable both as `client.keyResults` and as `client.goals.keyResults`; they
1613
+ * are the same instance. Every id here is a **cuid string**, while the `goalId`
1614
+ * that ties a key result to its objective is an **integer**. The tRPC router
1615
+ * behind these calls is mounted at `okr`, which is the key-result router — not
1616
+ * an objective router. Objectives live on {@link GoalsApi}.
1617
+ */
1618
+ declare class KeyResultsApi {
1619
+ private client;
1620
+ constructor(client: TrpcClient);
1621
+ /**
1622
+ * List key results. Pass `workspaceId` for the workspace-wide list (every
1623
+ * member's), omit it for your own.
1624
+ *
1625
+ * ⚠️ Workspace scoping here depends on a server-side fix to `okr.getAll`,
1626
+ * which previously accepted a `workspaceId` while still filtering on the
1627
+ * caller's `userId` — so against an older instance this returns only your own
1628
+ * key results, or `[]`, rather than the workspace's. Unlike the filters in
1629
+ * `goals.list()` that cannot be repaired here: the other members' rows never
1630
+ * reach the client. {@link KeyResultsApi.byObjective} is workspace-correct on
1631
+ * every server version and is the safer read when that matters.
1632
+ */
1633
+ list(options?: KeyResultListOptions): Promise<KeyResult[]>;
1634
+ /**
1635
+ * Objectives with their key results nested — the richest OKR read, and the
1636
+ * one to reach for when rendering "here is the quarter".
1637
+ */
1638
+ byObjective(options?: KeyResultByObjectiveOptions): Promise<ObjectiveWithKeyResults[]>;
1639
+ get(id: string): Promise<KeyResult>;
1640
+ /**
1641
+ * Create a key result on an objective.
1642
+ *
1643
+ * When `workspaceId` is omitted it is resolved from the objective first,
1644
+ * rather than left to the server. `okr.create` writes the input through as-is
1645
+ * on older instances, so an absent workspace persists as `null` — and a key
1646
+ * result with no workspace is invisible to every workspace-scoped read and
1647
+ * unwritable by teammates once owner-OR-member authz applies. That is the
1648
+ * same orphaning that has already cost a goal; one extra read on a mutation
1649
+ * is a cheap way not to repeat it.
1650
+ */
1651
+ create(input: KeyResultCreateInput): Promise<KeyResult>;
1652
+ update(input: KeyResultUpdateInput): Promise<KeyResult>;
1653
+ /**
1654
+ * Record a progress check-in. The server derives the new status from where
1655
+ * `value` lands between `startValue` and `targetValue`, so a check-in both
1656
+ * moves the number and re-colours the key result.
1657
+ */
1658
+ checkIn(input: KeyResultCheckInInput): Promise<KeyResultCheckIn>;
1659
+ delete(id: string): Promise<{
1660
+ success: boolean;
1661
+ }>;
1662
+ /** Link a project to a key result as executing work. Idempotent. */
1663
+ linkProject(input: {
1664
+ keyResultId: string;
1665
+ projectId: string;
1666
+ }): Promise<{
1667
+ success: boolean;
1668
+ }>;
1669
+ unlinkProject(input: {
1670
+ keyResultId: string;
1671
+ projectId: string;
1672
+ }): Promise<{
1673
+ success: boolean;
1674
+ }>;
1675
+ /**
1676
+ * Link a feature to a key result as executing work. Idempotent. The feature's
1677
+ * product must live in the key result's workspace. A feature with no
1678
+ * objective alignment inherits the key result's objective; one that already
1679
+ * has an objective is never overwritten.
1680
+ */
1681
+ linkFeature(input: {
1682
+ keyResultId: string;
1683
+ featureId: string;
1684
+ }): Promise<{
1685
+ success: boolean;
1686
+ }>;
1687
+ /** Removes only the link row — never the feature's objective alignment. */
1688
+ unlinkFeature(input: {
1689
+ keyResultId: string;
1690
+ featureId: string;
1691
+ }): Promise<{
1692
+ success: boolean;
1693
+ }>;
1694
+ }
1695
+
1696
+ /**
1697
+ * Status on the goal write paths. `on-hold` is accepted only by
1698
+ * `goals.setStatus()` (`goal.updateGoalStatus`), never by `goals.update()`.
1699
+ */
1700
+ type GoalStatus = 'planned' | 'active' | 'completed' | 'archived' | 'on-hold';
1701
+ /** The subset `goals.update()` accepts. */
1702
+ type GoalWritableStatus = Exclude<GoalStatus, 'on-hold'>;
1703
+ /**
1704
+ * Rolled-up health, computed from key results, linked projects and child
1705
+ * goals. `healthOverride` wins over `health` when set.
1706
+ */
1707
+ type GoalHealth = 'on-track' | 'at-risk' | 'off-track' | 'no-update';
1708
+ interface GoalLifeDomain {
1709
+ id: number;
1710
+ title: string;
1711
+ description?: string | null;
1712
+ color?: string | null;
1713
+ icon?: string | null;
1714
+ }
1715
+ interface GoalProjectSummary {
1716
+ id: string;
1717
+ name: string;
1718
+ /** Present on list reads; the detail read selects a narrower project shape. */
1719
+ slug?: string;
1720
+ status?: string | null;
1721
+ progress?: number | null;
1722
+ priority?: string | null;
1723
+ endDate?: Date | null;
1724
+ }
1725
+ /**
1726
+ * The lean key-result shape list reads carry — enough to resolve progress
1727
+ * without the full KeyResult payload. `startValue` is absent on `tree()`,
1728
+ * whose select predates it.
1729
+ */
1730
+ interface GoalKeyResultSummary {
1731
+ id: string;
1732
+ status: string;
1733
+ startValue?: number;
1734
+ currentValue: number;
1735
+ targetValue: number;
1736
+ }
1737
+ interface GoalChildSummary {
1738
+ id: number;
1739
+ title: string;
1740
+ status: string;
1741
+ health: string | null;
1742
+ }
1743
+ interface GoalUserSummary {
1744
+ id: string;
1745
+ name: string | null;
1746
+ image?: string | null;
1747
+ }
1748
+ interface Goal {
1749
+ id: number;
1750
+ title: string;
1751
+ description: string | null;
1752
+ whyThisGoal?: string | null;
1753
+ notes?: string | null;
1754
+ dueDate: Date | null;
1755
+ /**
1756
+ * OKR period. A **free-form string** — `"Q3-2026"`, `"Annual-2026"`,
1757
+ * `"H1-2027"` — not an enum. `goals.periods()` lists the conventional values.
1758
+ */
1759
+ period: string | null;
1760
+ status: string;
1761
+ health: string | null;
1762
+ healthOverride?: string | null;
1763
+ progressOverride?: number | null;
1764
+ lifeDomainId: number | null;
1765
+ userId: string;
1766
+ driUserId: string | null;
1767
+ workspaceId: string | null;
1768
+ parentGoalId: number | null;
1769
+ icon?: string | null;
1770
+ iconColor?: string | null;
1771
+ displayOrder?: number;
1772
+ createdAt: Date;
1773
+ updatedAt: Date;
1774
+ lifeDomain?: GoalLifeDomain | null;
1775
+ projects?: GoalProjectSummary[];
1776
+ outcomes?: {
1777
+ id: string;
1778
+ description: string;
1779
+ }[];
1780
+ childGoals?: GoalChildSummary[];
1781
+ parentGoal?: {
1782
+ id: number;
1783
+ title: string;
1784
+ } | null;
1785
+ user?: GoalUserSummary;
1786
+ driUser?: GoalUserSummary | null;
1787
+ workspace?: {
1788
+ id: string;
1789
+ name: string;
1790
+ slug: string;
1791
+ } | null;
1792
+ /**
1793
+ * Effective progress 0–100: a manual `progressOverride` if set, else the mean
1794
+ * across measurable key results, else `null` for "no signal". Resolved
1795
+ * server-side so every consumer reads one number.
1796
+ */
1797
+ resolvedProgress?: number | null;
1798
+ /** Whether `resolvedProgress` came from the manual override. */
1799
+ isProgressManual?: boolean;
1800
+ keyResults?: GoalKeyResultSummary[];
1801
+ _count?: {
1802
+ keyResults?: number;
1803
+ comments?: number;
1804
+ };
1805
+ }
1806
+ /**
1807
+ * A goal with its children nested, as returned by `goals.tree()`. Only roots
1808
+ * (goals with no parent) come back at the top level; the server nests up to
1809
+ * the 5-level cap.
1810
+ */
1811
+ interface GoalTreeNode extends Goal {
1812
+ childGoals?: GoalTreeNode[] & GoalChildSummary[];
1813
+ keyResults?: GoalKeyResultSummary[];
1814
+ }
1815
+ /** One entry from `goals.periods()`. */
1816
+ interface GoalPeriod {
1817
+ value: string;
1818
+ label: string;
1819
+ }
1820
+ /** Aggregate OKR numbers from `goals.stats()`. */
1821
+ interface GoalStats {
1822
+ totalObjectives: number;
1823
+ totalKeyResults: number;
1824
+ completedKeyResults: number;
1825
+ statusBreakdown: {
1826
+ onTrack: number;
1827
+ atRisk: number;
1828
+ offTrack: number;
1829
+ achieved: number;
1830
+ };
1831
+ averageProgress: number;
1832
+ averageConfidence: number | null;
1833
+ periodEndDate: Date | null;
1834
+ }
1835
+
1836
+ interface GoalListOptions {
1837
+ /**
1838
+ * Scope to a workspace. With it the list is workspace-**wide** — every
1839
+ * member's objectives, not just yours. Without it you get your own.
1840
+ */
1841
+ workspaceId?: string;
1842
+ /** Free-form period string, e.g. `"Q3-2026"` or `"Annual-2026"`. */
1843
+ period?: string;
1844
+ status?: GoalStatus;
1845
+ }
1846
+ interface GoalTreeOptions {
1847
+ workspaceId?: string;
1848
+ status?: GoalStatus;
1849
+ }
1850
+ interface GoalCreateInput {
1851
+ title: string;
1852
+ description?: string;
1853
+ whyThisGoal?: string;
1854
+ notes?: string;
1855
+ dueDate?: Date;
1856
+ period?: string;
1857
+ status?: GoalWritableStatus;
1858
+ lifeDomainId?: number;
1859
+ /** Link the objective to one project on creation. */
1860
+ projectId?: string;
1861
+ outcomeIds?: string[];
1862
+ driUserId?: string;
1863
+ workspaceId?: string;
1864
+ /** Nest under a parent objective. Max nesting depth is 5. */
1865
+ parentGoalId?: number;
1866
+ icon?: string | null;
1867
+ iconColor?: string | null;
1868
+ }
1869
+ /**
1870
+ * A **partial** update: omit a field and it is left untouched, pass an explicit
1871
+ * `null` to clear it. Nothing you don't name is written.
1872
+ *
1873
+ * Prefer {@link GoalsApi.setStatus} for a status change and
1874
+ * {@link GoalsApi.setParent} for a re-parent — both write exactly one column.
1875
+ */
1876
+ interface GoalUpdateInput {
1877
+ id: number;
1878
+ title?: string;
1879
+ description?: string | null;
1880
+ whyThisGoal?: string | null;
1881
+ notes?: string | null;
1882
+ dueDate?: Date | null;
1883
+ period?: string | null;
1884
+ status?: GoalWritableStatus;
1885
+ lifeDomainId?: number | null;
1886
+ /** Replace the project links with this one project; `null` clears them. */
1887
+ projectId?: string | null;
1888
+ /** Replace the project links wholesale; `[]` clears them. */
1889
+ projectIds?: string[];
1890
+ outcomeIds?: string[];
1891
+ driUserId?: string | null;
1892
+ workspaceId?: string | null;
1893
+ parentGoalId?: number | null;
1894
+ displayOrder?: number;
1895
+ icon?: string | null;
1896
+ iconColor?: string | null;
1897
+ }
1898
+ interface GoalSetStatusInput {
1899
+ id: number;
1900
+ /** `on-hold` is accepted here and only here. */
1901
+ status: GoalStatus;
1902
+ }
1903
+ interface GoalSetParentInput {
1904
+ id: number;
1905
+ /** `null` detaches the objective from its parent. */
1906
+ parentGoalId: number | null;
1907
+ }
1908
+ interface GoalStatsOptions {
1909
+ workspaceId?: string;
1910
+ period?: string;
1911
+ }
1912
+ /**
1913
+ * Objectives (`Goal`) — the qualitative half of an OKR, keyed by **integer** id.
1914
+ * Their measurable key results hang off {@link KeyResultsApi}, reachable here as
1915
+ * `goals.keyResults`.
1916
+ *
1917
+ * On writes: `update()` is a partial update, but `setStatus()` and `setParent()`
1918
+ * each write a single column and are the right call whenever that is all you
1919
+ * mean to change — closing a quarter or re-parenting a cascade should never risk
1920
+ * a collateral write.
1921
+ */
1922
+ declare class GoalsApi {
1923
+ private client;
1924
+ /** Key results for these objectives. Same instance as `client.keyResults`. */
1925
+ keyResults: KeyResultsApi;
1926
+ constructor(client: TrpcClient,
1927
+ /** Key results for these objectives. Same instance as `client.keyResults`. */
1928
+ keyResults: KeyResultsApi);
1929
+ /**
1930
+ * List objectives. Pass `workspaceId` for the workspace-wide list (every
1931
+ * member's), omit it for your own. Includes each objective's linked
1932
+ * `projects`, which is the join that maps day-to-day work back to an OKR:
1933
+ * every action carries a `projectId`.
1934
+ *
1935
+ * `period` and `status` are sent to the server *and* re-applied here. The
1936
+ * server grew those filters recently; against an instance that predates them
1937
+ * zod strips the unknown keys and hands back **every** objective — a filter
1938
+ * that silently matches everything is worse than one that errors. Re-applying
1939
+ * is a no-op once the server has done the work. Same reasoning as the
1940
+ * client-side `branchName`/`prUrl` filters in `tickets.ts`.
1941
+ */
1942
+ list(options?: GoalListOptions): Promise<Goal[]>;
1943
+ /**
1944
+ * The same objectives nested parent → child (up to 5 levels), each with its
1945
+ * projects and key results. One call for the whole annual → quarterly cascade.
1946
+ */
1947
+ tree(options?: GoalTreeOptions): Promise<GoalTreeNode[]>;
1948
+ get(id: number): Promise<Goal>;
1949
+ /** Objectives linked to a given project. */
1950
+ listByProject(projectId: string): Promise<Goal[]>;
1951
+ create(input: GoalCreateInput): Promise<Goal>;
1952
+ /**
1953
+ * Partial update — see {@link GoalUpdateInput}. Fields you omit are left
1954
+ * alone; pass an explicit `null` to clear one.
1955
+ */
1956
+ update(input: GoalUpdateInput): Promise<Goal>;
1957
+ /**
1958
+ * Status-only write. Never touches another field, and is the only path that
1959
+ * accepts `on-hold`. Moving an objective to `completed` also records a
1960
+ * workspace milestone.
1961
+ */
1962
+ setStatus(input: GoalSetStatusInput): Promise<Goal>;
1963
+ /**
1964
+ * Re-parent an objective, or detach it with `parentGoalId: null`. Writes only
1965
+ * `parentGoalId`, and validates the no-self / no-cycle / depth-5 rules.
1966
+ */
1967
+ setParent(input: GoalSetParentInput): Promise<Goal>;
1968
+ delete(id: number): Promise<Goal>;
1969
+ /** The conventional period strings (quarters, halves, annual) for this year and next. */
1970
+ periods(): Promise<GoalPeriod[]>;
1971
+ /** Aggregate objective/key-result counts and average progress. */
1972
+ stats(options?: GoalStatsOptions): Promise<GoalStats>;
1973
+ }
1974
+
1218
1975
  interface Project {
1219
1976
  id: string;
1220
1977
  name: string;
@@ -1722,21 +2479,32 @@ interface TicketDetail extends Ticket {
1722
2479
 
1723
2480
  interface TicketListOptions {
1724
2481
  /**
1725
- * Required for product-scoped queries. Optional when `prUrl` or `branchName`
1726
- * is supplied — those filters are workspace-global (a PR URL or branch name
1727
- * uniquely identifies a Ticket across all products in the workspace), so the
1728
- * server resolves scope from the caller's auth context instead.
2482
+ * Always required. `product.ticket.list` is product-scoped on the server —
2483
+ * there is no workspace-wide ticket query. To search several products, call
2484
+ * `list` once per product and merge the results.
1729
2485
  */
1730
- productId?: string;
2486
+ productId: string;
1731
2487
  status?: TicketStatus;
1732
2488
  type?: TicketType;
1733
2489
  featureId?: string;
1734
2490
  epicId?: string;
1735
2491
  cycleId?: string;
1736
2492
  assigneeId?: string;
1737
- /** Workspace-scoped lookup by `Ticket.prUrl` (exact match). */
2493
+ /**
2494
+ * Filter by `Ticket.prUrl` (exact match).
2495
+ *
2496
+ * Applied **client-side**, after the product-scoped fetch — the server's
2497
+ * `list` input schema has no `prUrl` field. See the note on {@link
2498
+ * TicketsApi.list}.
2499
+ */
1738
2500
  prUrl?: string;
1739
- /** Workspace-scoped lookup by `Ticket.branchName` (exact match). */
2501
+ /**
2502
+ * Filter by `Ticket.branchName` (exact match).
2503
+ *
2504
+ * Applied **client-side**, after the product-scoped fetch — the server's
2505
+ * `list` input schema has no `branchName` field. See the note on {@link
2506
+ * TicketsApi.list}.
2507
+ */
1740
2508
  branchName?: string;
1741
2509
  }
1742
2510
  interface TicketCreateInput {
@@ -1796,6 +2564,16 @@ interface TicketSearchOptions {
1796
2564
  declare class TicketsApi {
1797
2565
  private client;
1798
2566
  constructor(client: TrpcClient);
2567
+ /**
2568
+ * List tickets in one product.
2569
+ *
2570
+ * `prUrl` and `branchName` are filtered here rather than on the server. The
2571
+ * `product.ticket.list` tRPC input schema accepts neither, and zod strips
2572
+ * unknown keys, so forwarding them was silently a no-op: a lookup by a branch
2573
+ * that matched nothing came back as *every ticket in the product*. Filtering
2574
+ * locally makes them mean what they say. Move them server-side once
2575
+ * `product.ticket.list` grows the matching input fields.
2576
+ */
1799
2577
  list(options: TicketListOptions): Promise<Ticket[]>;
1800
2578
  get(id: string): Promise<TicketDetail>;
1801
2579
  create(input: TicketCreateInput): Promise<Ticket>;
@@ -2390,6 +3168,9 @@ declare class ExponentialClient {
2390
3168
  featureComments: FeatureCommentsApi;
2391
3169
  pageComments: PageCommentsApi;
2392
3170
  goalComments: GoalCommentsApi;
3171
+ goals: GoalsApi;
3172
+ /** Same instance as `goals.keyResults`. */
3173
+ keyResults: KeyResultsApi;
2393
3174
  projects: ProjectsApi;
2394
3175
  workspaces: WorkspacesApi;
2395
3176
  contacts: ContactsApi;
@@ -2412,4 +3193,4 @@ declare class ExponentialClient {
2412
3193
  });
2413
3194
  }
2414
3195
 
2415
- export { type Action, type ActionComment, type ActionCommentAddInput, type ActionCommentUpdateInput, type ActionCreateInput, type ActionOutput, type ActionStatus, type ActionUpdateInput, type ActionsListOutput, type AddInteractionInput, type Area, type AreaCreateInput, type AreaListOptions, type CommentAuthor, type Contact, type ContactCreateInput, type ContactInteraction, type ContactListOutput, type ContactUpdateInput, type ContactsListOptions, type Deal, type DealActivity, type DealCreateInput, type DealMoveInput, type DealUpdateInput, type EnrichContactResult, type Epic, type EpicCreateInput, type EpicListOptions, type EpicPriority, type EpicStatus, type EpicUpdateInput, ExponentialClient, type ExponentialConfig, type Feature, type FeatureComment, type FeatureCommentCreateInput, type FeatureCommentReplyInput, type FeatureCommentThreadInput, type FeatureCommentUpdateInput, type FeatureCreateInput, type FeatureLinkPageInput, type FeatureListOptions, type FeatureScope, type FeatureScopeStatus, type FeatureStatus, type FeatureUpdateInput, type GlobalSearchOptions, type GlobalSearchOutput, type GoalComment, type GoalCommentAddInput, type GoalCommentUpdateInput, type InteractionDirection, type InteractionType, type KanbanStatus, type KnowledgePage, type LabelCreateInput, type LabelListOptions, type ListForEntityInput, type Organization, type OrganizationCreateInput, type OrganizationListOutput, type OrganizationSize, type OrganizationsListOptions, type OverdueCohort, type OverdueTriage, type OverdueTriageRow, type PageComment, type PageCommentCreateInput, type PageCommentUpdateInput, type PageCreateInput, type PageListOptions, type PageUpdateInput, type Pipeline, type PipelineStage, type Priority, type Product, type ProductCreateInput, type ProductUpdateInput, type Project, type ProjectOutput, type ProjectsListOutput, type Requirement, type RequirementCreateInput, type RequirementKind, type RequirementListOptions, type ScopeCreateInput, type ScopeListOptions, type ScopeUpdateInput, type SearchResult, type SearchResultType, type SearchResultWorkspace, type SetEntityTagsInput, type SetEntityTagsResult, type Tag, type TagEntityType, type TagListResult, type Ticket, type TicketAssignee, type TicketComment, type TicketCommentAddInput, type TicketCommentUpdateInput, type TicketCreateInput, type TicketDependencyEdge, type TicketDetail, type TicketListOptions, type TicketSearchOptions, type TicketStatus, type TicketType, type TicketUpdateInput, type TodaysActionRow, type TodaysActions, type TodaysActionsGroup, type UserStory, type UserStoryCreateInput, type UserStoryListOptions, type UserStoryUpdateInput, type Workspace, type WorkspaceMember, type WorkspaceOutput, type WorkspacesListOutput, clearConfig, createConfigStore, getConfigPath, isAuthenticated, isTRPCError, loadConfig, saveConfig };
3196
+ export { type Action, type ActionComment, type ActionCommentAddInput, type ActionCommentUpdateInput, type ActionCreateInput, type ActionOutput, type ActionStatus, type ActionUpdateInput, type ActionsListOutput, type AddInteractionInput, type Area, type AreaCreateInput, type AreaListOptions, type CommentAuthor, type Contact, type ContactCreateInput, type ContactInteraction, type ContactListOutput, type ContactUpdateInput, type ContactsListOptions, type Deal, type DealActivity, type DealCreateInput, type DealMoveInput, type DealUpdateInput, type EnrichContactResult, type Epic, type EpicCreateInput, type EpicListOptions, type EpicPriority, type EpicStatus, type EpicUpdateInput, ExponentialClient, type ExponentialConfig, type Feature, type FeatureComment, type FeatureCommentCreateInput, type FeatureCommentReplyInput, type FeatureCommentThreadInput, type FeatureCommentUpdateInput, type FeatureCreateInput, type FeatureLinkPageInput, type FeatureListOptions, type FeatureScope, type FeatureScopeStatus, type FeatureStatus, type FeatureUpdateInput, type GlobalSearchOptions, type GlobalSearchOutput, type Goal, type GoalChildSummary, type GoalComment, type GoalCommentAddInput, type GoalCommentUpdateInput, type GoalCreateInput, type GoalHealth, type GoalKeyResultSummary, type GoalLifeDomain, type GoalListOptions, type GoalPeriod, type GoalProjectSummary, type GoalSetParentInput, type GoalSetStatusInput, type GoalStats, type GoalStatsOptions, type GoalStatus, type GoalTreeNode, type GoalTreeOptions, type GoalUpdateInput, type GoalUserSummary, type GoalWritableStatus, type InteractionDirection, type InteractionType, type KanbanStatus, type KeyResult, type KeyResultByObjectiveOptions, type KeyResultCheckIn, type KeyResultCheckInInput, type KeyResultCreateInput, type KeyResultFeatureLink, type KeyResultListOptions, type KeyResultProjectLink, type KeyResultStatus, type KeyResultUnit, type KeyResultUpdateInput, type KnowledgePage, type LabelCreateInput, type LabelListOptions, type ListForEntityInput, type ObjectiveWithKeyResults, type Organization, type OrganizationCreateInput, type OrganizationListOutput, type OrganizationSize, type OrganizationsListOptions, type OverdueCohort, type OverdueTriage, type OverdueTriageRow, type PageComment, type PageCommentCreateInput, type PageCommentUpdateInput, type PageCreateInput, type PageListOptions, type PageUpdateInput, type Pipeline, type PipelineStage, type Priority, type Product, type ProductCreateInput, type ProductUpdateInput, type Project, type ProjectOutput, type ProjectsListOutput, type Requirement, type RequirementCreateInput, type RequirementKind, type RequirementListOptions, type ScopeCreateInput, type ScopeListOptions, type ScopeUpdateInput, type SearchResult, type SearchResultType, type SearchResultWorkspace, type SetEntityTagsInput, type SetEntityTagsResult, type Tag, type TagEntityType, type TagListResult, type Ticket, type TicketAssignee, type TicketComment, type TicketCommentAddInput, type TicketCommentUpdateInput, type TicketCreateInput, type TicketDependencyEdge, type TicketDetail, type TicketListOptions, type TicketSearchOptions, type TicketStatus, type TicketType, type TicketUpdateInput, type TodaysActionRow, type TodaysActions, type TodaysActionsGroup, type UserStory, type UserStoryCreateInput, type UserStoryListOptions, type UserStoryUpdateInput, type Workspace, type WorkspaceMember, type WorkspaceOutput, type WorkspacesListOutput, clearConfig, createConfigStore, getConfigPath, isAuthenticated, isTRPCError, loadConfig, saveConfig };