exponential-sdk 1.16.0 → 1.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -178,6 +178,67 @@ type MeetingUpdateDetailsProcedureInput = {
178
178
  workspaceId?: string | null;
179
179
  meetingDate?: Date | null;
180
180
  };
181
+ type DecisionStatusInput = 'OPEN' | 'PROPOSED' | 'ACCEPTED' | 'SUPERSEDED' | 'DEPRECATED';
182
+ type DecisionSourceInput = 'MEETING' | 'MANUAL' | 'AGENT';
183
+ type DecisionEvidenceInput = {
184
+ turnIndex: number;
185
+ speaker?: string | null;
186
+ startTime?: number | null;
187
+ text: string;
188
+ };
189
+ type DecisionDeciderProcedureInput = {
190
+ userId?: string | null;
191
+ name: string;
192
+ email?: string | null;
193
+ };
194
+ type DecisionCreateProcedureInput = {
195
+ workspaceId: string;
196
+ statement: string;
197
+ body?: string | null;
198
+ status?: DecisionStatusInput;
199
+ source?: DecisionSourceInput;
200
+ decidedAt?: Date | null;
201
+ ownerId?: string | null;
202
+ transcriptionSessionId?: string | null;
203
+ occurrenceId?: string | null;
204
+ productId?: string | null;
205
+ projectId?: string | null;
206
+ goalId?: number | null;
207
+ keyResultId?: string | null;
208
+ deciders?: DecisionDeciderProcedureInput[];
209
+ evidence?: DecisionEvidenceInput[];
210
+ };
211
+ type DecisionUpdateProcedureInput = {
212
+ workspaceId: string;
213
+ decisionId: string;
214
+ statement?: string;
215
+ body?: string | null;
216
+ decidedAt?: Date | null;
217
+ ownerId?: string | null;
218
+ productId?: string | null;
219
+ projectId?: string | null;
220
+ goalId?: number | null;
221
+ keyResultId?: string | null;
222
+ adrDocumentId?: string | null;
223
+ };
224
+ type ActionUpsertBySourceInput$1 = {
225
+ sourceType: string;
226
+ sourceId: string;
227
+ name: string;
228
+ workspaceId: string;
229
+ description?: string;
230
+ projectId?: string | null;
231
+ ticketId?: string | null;
232
+ };
233
+ type TimeEntryCreateInput = {
234
+ actionId: string;
235
+ startedAt: Date;
236
+ endedAt: Date;
237
+ source?: 'manual' | 'claude-desktop' | 'agent-run';
238
+ status?: 'PROPOSED' | 'CONFIRMED';
239
+ sourceRef?: string;
240
+ note?: string;
241
+ };
181
242
  interface TrpcClient {
182
243
  transcription: {
183
244
  getAllTranscriptions: {
@@ -255,6 +316,10 @@ interface TrpcClient {
255
316
  update: {
256
317
  mutate: (input: ActionUpdateInput$1) => Promise<unknown>;
257
318
  };
319
+ /** Idempotent create keyed on (workspaceId, sourceType, sourceId). */
320
+ upsertBySource: {
321
+ mutate: (input: ActionUpsertBySourceInput$1) => Promise<unknown>;
322
+ };
258
323
  bulkReschedule: {
259
324
  mutate: (input: {
260
325
  actionIds: string[];
@@ -478,6 +543,118 @@ interface TrpcClient {
478
543
  }) => Promise<unknown>;
479
544
  };
480
545
  };
546
+ timeEntry: {
547
+ /** Explicit-bounds entry; never touches the running Timer (ADR-0061). */
548
+ create: {
549
+ mutate: (input: TimeEntryCreateInput) => Promise<unknown>;
550
+ };
551
+ upsertBySourceRef: {
552
+ mutate: (input: TimeEntryCreateInput & {
553
+ sourceRef: string;
554
+ }) => Promise<unknown>;
555
+ };
556
+ listByDateRange: {
557
+ query: (input: {
558
+ startDate: Date;
559
+ endDate: Date;
560
+ workspaceId?: string | null;
561
+ }) => Promise<unknown[]>;
562
+ };
563
+ };
564
+ decision: {
565
+ list: {
566
+ query: (input: {
567
+ workspaceId: string;
568
+ statuses?: DecisionStatusInput[];
569
+ sources?: DecisionSourceInput[];
570
+ /** A product id, or "workspace" for decisions with no product. */
571
+ productId?: string;
572
+ includeWorkspaceWide?: boolean;
573
+ projectId?: string;
574
+ search?: string;
575
+ /** One decision by its workspace sequence number — `D-0003` → 3. */
576
+ number?: number;
577
+ limit?: number;
578
+ }) => Promise<unknown[]>;
579
+ };
580
+ get: {
581
+ query: (input: {
582
+ workspaceId: string;
583
+ decisionId: string;
584
+ }) => Promise<unknown>;
585
+ };
586
+ /** Workspace comes from the meeting; drafts included for meeting editors. */
587
+ listForMeeting: {
588
+ query: (input: {
589
+ transcriptionSessionId: string;
590
+ }) => Promise<unknown>;
591
+ };
592
+ listForAdr: {
593
+ query: (input: {
594
+ workspaceId: string;
595
+ adrDocumentId: string;
596
+ }) => Promise<unknown[]>;
597
+ };
598
+ /** Extract draft decisions from a meeting's notes and transcript. */
599
+ extractDrafts: {
600
+ mutate: (input: {
601
+ transcriptionSessionId: string;
602
+ }) => Promise<unknown>;
603
+ };
604
+ create: {
605
+ mutate: (input: DecisionCreateProcedureInput) => Promise<unknown>;
606
+ };
607
+ update: {
608
+ mutate: (input: DecisionUpdateProcedureInput) => Promise<unknown>;
609
+ };
610
+ setStatus: {
611
+ mutate: (input: {
612
+ workspaceId: string;
613
+ decisionId: string;
614
+ status: DecisionStatusInput;
615
+ supersededById?: string | null;
616
+ }) => Promise<unknown>;
617
+ };
618
+ linkTicket: {
619
+ mutate: (input: {
620
+ workspaceId: string;
621
+ decisionId: string;
622
+ ticketId: string;
623
+ }) => Promise<unknown>;
624
+ };
625
+ linkFeature: {
626
+ mutate: (input: {
627
+ workspaceId: string;
628
+ decisionId: string;
629
+ featureId: string;
630
+ }) => Promise<unknown>;
631
+ };
632
+ /** `linkId` is the DecisionLink id, not the ticket or feature id. */
633
+ unlink: {
634
+ mutate: (input: {
635
+ workspaceId: string;
636
+ linkId: string;
637
+ }) => Promise<unknown>;
638
+ };
639
+ confirmDraft: {
640
+ mutate: (input: {
641
+ workspaceId: string;
642
+ decisionId: string;
643
+ }) => Promise<unknown>;
644
+ };
645
+ rejectDraft: {
646
+ mutate: (input: {
647
+ workspaceId: string;
648
+ decisionId: string;
649
+ }) => Promise<unknown>;
650
+ };
651
+ deleteDraft: {
652
+ mutate: (input: {
653
+ workspaceId: string;
654
+ decisionId: string;
655
+ }) => Promise<unknown>;
656
+ };
657
+ };
481
658
  crmApi: {
482
659
  contactList: {
483
660
  query: (input: {
@@ -1143,7 +1320,9 @@ interface Action {
1143
1320
  name: string;
1144
1321
  } | null;
1145
1322
  assignees?: Array<{
1146
- user: {
1323
+ /** Bare form returned by `action.upsertBySource`. */
1324
+ userId?: string;
1325
+ user?: {
1147
1326
  id: string;
1148
1327
  name: string | null;
1149
1328
  email: string | null;
@@ -1231,6 +1410,30 @@ interface ActionUpdateInput {
1231
1410
  effortEstimate?: number | null;
1232
1411
  blockedByIds?: string[];
1233
1412
  }
1413
+ interface ActionUpsertBySourceInput {
1414
+ /** Convention for the Daily worklog: `claude-session`. */
1415
+ sourceType: string;
1416
+ /** The conversation id — re-running with the same pair updates, never duplicates. */
1417
+ sourceId: string;
1418
+ name: string;
1419
+ workspaceId: string;
1420
+ description?: string;
1421
+ /** Must live in `workspaceId`, or the call is NOT_FOUND. */
1422
+ projectId?: string | null;
1423
+ /** Must belong to a product in `workspaceId`, or the call is NOT_FOUND. */
1424
+ ticketId?: string | null;
1425
+ }
1426
+ interface ActionUpsertBySourceResult {
1427
+ action: Action & {
1428
+ ticket?: {
1429
+ id: string;
1430
+ number: number;
1431
+ shortId: string | null;
1432
+ productId: string;
1433
+ } | null;
1434
+ };
1435
+ outcome: 'created' | 'updated';
1436
+ }
1234
1437
  /** One action as returned inside a {@link TodaysActions} group. */
1235
1438
  interface TodaysActionRow {
1236
1439
  id: string;
@@ -1333,6 +1536,13 @@ declare class ActionsApi {
1333
1536
  getProjectActions(projectId: string, assigneeId?: string): Promise<Action[]>;
1334
1537
  create(input: ActionCreateInput): Promise<Action>;
1335
1538
  update(input: ActionUpdateInput): Promise<Action>;
1539
+ /**
1540
+ * One Action per external source: find by (workspaceId, sourceType,
1541
+ * sourceId), refresh its name and links, else create it. `outcome` says
1542
+ * which happened. Agents may call this; the created Action records the
1543
+ * agent's shadow user as creator with `source: "agent"` (ADR-0049).
1544
+ */
1545
+ upsertBySource(input: ActionUpsertBySourceInput): Promise<ActionUpsertBySourceResult>;
1336
1546
  }
1337
1547
 
1338
1548
  interface CommentAuthor {
@@ -2433,6 +2643,381 @@ declare class ContactsApi {
2433
2643
  enrich(id: string): Promise<EnrichContactResult>;
2434
2644
  }
2435
2645
 
2646
+ /**
2647
+ * Lifecycle of a decision.
2648
+ *
2649
+ * - `OPEN` — an open question: raised, not yet decided. This is how the
2650
+ * "Open questions" panel is populated; there is no separate model.
2651
+ * - `PROPOSED` — put forward, not yet agreed (the server's default).
2652
+ * - `ACCEPTED` — decided.
2653
+ * - `SUPERSEDED` / `DEPRECATED` — end states reached through `setStatus`;
2654
+ * `create` rejects them as a birth state.
2655
+ */
2656
+ type DecisionStatus = 'OPEN' | 'PROPOSED' | 'ACCEPTED' | 'SUPERSEDED' | 'DEPRECATED';
2657
+ /** Who logged it: a meeting, a person by hand, or an agent. */
2658
+ type DecisionSource = 'MEETING' | 'MANUAL' | 'AGENT';
2659
+ /**
2660
+ * Draft decisions are invisible everywhere except the source meeting's draft
2661
+ * views, and only to people who can edit that meeting.
2662
+ */
2663
+ type DecisionReviewState = 'DRAFT' | 'CONFIRMED' | 'REJECTED';
2664
+ /** A quoted transcript turn backing a decision (max 50 per decision). */
2665
+ interface DecisionEvidenceTurn {
2666
+ turnIndex: number;
2667
+ speaker?: string | null;
2668
+ startTime?: number | null;
2669
+ text: string;
2670
+ }
2671
+ /**
2672
+ * Someone who made the decision. External participants have no `User` row, so
2673
+ * `userId` is null and the name/email pair carries them.
2674
+ */
2675
+ interface DecisionDecider {
2676
+ id: string;
2677
+ userId: string | null;
2678
+ name: string;
2679
+ email: string | null;
2680
+ }
2681
+ interface DecisionUserRef {
2682
+ id: string;
2683
+ name: string | null;
2684
+ email?: string | null;
2685
+ image?: string | null;
2686
+ }
2687
+ interface DecisionProductRef {
2688
+ id: string;
2689
+ name: string;
2690
+ slug: string;
2691
+ }
2692
+ interface DecisionProjectRef {
2693
+ id: string;
2694
+ name: string;
2695
+ slug: string;
2696
+ }
2697
+ interface DecisionMeetingRef {
2698
+ id: string;
2699
+ title: string | null;
2700
+ meetingDate?: Date | null;
2701
+ workspaceId?: string | null;
2702
+ }
2703
+ interface DecisionOccurrenceRef {
2704
+ id: string;
2705
+ scheduledStart: Date;
2706
+ ceremony: {
2707
+ id: string;
2708
+ name: string;
2709
+ slug: string;
2710
+ };
2711
+ }
2712
+ /** A neighbour in the supersession chain. */
2713
+ interface DecisionChainRef {
2714
+ id: string;
2715
+ number: number;
2716
+ statement: string;
2717
+ status: DecisionStatus;
2718
+ }
2719
+ interface DecisionTicketRef {
2720
+ id: string;
2721
+ shortId: string | null;
2722
+ number: number;
2723
+ title: string;
2724
+ status: string;
2725
+ productId: string;
2726
+ }
2727
+ interface DecisionFeatureRef {
2728
+ id: string;
2729
+ name: string;
2730
+ status: string;
2731
+ }
2732
+ /** An "implemented by" edge to a ticket or a feature. */
2733
+ interface DecisionLink {
2734
+ id: string;
2735
+ decisionId: string;
2736
+ ticketId: string | null;
2737
+ featureId: string | null;
2738
+ createdById: string;
2739
+ createdAt: Date;
2740
+ ticket?: DecisionTicketRef | null;
2741
+ feature?: DecisionFeatureRef | null;
2742
+ createdBy?: DecisionUserRef;
2743
+ }
2744
+ interface DecisionAdrRef {
2745
+ id: string;
2746
+ number: number;
2747
+ title: string;
2748
+ repositoryId: string | null;
2749
+ }
2750
+ /**
2751
+ * A list row — enough for the Decision Log and the meeting panels, without
2752
+ * the body, evidence text, deciders or links.
2753
+ */
2754
+ interface DecisionListRow {
2755
+ id: string;
2756
+ workspaceId: string;
2757
+ /** Sequence number within the workspace; `label` is its rendered form. */
2758
+ number: number;
2759
+ /** `D-` plus the zero-padded number, e.g. `D-0042`. */
2760
+ label: string;
2761
+ statement: string;
2762
+ status: DecisionStatus;
2763
+ source: DecisionSource;
2764
+ decidedAt: Date | null;
2765
+ updatedAt: Date;
2766
+ transcriptionSessionId: string | null;
2767
+ occurrenceId: string | null;
2768
+ productId: string | null;
2769
+ projectId: string | null;
2770
+ supersededById: string | null;
2771
+ evidenceCount: number;
2772
+ product: DecisionProductRef | null;
2773
+ project: DecisionProjectRef | null;
2774
+ occurrence: DecisionOccurrenceRef | null;
2775
+ transcriptionSession: {
2776
+ id: string;
2777
+ title: string | null;
2778
+ } | null;
2779
+ /**
2780
+ * `listForMeeting` rows carry `statement` and `status` too; the workspace
2781
+ * log's rows carry only the id and label.
2782
+ */
2783
+ supersededBy: {
2784
+ id: string;
2785
+ label: string;
2786
+ statement?: string;
2787
+ status?: DecisionStatus;
2788
+ } | null;
2789
+ /** Present only on `listForMeeting` rows. */
2790
+ reviewState?: DecisionReviewState;
2791
+ _count?: {
2792
+ links: number;
2793
+ deciders: number;
2794
+ };
2795
+ }
2796
+ /** One decision in full, as `get`, `create`, `update` and `setStatus` return it. */
2797
+ interface Decision {
2798
+ id: string;
2799
+ workspaceId: string;
2800
+ number: number;
2801
+ label: string;
2802
+ statement: string;
2803
+ /** Markdown, with ADR headings (context / alternatives / consequences). */
2804
+ body: string | null;
2805
+ status: DecisionStatus;
2806
+ reviewState: DecisionReviewState;
2807
+ source: DecisionSource;
2808
+ decidedAt: Date | null;
2809
+ ownerId: string | null;
2810
+ createdById: string;
2811
+ confirmedById: string | null;
2812
+ confirmedAt: Date | null;
2813
+ transcriptionSessionId: string | null;
2814
+ occurrenceId: string | null;
2815
+ productId: string | null;
2816
+ projectId: string | null;
2817
+ goalId: number | null;
2818
+ keyResultId: string | null;
2819
+ supersededById: string | null;
2820
+ adrDocumentId: string | null;
2821
+ pendingAdrPrUrl: string | null;
2822
+ evidence: DecisionEvidenceTurn[];
2823
+ createdAt: Date;
2824
+ updatedAt: Date;
2825
+ owner?: DecisionUserRef | null;
2826
+ createdBy?: DecisionUserRef;
2827
+ confirmedBy?: DecisionUserRef | null;
2828
+ deciders?: DecisionDecider[];
2829
+ transcriptionSession?: DecisionMeetingRef | null;
2830
+ occurrence?: DecisionOccurrenceRef | null;
2831
+ product?: DecisionProductRef | null;
2832
+ project?: DecisionProjectRef | null;
2833
+ goal?: {
2834
+ id: number;
2835
+ title: string;
2836
+ } | null;
2837
+ keyResult?: {
2838
+ id: string;
2839
+ title: string;
2840
+ } | null;
2841
+ supersededBy?: DecisionChainRef | null;
2842
+ supersedes?: DecisionChainRef[];
2843
+ adrDocument?: DecisionAdrRef | null;
2844
+ links?: DecisionLink[];
2845
+ /** Present on `get`: whether the caller may write to this decision. */
2846
+ canEdit?: boolean;
2847
+ }
2848
+ /** What `listForMeeting` answers with — the rows plus the caller's rights. */
2849
+ interface MeetingDecisions {
2850
+ decisions: DecisionListRow[];
2851
+ /** False when the caller can't edit the meeting, or it has no workspace. */
2852
+ canLogDecision: boolean;
2853
+ workspaceId: string | null;
2854
+ }
2855
+ /** What `extractDrafts` reports back about one meeting. */
2856
+ interface DraftDecisionsResult {
2857
+ success: boolean;
2858
+ /** The meeting already has confirmed decisions; nothing was extracted. */
2859
+ alreadyPublished: boolean;
2860
+ /** The meeting already had drafts; they were returned, not regenerated. */
2861
+ alreadyDrafted: boolean;
2862
+ /** Drafts now awaiting review (existing or just created). */
2863
+ draftCount: number;
2864
+ draftsCreated: number;
2865
+ /** Candidates dropped because no transcript turn supported them. */
2866
+ discardedWithoutEvidence: number;
2867
+ errors: string[];
2868
+ }
2869
+
2870
+ /** A person who made the decision; `name` is the only required half. */
2871
+ interface DecisionDeciderInput {
2872
+ userId?: string | null;
2873
+ name: string;
2874
+ email?: string | null;
2875
+ }
2876
+ interface DecisionListOptions {
2877
+ workspaceId: string;
2878
+ statuses?: DecisionStatus[];
2879
+ sources?: DecisionSource[];
2880
+ /** A product id, or the literal `"workspace"` for decisions with no product. */
2881
+ productId?: string;
2882
+ /** With a real `productId`: ALSO include decisions that have no product. */
2883
+ includeWorkspaceWide?: boolean;
2884
+ projectId?: string;
2885
+ /** Free-text over statement and body (max 200 characters). */
2886
+ search?: string;
2887
+ /** One decision by its workspace sequence number — `D-0003` is number 3. */
2888
+ number?: number;
2889
+ /** Cap the rows returned (1-500). Unset returns everything visible. */
2890
+ limit?: number;
2891
+ }
2892
+ interface DecisionCreateInput {
2893
+ workspaceId: string;
2894
+ /** The decision itself, or the open question. Max 500 characters. */
2895
+ statement: string;
2896
+ /** Markdown detail — context, alternatives, consequences. Max 20,000. */
2897
+ body?: string | null;
2898
+ /**
2899
+ * Defaults to `PROPOSED` server-side. Pass `OPEN` to log an OPEN QUESTION —
2900
+ * that is the only representation of one. `SUPERSEDED` and `DEPRECATED` are
2901
+ * rejected here; they are `setStatus` transitions.
2902
+ */
2903
+ status?: DecisionStatus;
2904
+ source?: DecisionSource;
2905
+ decidedAt?: Date | null;
2906
+ ownerId?: string | null;
2907
+ /** Meeting provenance. Requires EDIT access to that meeting. */
2908
+ transcriptionSessionId?: string | null;
2909
+ occurrenceId?: string | null;
2910
+ productId?: string | null;
2911
+ projectId?: string | null;
2912
+ goalId?: number | null;
2913
+ keyResultId?: string | null;
2914
+ /** Max 50. */
2915
+ deciders?: DecisionDeciderInput[];
2916
+ /**
2917
+ * Quoted transcript turns backing the decision (max 50). The server checks
2918
+ * every turn against the meeting's actual transcript: the index must
2919
+ * resolve and the words must be that turn's, compared loosely for case,
2920
+ * punctuation and whitespace. Turns that don't match are DROPPED, silently
2921
+ * from the caller's side, and `speaker`/`startTime` are overwritten with
2922
+ * the transcript's own values. Evidence therefore requires
2923
+ * `transcriptionSessionId` — sending it without one is a BAD_REQUEST.
2924
+ */
2925
+ evidence?: DecisionEvidenceTurn[];
2926
+ }
2927
+ /** Content and scope only — status changes go through {@link DecisionsApi.setStatus}. */
2928
+ interface DecisionUpdateInput {
2929
+ workspaceId: string;
2930
+ decisionId: string;
2931
+ statement?: string;
2932
+ body?: string | null;
2933
+ decidedAt?: Date | null;
2934
+ ownerId?: string | null;
2935
+ productId?: string | null;
2936
+ projectId?: string | null;
2937
+ goalId?: number | null;
2938
+ keyResultId?: string | null;
2939
+ adrDocumentId?: string | null;
2940
+ }
2941
+ interface DecisionSetStatusInput {
2942
+ workspaceId: string;
2943
+ decisionId: string;
2944
+ status: DecisionStatus;
2945
+ /** Required by convention when moving to `SUPERSEDED`. */
2946
+ supersededById?: string | null;
2947
+ }
2948
+ /**
2949
+ * Decisions — the writable half of the Decision Log (ADR-0060).
2950
+ *
2951
+ * The one thing worth knowing before using this: **an open question is a
2952
+ * decision with status `OPEN`**. There is no separate model, and it is what
2953
+ * the "Open questions" panel on a meeting page reads.
2954
+ *
2955
+ * Reads need workspace `view`; writes need workspace `edit`, and a decision
2956
+ * carrying `transcriptionSessionId` additionally needs edit access to that
2957
+ * meeting.
2958
+ */
2959
+ declare class DecisionsApi {
2960
+ private client;
2961
+ constructor(client: TrpcClient);
2962
+ /**
2963
+ * Confirmed decisions in a workspace, newest decided first. Drafts are
2964
+ * never included — see {@link listForMeeting} for those.
2965
+ */
2966
+ list(options: DecisionListOptions): Promise<DecisionListRow[]>;
2967
+ get(workspaceId: string, decisionId: string): Promise<Decision>;
2968
+ /**
2969
+ * Decisions logged from one meeting — both panels' contents. Drafts are
2970
+ * included for callers who can edit the meeting. No workspace id needed:
2971
+ * the meeting resolves it.
2972
+ */
2973
+ listForMeeting(transcriptionSessionId: string): Promise<MeetingDecisions>;
2974
+ /** Decisions formalised as one ADR ("Decided in"). */
2975
+ listForAdr(workspaceId: string, adrDocumentId: string): Promise<DecisionListRow[]>;
2976
+ /**
2977
+ * Extract draft decisions from a meeting's notes and transcript. Drafts
2978
+ * only — someone confirms or rejects each one. Idempotent per meeting:
2979
+ * existing drafts come back untouched, and a meeting that already has
2980
+ * confirmed decisions reports `alreadyPublished` without calling the model.
2981
+ */
2982
+ extractDrafts(transcriptionSessionId: string): Promise<DraftDecisionsResult>;
2983
+ /**
2984
+ * Log a decision. Pass `status: 'OPEN'` for an open question, and
2985
+ * `transcriptionSessionId` to attach it to the meeting it came out of.
2986
+ */
2987
+ create(input: DecisionCreateInput): Promise<Decision>;
2988
+ update(input: DecisionUpdateInput): Promise<Decision>;
2989
+ /**
2990
+ * Lifecycle transition — including answering an open question by moving it
2991
+ * from `OPEN` to `ACCEPTED`.
2992
+ */
2993
+ setStatus(input: DecisionSetStatusInput): Promise<Decision>;
2994
+ /** "Implemented by" a ticket. Idempotent: an existing link is returned. */
2995
+ linkTicket(workspaceId: string, decisionId: string, ticketId: string): Promise<DecisionLink>;
2996
+ /** "Implemented by" a feature. Idempotent: an existing link is returned. */
2997
+ linkFeature(workspaceId: string, decisionId: string, featureId: string): Promise<DecisionLink>;
2998
+ /** Remove one link, by the `DecisionLink` id (not the ticket/feature id). */
2999
+ unlink(workspaceId: string, linkId: string): Promise<{
3000
+ deleted: boolean;
3001
+ }>;
3002
+ /** Publish a draft into the log. */
3003
+ confirmDraft(workspaceId: string, decisionId: string): Promise<Decision>;
3004
+ /**
3005
+ * Reject a draft. Confirmed decisions are never rejected — deprecate or
3006
+ * supersede them through {@link setStatus}.
3007
+ */
3008
+ rejectDraft(workspaceId: string, decisionId: string): Promise<{
3009
+ id: string;
3010
+ reviewState: DecisionReviewState;
3011
+ }>;
3012
+ /**
3013
+ * Hard-delete a draft or rejected row. The server refuses for a confirmed
3014
+ * decision — the log keeps its history.
3015
+ */
3016
+ deleteDraft(workspaceId: string, decisionId: string): Promise<{
3017
+ id: string;
3018
+ }>;
3019
+ }
3020
+
2436
3021
  type OrganizationSize = '1-10' | '11-50' | '51-200' | '201-500' | '501-1000' | '1000+';
2437
3022
  interface Organization {
2438
3023
  id: string;
@@ -3549,6 +4134,104 @@ declare class SearchApi {
3549
4134
  global(options: GlobalSearchOptions): Promise<GlobalSearchOutput>;
3550
4135
  }
3551
4136
 
4137
+ type TimeEntryStatus = 'PROPOSED' | 'CONFIRMED';
4138
+ /**
4139
+ * Where an entry came from. `plugin` is the legacy stamp of the in-app Timer
4140
+ * and calendar grids; new writes use the other three. `claude-desktop` is
4141
+ * Proposed time from the Daily worklog, `agent-run` is Agent-run time (an
4142
+ * agent working with no human turns, kept off the owner's attention totals).
4143
+ */
4144
+ type TimeEntrySource = 'plugin' | 'manual' | 'claude-desktop' | 'agent-run';
4145
+ interface TimeEntry {
4146
+ id: string;
4147
+ /** Whose time it is. Under an agent key this is the agent's OWNER (ADR-0061). */
4148
+ userId: string;
4149
+ actionId: string;
4150
+ workspaceId: string | null;
4151
+ startedAt: Date;
4152
+ endedAt: Date | null;
4153
+ source: string;
4154
+ status: TimeEntryStatus;
4155
+ /** Idempotency key, e.g. `claude-session:<sessionId>#<segmentIndex>`. */
4156
+ sourceRef: string | null;
4157
+ note: string | null;
4158
+ /** The external agent that wrote the row; null for human-made entries. */
4159
+ createdByAgentId: string | null;
4160
+ action: {
4161
+ id: string;
4162
+ name: string;
4163
+ projectId: string | null;
4164
+ workspaceId: string | null;
4165
+ };
4166
+ }
4167
+ interface TimeLogInput {
4168
+ actionId: string;
4169
+ startedAt: Date;
4170
+ endedAt: Date;
4171
+ /** Defaults to `manual` server-side. */
4172
+ source?: Exclude<TimeEntrySource, 'plugin'>;
4173
+ /**
4174
+ * Ignored under an agent key: agent-written entries are always PROPOSED.
4175
+ * A human's entry defaults to CONFIRMED.
4176
+ */
4177
+ status?: TimeEntryStatus;
4178
+ /**
4179
+ * With a `sourceRef` the write is idempotent per owner: a re-run updates a
4180
+ * PROPOSED entry in place and leaves a CONFIRMED one alone.
4181
+ */
4182
+ sourceRef?: string;
4183
+ /** One line shown in the day view and list row (max 1000 chars). */
4184
+ note?: string;
4185
+ }
4186
+ /**
4187
+ * `created` — a new row; `updated` — an existing PROPOSED row was replaced;
4188
+ * `left` — the row is CONFIRMED and was not touched.
4189
+ */
4190
+ type TimeLogOutcome = 'created' | 'updated' | 'left';
4191
+ interface TimeLogResult {
4192
+ entry: TimeEntry;
4193
+ outcome: TimeLogOutcome;
4194
+ }
4195
+ interface TimeLogBatchResult {
4196
+ index: number;
4197
+ success: boolean;
4198
+ sourceRef?: string;
4199
+ entry?: TimeEntry;
4200
+ outcome?: TimeLogOutcome;
4201
+ error?: string;
4202
+ }
4203
+ /**
4204
+ * Time entries — the Daily worklog's write path (ADR-0061).
4205
+ *
4206
+ * The thing to know: an entry always belongs to the person whose time it
4207
+ * was. Called with an external-agent key, {@link log} writes an entry OWNED
4208
+ * by the agent's owner, records the agent as author and forces it to
4209
+ * `PROPOSED`; it shows on the owner's `/time` with a "proposed" chip and
4210
+ * stays out of `Action.timeSpentMins` until the owner confirms the day.
4211
+ * Manual time is never altered by these calls.
4212
+ */
4213
+ declare class TimeApi {
4214
+ private client;
4215
+ constructor(client: TrpcClient);
4216
+ /**
4217
+ * Log one completed entry with explicit bounds. Never starts, stops or
4218
+ * alters the running Timer. With `sourceRef` the call is an upsert keyed
4219
+ * on (owner, sourceRef); without it every call creates a row.
4220
+ */
4221
+ log(input: TimeLogInput): Promise<TimeLogResult>;
4222
+ /**
4223
+ * Log many entries, one call each and in order, so a failure names the
4224
+ * entry it belonged to instead of rejecting the whole batch. `defaults`
4225
+ * fill any field an entry leaves out.
4226
+ */
4227
+ logBatch(entries: Partial<TimeLogInput>[], defaults?: Partial<TimeLogInput>): Promise<TimeLogBatchResult[]>;
4228
+ /**
4229
+ * The caller's entries that touch one calendar day (local time), oldest
4230
+ * first, each with its `status`. Pass `YYYY-MM-DD` or a Date.
4231
+ */
4232
+ list(date: Date | string, workspaceId?: string): Promise<TimeEntry[]>;
4233
+ }
4234
+
3552
4235
  interface ExponentialConfig {
3553
4236
  apiUrl: string;
3554
4237
  token: string;
@@ -3585,6 +4268,7 @@ declare class ExponentialClient {
3585
4268
  projects: ProjectsApi;
3586
4269
  workspaces: WorkspacesApi;
3587
4270
  contacts: ContactsApi;
4271
+ decisions: DecisionsApi;
3588
4272
  organizations: OrganizationsApi;
3589
4273
  pipelines: PipelinesApi;
3590
4274
  tickets: TicketsApi;
@@ -3599,10 +4283,12 @@ declare class ExponentialClient {
3599
4283
  requirements: RequirementsApi;
3600
4284
  scopes: ScopesApi;
3601
4285
  search: SearchApi;
4286
+ /** Time entries — the Daily worklog's write path (ADR-0061). */
4287
+ time: TimeApi;
3602
4288
  constructor(config: {
3603
4289
  token: string;
3604
4290
  apiUrl: string;
3605
4291
  });
3606
4292
  }
3607
4293
 
3608
- 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 FeatureKeyResultLink, 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 Meeting, type MeetingActionSummary, type MeetingCreateInput, type MeetingListOptions, type MeetingParticipant, type MeetingParticipantInput, type MeetingProjectRef, type MeetingSourceIntegration, type MeetingTypeFilter, type MeetingUpdateInput, type MeetingWorkspaceRef, 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 ProjectDetail, type ProjectKeyResultLink, type ProjectOutput, type ProjectPriority, type ProjectStatus, type ProjectUpdateInput, type ProjectsListOptions, 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 };
4294
+ export { type Action, type ActionComment, type ActionCommentAddInput, type ActionCommentUpdateInput, type ActionCreateInput, type ActionOutput, type ActionStatus, type ActionUpdateInput, type ActionUpsertBySourceInput, type ActionUpsertBySourceResult, 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 Decision, type DecisionAdrRef, type DecisionChainRef, type DecisionCreateInput, type DecisionDecider, type DecisionDeciderInput, type DecisionEvidenceTurn, type DecisionFeatureRef, type DecisionLink, type DecisionListOptions, type DecisionListRow, type DecisionMeetingRef, type DecisionOccurrenceRef, type DecisionProductRef, type DecisionProjectRef, type DecisionReviewState, type DecisionSetStatusInput, type DecisionSource, type DecisionStatus, type DecisionTicketRef, type DecisionUpdateInput, type DecisionUserRef, type DraftDecisionsResult, 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 FeatureKeyResultLink, 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 Meeting, type MeetingActionSummary, type MeetingCreateInput, type MeetingDecisions, type MeetingListOptions, type MeetingParticipant, type MeetingParticipantInput, type MeetingProjectRef, type MeetingSourceIntegration, type MeetingTypeFilter, type MeetingUpdateInput, type MeetingWorkspaceRef, 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 ProjectDetail, type ProjectKeyResultLink, type ProjectOutput, type ProjectPriority, type ProjectStatus, type ProjectUpdateInput, type ProjectsListOptions, 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, TimeApi, type TimeEntry, type TimeEntrySource, type TimeEntryStatus, type TimeLogBatchResult, type TimeLogInput, type TimeLogOutcome, type TimeLogResult, 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 };