@rightkit/social-ui 0.0.0-stage → 0.1.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.
Files changed (124) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/LICENSE-APACHE +201 -0
  3. package/LICENSE-MIT +21 -0
  4. package/README.md +40 -2
  5. package/dist/appName.d.ts +2 -0
  6. package/dist/appName.js +8 -0
  7. package/dist/components/ScopeSelect.d.ts +7 -0
  8. package/dist/components/ScopeSelect.js +6 -0
  9. package/dist/components/Shared.d.ts +34 -0
  10. package/dist/components/Shared.js +55 -0
  11. package/dist/data/derive.d.ts +21 -0
  12. package/dist/data/derive.js +47 -0
  13. package/dist/data/draftRules.d.ts +10 -0
  14. package/dist/data/draftRules.js +20 -0
  15. package/dist/data/engine/engineDataSource.d.ts +194 -0
  16. package/dist/data/engine/engineDataSource.js +836 -0
  17. package/dist/data/engine/errors.d.ts +13 -0
  18. package/dist/data/engine/errors.js +21 -0
  19. package/dist/data/engine/mapping.d.ts +172 -0
  20. package/dist/data/engine/mapping.js +1487 -0
  21. package/dist/data/engine/protocol.d.ts +910 -0
  22. package/dist/data/engine/protocol.js +67 -0
  23. package/dist/data/index.d.ts +18 -0
  24. package/dist/data/index.js +23 -0
  25. package/dist/data/mock/devSource.d.ts +7 -0
  26. package/dist/data/mock/devSource.js +10 -0
  27. package/dist/data/mock/fixtures-analytics.d.ts +7 -0
  28. package/dist/data/mock/fixtures-analytics.js +123 -0
  29. package/dist/data/mock/fixtures-briefs.d.ts +4 -0
  30. package/dist/data/mock/fixtures-briefs.js +230 -0
  31. package/dist/data/mock/fixtures-content.d.ts +4 -0
  32. package/dist/data/mock/fixtures-content.js +89 -0
  33. package/dist/data/mock/fixtures-digests.d.ts +3 -0
  34. package/dist/data/mock/fixtures-digests.js +40 -0
  35. package/dist/data/mock/fixtures-drafts.d.ts +2 -0
  36. package/dist/data/mock/fixtures-drafts.js +74 -0
  37. package/dist/data/mock/fixtures-gate.d.ts +3 -0
  38. package/dist/data/mock/fixtures-gate.js +49 -0
  39. package/dist/data/mock/fixtures-hooks.d.ts +2 -0
  40. package/dist/data/mock/fixtures-hooks.js +103 -0
  41. package/dist/data/mock/fixtures-inbox.d.ts +11 -0
  42. package/dist/data/mock/fixtures-inbox.js +213 -0
  43. package/dist/data/mock/fixtures-links.d.ts +5 -0
  44. package/dist/data/mock/fixtures-links.js +89 -0
  45. package/dist/data/mock/fixtures-memory.d.ts +3 -0
  46. package/dist/data/mock/fixtures-memory.js +148 -0
  47. package/dist/data/mock/fixtures-ops.d.ts +15 -0
  48. package/dist/data/mock/fixtures-ops.js +403 -0
  49. package/dist/data/mock/fixtures-optimise.d.ts +18 -0
  50. package/dist/data/mock/fixtures-optimise.js +221 -0
  51. package/dist/data/mock/fixtures-pacing.d.ts +5 -0
  52. package/dist/data/mock/fixtures-pacing.js +285 -0
  53. package/dist/data/mock/fixtures-publish.d.ts +2 -0
  54. package/dist/data/mock/fixtures-publish.js +129 -0
  55. package/dist/data/mock/fixtures-store.d.ts +10 -0
  56. package/dist/data/mock/fixtures-store.js +13 -0
  57. package/dist/data/mock/fixtures-variants.d.ts +5 -0
  58. package/dist/data/mock/fixtures-variants.js +138 -0
  59. package/dist/data/mock/fixtures.d.ts +6 -0
  60. package/dist/data/mock/fixtures.js +420 -0
  61. package/dist/data/mock/mockDataSource.d.ts +98 -0
  62. package/dist/data/mock/mockDataSource.js +903 -0
  63. package/dist/data/money.d.ts +14 -0
  64. package/dist/data/money.js +36 -0
  65. package/dist/data/platforms.d.ts +12 -0
  66. package/dist/data/platforms.js +26 -0
  67. package/dist/data/source.d.ts +196 -0
  68. package/dist/data/source.js +1 -0
  69. package/dist/data/time.d.ts +23 -0
  70. package/dist/data/time.js +86 -0
  71. package/dist/data/types.d.ts +1092 -0
  72. package/dist/data/types.js +3 -0
  73. package/dist/env.d.ts +59 -0
  74. package/dist/hooks/useAsync.d.ts +19 -0
  75. package/dist/hooks/useAsync.js +25 -0
  76. package/dist/index.d.ts +56 -0
  77. package/dist/index.js +58 -0
  78. package/dist/lib/host.d.ts +21 -0
  79. package/dist/lib/host.js +32 -0
  80. package/dist/lib/shell.d.ts +156 -0
  81. package/dist/lib/shell.js +16 -0
  82. package/dist/screens/AccountsScreen.d.ts +8 -0
  83. package/dist/screens/AccountsScreen.js +100 -0
  84. package/dist/screens/AnalyticsScreen.d.ts +7 -0
  85. package/dist/screens/AnalyticsScreen.js +64 -0
  86. package/dist/screens/ApprovalsScreen.d.ts +10 -0
  87. package/dist/screens/ApprovalsScreen.js +144 -0
  88. package/dist/screens/BriefsScreen.d.ts +7 -0
  89. package/dist/screens/BriefsScreen.js +83 -0
  90. package/dist/screens/CalendarScreen.d.ts +10 -0
  91. package/dist/screens/CalendarScreen.js +143 -0
  92. package/dist/screens/CampaignsScreen.d.ts +7 -0
  93. package/dist/screens/CampaignsScreen.js +52 -0
  94. package/dist/screens/ChannelMemoryScreen.d.ts +7 -0
  95. package/dist/screens/ChannelMemoryScreen.js +109 -0
  96. package/dist/screens/ContentScreen.d.ts +7 -0
  97. package/dist/screens/ContentScreen.js +64 -0
  98. package/dist/screens/DigestsScreen.d.ts +7 -0
  99. package/dist/screens/DigestsScreen.js +53 -0
  100. package/dist/screens/DraftsScreen.d.ts +10 -0
  101. package/dist/screens/DraftsScreen.js +108 -0
  102. package/dist/screens/FailuresScreen.d.ts +8 -0
  103. package/dist/screens/FailuresScreen.js +111 -0
  104. package/dist/screens/HookTestsScreen.d.ts +7 -0
  105. package/dist/screens/HookTestsScreen.js +54 -0
  106. package/dist/screens/InboxScreen.d.ts +12 -0
  107. package/dist/screens/InboxScreen.js +76 -0
  108. package/dist/screens/LinksScreen.d.ts +7 -0
  109. package/dist/screens/LinksScreen.js +52 -0
  110. package/dist/screens/PacingScreen.d.ts +7 -0
  111. package/dist/screens/PacingScreen.js +88 -0
  112. package/dist/screens/PublishJobsScreen.d.ts +7 -0
  113. package/dist/screens/PublishJobsScreen.js +66 -0
  114. package/dist/screens/SuggestionsScreen.d.ts +8 -0
  115. package/dist/screens/SuggestionsScreen.js +94 -0
  116. package/dist/screens/TextGateScreen.d.ts +7 -0
  117. package/dist/screens/TextGateScreen.js +111 -0
  118. package/dist/screens/ThreadsScreen.d.ts +8 -0
  119. package/dist/screens/ThreadsScreen.js +113 -0
  120. package/dist/screens/TypedBriefsScreen.d.ts +7 -0
  121. package/dist/screens/TypedBriefsScreen.js +75 -0
  122. package/dist/screens/labels.d.ts +121 -0
  123. package/dist/screens/labels.js +272 -0
  124. package/package.json +56 -3
@@ -0,0 +1,910 @@
1
+ import type { JsonValue } from "../types.js";
2
+ /** Every method the shell forwards. Keep in step with UI_METHODS in src-tauri/src/lib.rs. */
3
+ export declare const UI_METHODS: readonly ["channel.list", "calendar.list", "calendar.get", "calendar.approve", "calendar.reject", "calendar.pause", "calendar.resume", "brief.get", "account.list", "account.get", "account.pause", "account.resume", "account.disconnect", "draft.list", "draft.approve", "draft.mark_posted", "draft.skip", "publish.get", "publish.list", "optimise.list", "optimise.get", "optimise.accept", "optimise.dismiss", "allowance.get", "spend.report", "price.list", "campaign.list", "link.list", "link.attribution", "hook_test.list", "hook_test.get", "digest.list", "digest.get", "digest.applied", "content.list", "content.get", "content.experiment_summary", "gate_policy.get", "gate.check", "gate.records", "brief_out.list", "brief_out.get", "delivery.list", "delivery.get", "dispatch.list", "memory.get", "memory.history", "proof.list", "typed_brief.list", "typed_brief.get", "variant.list", "analytics.list", "analytics.summary", "metric_import.list", "heartbeat.status", "store.restore_receipts", "inbox.list", "inbox.get", "inbox.stats", "publish.next", "publish.quota_get", "doctor", "rightkit.settings.get", "rightkit.settings.patch"];
4
+ export type UiMethod = (typeof UI_METHODS)[number];
5
+ /** The exact key of a channel: venture, channel and account. */
6
+ export interface EngineScope {
7
+ venture: string;
8
+ channel: string;
9
+ account: string;
10
+ }
11
+ export interface EngineChannelRow {
12
+ scope: EngineScope;
13
+ brand_code: string;
14
+ monetised: boolean;
15
+ asset_rights: string;
16
+ }
17
+ export interface EngineChannelList {
18
+ channels: EngineChannelRow[];
19
+ }
20
+ export interface EngineMediaItem {
21
+ hash: string;
22
+ kind: string;
23
+ duration_ms: number | null;
24
+ }
25
+ /** One stored calendar entry, as every calendar command returns it. */
26
+ export interface EngineEntry {
27
+ scope: EngineScope;
28
+ entry_id: string;
29
+ brief_id: string;
30
+ brief_revision: number;
31
+ platform: string;
32
+ format: string;
33
+ caption: string;
34
+ media: EngineMediaItem[];
35
+ /** UTC instant, YYYY-MM-DDTHH:MM:SSZ. */
36
+ scheduled_at: string;
37
+ timezone: string;
38
+ local_time: string;
39
+ /** The stored state. */
40
+ state: string;
41
+ /** `late` for a draft or media_pending entry past its preparation deadline; otherwise `state`. */
42
+ effective_state: string;
43
+ paused_from: string | null;
44
+ revision: number;
45
+ approval_state: string;
46
+ approved_entry_revision: number | null;
47
+ approved_by: string | null;
48
+ policy_revision: number | null;
49
+ rejection_reason: string | null;
50
+ updated_at: string;
51
+ }
52
+ export interface EngineCalendarList {
53
+ scope: EngineScope;
54
+ entries: EngineEntry[];
55
+ }
56
+ /** Derived readiness the engine returns with every account. `blockers` are machine codes. */
57
+ export interface EngineAccountReadiness {
58
+ can_publish: boolean;
59
+ blockers: string[];
60
+ }
61
+ /**
62
+ * One stored account, as account.list, account.get, account.put, account.pause and account.resume
63
+ * return it. The account key is the scope plus the platform. States the engine cannot know are
64
+ * stored as `unknown` or `not_started`.
65
+ */
66
+ export interface EngineAccount {
67
+ scope: EngineScope;
68
+ platform: string;
69
+ handle: string;
70
+ display_name: string;
71
+ account_kind: string;
72
+ /** Set only for instagram: instagram_login or facebook_login. */
73
+ login_route: string | null;
74
+ /** not_connected, connected, reauth_required or unknown. */
75
+ connection_state: string;
76
+ /** UTC instant, or null when the expiry is not known. */
77
+ token_expires_at: string | null;
78
+ /** Each entitlement is not_started, in_progress, passed, blocked or unknown. */
79
+ sandbox_mechanics: string;
80
+ review_submission: string;
81
+ audience_visible: string;
82
+ /** UTC instant the quota cooldown ends. Active while it is after `now`. */
83
+ quota_cooldown_until: string | null;
84
+ paused: boolean;
85
+ paused_reason: string | null;
86
+ paused_at: string | null;
87
+ revision: number;
88
+ updated_at: string;
89
+ readiness: EngineAccountReadiness;
90
+ }
91
+ /**
92
+ * account.disconnect output (crates/protocol/src/accounts.rs). `cancelled_jobs` and `kept_jobs` are publish job ids.
93
+ */
94
+ export interface EngineAccountDisconnect {
95
+ account: EngineAccount;
96
+ cancelled_jobs: string[];
97
+ kept_jobs: string[];
98
+ }
99
+ export interface EngineAccountList {
100
+ accounts: EngineAccount[];
101
+ }
102
+ /** One stored manual draft, as every draft command returns it (crates/protocol/src/drafts.rs). */
103
+ export interface EngineDraft {
104
+ scope: EngineScope;
105
+ draft_id: string;
106
+ platform: string;
107
+ kind: string;
108
+ target: string | null;
109
+ title: string | null;
110
+ body: string;
111
+ body_chars: number;
112
+ disclosure_required: boolean;
113
+ state: string;
114
+ revision: number;
115
+ posted_url: string | null;
116
+ /** UTC instant, YYYY-MM-DDTHH:MM:SSZ. Set only when posted. */
117
+ posted_at: string | null;
118
+ skip_reason: string | null;
119
+ source_note: string;
120
+ created_at: string;
121
+ updated_at: string;
122
+ }
123
+ export interface EngineDraftList {
124
+ scope: EngineScope;
125
+ drafts: EngineDraft[];
126
+ }
127
+ /** draft.mark_posted reply: the draft plus the host check that passed. */
128
+ export interface EngineDraftMarkPosted {
129
+ draft: EngineDraft;
130
+ host_check: string;
131
+ host_note: string | null;
132
+ }
133
+ /** A remote id recorded by the publish core (crates/protocol/src/publish.rs, PublishRemote). */
134
+ export interface EnginePublishRemote {
135
+ container_id: string | null;
136
+ post_id: string | null;
137
+ permalink: string | null;
138
+ }
139
+ /** One durable publish job, as publish.get and publish.list return it. Holds no token. */
140
+ export interface EnginePublishJob {
141
+ job_id: string;
142
+ scope: EngineScope;
143
+ remote_account: string;
144
+ platform: string;
145
+ entry_id: string;
146
+ entry_revision: number;
147
+ payload: {
148
+ caption: string;
149
+ format: string;
150
+ };
151
+ phase: string;
152
+ remote: EnginePublishRemote;
153
+ attempts: number;
154
+ polls: number;
155
+ reconciles: number;
156
+ inflight: string | null;
157
+ /** UTC instant, or null when the job is not waiting. */
158
+ next_attempt_at: string | null;
159
+ /** queued, running, waiting, published, failed, outcome_unknown or cancelled. */
160
+ state: string;
161
+ last_error_code: string | null;
162
+ last_error_message: string | null;
163
+ created_at: string;
164
+ updated_at: string;
165
+ revision: number;
166
+ /** Set only when a person closed an outcome_unknown job with publish.resolve_unknown. Null otherwise. */
167
+ resolution?: EnginePublishResolution | null;
168
+ }
169
+ /** What a person recorded for an outcome_unknown job (PublishResolution, crates/protocol/src/publish.rs). */
170
+ export interface EnginePublishResolution {
171
+ decision: string;
172
+ resolved_by: string;
173
+ resolved_at: string;
174
+ note: string;
175
+ remote_id_entered_by_hand: boolean;
176
+ }
177
+ export interface EnginePublishList {
178
+ scope: EngineScope;
179
+ jobs: EnginePublishJob[];
180
+ }
181
+ /** One stored inbox event (crates/protocol/src/inbox.rs, InboxEvent). Every text field is untrusted. */
182
+ export interface EngineInboxEvent {
183
+ event_id: string;
184
+ delivery: string;
185
+ seq: number;
186
+ platform: string;
187
+ /** The bound channel account, or null when unmatched. */
188
+ scope: EngineScope | null;
189
+ unmatched_account: boolean;
190
+ /** `no_account` or `ambiguous_account`, or null when matched. */
191
+ unmatched_reason: string | null;
192
+ recipient_id: string | null;
193
+ kind: string;
194
+ platform_event_id: string | null;
195
+ sender_id: string | null;
196
+ text: string | null;
197
+ event_time: string | null;
198
+ oversize: boolean;
199
+ received_at: string;
200
+ state: string;
201
+ state_by: string | null;
202
+ state_at: string | null;
203
+ state_note: string;
204
+ }
205
+ export interface EngineInboxList {
206
+ events: EngineInboxEvent[];
207
+ /** The event id to pass as `before` for the next page, or null. */
208
+ next_before: string | null;
209
+ }
210
+ /** inbox.get reply: the event and the raw item JSON it came from. */
211
+ export interface EngineInboxGet {
212
+ event: EngineInboxEvent;
213
+ raw: unknown;
214
+ }
215
+ export interface EngineInboxStatsGroup {
216
+ scope: EngineScope | null;
217
+ kind: string;
218
+ state: string;
219
+ count: number;
220
+ }
221
+ /** inbox.stats reply (InboxStatsOutput). Takes no input; the counts are whole-store. */
222
+ export interface EngineInboxStats {
223
+ total_events: number;
224
+ unmatched_events: number;
225
+ groups: EngineInboxStatsGroup[];
226
+ deliveries_parsed: number;
227
+ deliveries_unparseable: number;
228
+ refused_total: number;
229
+ }
230
+ /** A publish job named by publish.next (crates/protocol/src/publish.rs, PublishNextJob). */
231
+ export interface EnginePublishNextJob {
232
+ job_id: string;
233
+ scope: EngineScope;
234
+ platform: string;
235
+ remote_account: string;
236
+ entry_id: string;
237
+ state: string;
238
+ phase: string;
239
+ scheduled_at: string;
240
+ }
241
+ /** A job publish.next says may not run now. `until` and `behind` are absent when the engine gives none. */
242
+ export interface EnginePublishNextBlocked extends EnginePublishNextJob {
243
+ reason: string;
244
+ reasons: string[];
245
+ until?: string | null;
246
+ detail: string;
247
+ behind?: string | null;
248
+ }
249
+ /** publish.next reply (PublishNextOutput). */
250
+ export interface EnginePublishNext {
251
+ now: string;
252
+ ready: EnginePublishNextJob[];
253
+ ready_total: number;
254
+ blocked: EnginePublishNextBlocked[];
255
+ in_progress: EnginePublishNextJob[];
256
+ }
257
+ /** publish.quota_get reply (PublishQuotaRecord). Limits are the stored ones, or the host app defaults when opted_in is false. */
258
+ export interface EnginePublishQuota {
259
+ scope: EngineScope;
260
+ platform: string;
261
+ remote_account: string;
262
+ opted_in: boolean;
263
+ min_gap_secs: number;
264
+ max_per_day: number;
265
+ default_min_gap_secs: number;
266
+ default_max_per_day: number;
267
+ paused_until?: string | null;
268
+ last_create_at?: string | null;
269
+ creates_today: number;
270
+ day_resets_at: string;
271
+ rate_limited_at?: string | null;
272
+ rate_limited_until?: string | null;
273
+ }
274
+ /** One optimise proposal (crates/protocol/src/optimise.rs, OptimiseProposal). value and threshold are exact integer text. */
275
+ export interface EngineOptimiseProposal {
276
+ scope: EngineScope;
277
+ proposal_id: string;
278
+ kind: string;
279
+ state: string;
280
+ revision: number;
281
+ source_job_id: string;
282
+ platform: string;
283
+ metric: string;
284
+ window: string;
285
+ observed_at: string;
286
+ value: string;
287
+ threshold: string;
288
+ sample_size: number;
289
+ decile_size: number;
290
+ due_at: string;
291
+ lineage_job_ids: string[];
292
+ lineage_pull_ids: string[];
293
+ decision_note: string | null;
294
+ decided_at: string | null;
295
+ calendar_entry_id: string | null;
296
+ created_at: string;
297
+ updated_at: string;
298
+ }
299
+ export interface EngineOptimiseList {
300
+ scope: EngineScope;
301
+ proposals: EngineOptimiseProposal[];
302
+ }
303
+ /** One allowance row (crates/protocol/src/spend.rs, SpendAllowance). Amounts are integer micro-units. */
304
+ export interface EngineSpendAllowance {
305
+ scope: EngineScope;
306
+ month: string;
307
+ currency: string;
308
+ limit_micro: number;
309
+ reserved_micro: number;
310
+ committed_micro: number;
311
+ remaining_micro: number;
312
+ revision: number;
313
+ updated_at: string;
314
+ }
315
+ export interface EngineSpendRouteTotal {
316
+ route_id: string;
317
+ count_reserved: number;
318
+ count_committed: number;
319
+ count_released: number;
320
+ count_expired: number;
321
+ open_micro: number;
322
+ forecast_micro: number;
323
+ measured_micro: number;
324
+ variance_micro: number;
325
+ over_reservations: number;
326
+ }
327
+ export interface EngineSpendReport {
328
+ scope: EngineScope;
329
+ month: string;
330
+ currency: string;
331
+ limit_micro: number;
332
+ reserved_micro: number;
333
+ committed_micro: number;
334
+ remaining_micro: number;
335
+ reconciles: boolean;
336
+ routes: EngineSpendRouteTotal[];
337
+ }
338
+ /** One price version with its qualification (SpendPriceView flattens the price row). */
339
+ export interface EngineSpendPrice {
340
+ route_id: string;
341
+ version: number;
342
+ provider: string;
343
+ model_slug: string;
344
+ unit: string;
345
+ amount_micro: number;
346
+ currency: string;
347
+ source_url: string | null;
348
+ source_path_line: string | null;
349
+ fetched_at: string;
350
+ verified_by: string | null;
351
+ created_at: string;
352
+ qualified: boolean;
353
+ reason: string | null;
354
+ }
355
+ export interface EngineSpendPriceList {
356
+ prices: EngineSpendPrice[];
357
+ }
358
+ /** Engine error codes the desktop maps (docs/CLI-POSTRIGHT.md, "Calendar error codes"). */
359
+ export type EngineErrorCodeName = "foreign_scope" | "not_found" | "brief_not_found" | "revision_conflict" | "revision_required" | "invalid_transition" | "time_nonexistent" | "time_ambiguous" | "timezone_unsupported" | "time_out_of_table" | "bad_input" | "db_error";
360
+ /** One campaign (crates/protocol/src/links.rs, Campaign). */
361
+ export interface EngineCampaign {
362
+ scope: EngineScope;
363
+ campaign_id: string;
364
+ name: string;
365
+ utm_campaign: string;
366
+ revision: number;
367
+ created_at: string;
368
+ updated_at: string;
369
+ }
370
+ /** campaign.list reply: every campaign in one scope, ordered by campaign id. */
371
+ export interface EngineCampaignList {
372
+ scope: EngineScope;
373
+ campaigns: EngineCampaign[];
374
+ }
375
+ /** One tracked link (TrackedLink). final_url is fixed at creation; the UTM parts are the ones it was cut with. */
376
+ export interface EngineTrackedLink {
377
+ scope: EngineScope;
378
+ link_id: string;
379
+ campaign_id: string;
380
+ variant_id: string;
381
+ platform: string;
382
+ destination: string;
383
+ calendar_entry_id: string | null;
384
+ utm_source: string;
385
+ utm_medium: string;
386
+ utm_campaign: string;
387
+ utm_content: string;
388
+ final_url: string;
389
+ created_at: string;
390
+ }
391
+ /** link.list reply. Ordered by campaign id, variant id, platform and link id. */
392
+ export interface EngineLinkList {
393
+ scope: EngineScope;
394
+ links: EngineTrackedLink[];
395
+ }
396
+ /** One link's visit count (AttributionRow). visits is a plain whole count. */
397
+ export interface EngineAttributionRow {
398
+ link_id: string;
399
+ variant_id: string;
400
+ platform: string;
401
+ account: string;
402
+ calendar_entry_id: string | null;
403
+ visits: number;
404
+ }
405
+ /** link.attribution reply: counts only, with the sum in total_visits. */
406
+ export interface EngineLinkAttribution {
407
+ scope: EngineScope;
408
+ campaign_id: string;
409
+ links: EngineAttributionRow[];
410
+ total_visits: number;
411
+ }
412
+ /** One opening of a hook test set (HookTestOpening). Value fields are set only once a read has compared it. */
413
+ export interface EngineHookTestOpening {
414
+ opening_index: number;
415
+ text: string;
416
+ job_id: string | null;
417
+ bound_at: string | null;
418
+ role: string | null;
419
+ value: string | null;
420
+ observed_at: string | null;
421
+ pull_id: string | null;
422
+ published_at: string | null;
423
+ }
424
+ /** One variant set (HookTestSet), as hook_test.get returns it and hook_test.list holds it. */
425
+ export interface EngineHookTestSet {
426
+ scope: EngineScope;
427
+ set_id: string;
428
+ brief_ref: string;
429
+ body: string;
430
+ metric: string;
431
+ window: string;
432
+ state: string;
433
+ revision: number;
434
+ winner_opening: number | null;
435
+ decided_at: string | null;
436
+ created_at: string;
437
+ updated_at: string;
438
+ openings: EngineHookTestOpening[];
439
+ }
440
+ /** hook_test.list reply: every set in one scope, ordered by creation then set id. */
441
+ export interface EngineHookTestList {
442
+ scope: EngineScope;
443
+ sets: EngineHookTestSet[];
444
+ }
445
+ /** One digest entry (crates/protocol/src/digest.rs, DigestEntry). source is a url or path:line. */
446
+ export interface EngineDigestEntry {
447
+ entry_id: string;
448
+ topic: string;
449
+ finding: string;
450
+ source: string;
451
+ fetched_on: string;
452
+ platform: string;
453
+ format: string;
454
+ }
455
+ /** One stored digest (DigestRecord), as digest.get returns it and digest.list holds it. */
456
+ export interface EngineDigestRecord {
457
+ scope: EngineScope;
458
+ digest_id: string;
459
+ digest_date: string;
460
+ entries: EngineDigestEntry[];
461
+ created_at: string;
462
+ }
463
+ /** digest.list reply: every digest in one scope, ordered by date then id. */
464
+ export interface EngineDigestList {
465
+ scope: EngineScope;
466
+ digests: EngineDigestRecord[];
467
+ }
468
+ /** One applied digest entry (DigestApplication). entry_id is the draft calendar entry it created. */
469
+ export interface EngineDigestApplication {
470
+ digest_id: string;
471
+ digest_entry_id: string;
472
+ brief_id: string;
473
+ entry_id: string;
474
+ applied_at: string;
475
+ }
476
+ /** digest.applied reply: which digest entries produced which calendar entries. */
477
+ export interface EngineDigestApplied {
478
+ scope: EngineScope;
479
+ digest_id: string;
480
+ applications: EngineDigestApplication[];
481
+ }
482
+ /** One media item a content record reuses (ContentMediaItem). duration_ms is a whole number or null. */
483
+ export interface EngineContentMediaItem {
484
+ hash: string;
485
+ kind: string;
486
+ duration_ms: number | null;
487
+ }
488
+ /** One stored content record (ContentRecord). state is the derived state at the clock the read used. */
489
+ export interface EngineContentRecord {
490
+ scope: EngineScope;
491
+ content_id: string;
492
+ title: string;
493
+ media: EngineContentMediaItem[];
494
+ base_caption: string;
495
+ evergreen: boolean;
496
+ cooldown_days: number;
497
+ expires_at: string | null;
498
+ state: string;
499
+ withdrawal_reason: string | null;
500
+ revision: number;
501
+ created_at: string;
502
+ updated_at: string;
503
+ }
504
+ /** One caption or CTA variant (ContentVariant). */
505
+ export interface EngineContentVariant {
506
+ scope: EngineScope;
507
+ variant_id: string;
508
+ content_id: string;
509
+ kind: string;
510
+ text: string;
511
+ created_at: string;
512
+ }
513
+ /** content.list reply: every record in one scope, ordered by content id. */
514
+ export interface EngineContentList {
515
+ scope: EngineScope;
516
+ records: EngineContentRecord[];
517
+ }
518
+ /** content.get reply: one record and its variants. */
519
+ export interface EngineContentGet {
520
+ record: EngineContentRecord;
521
+ variants: EngineContentVariant[];
522
+ }
523
+ /** Plain counts for one variant (VariantCount). Counts are whole numbers. */
524
+ export interface EngineContentVariantCount {
525
+ variant_id: string;
526
+ text: string;
527
+ planned: number;
528
+ published: number;
529
+ cancelled: number;
530
+ meets_minimum: boolean;
531
+ /** Published occurrences whose primary metric value was compared. Zero unless a metric is declared. */
532
+ compared?: number;
533
+ /** Exact sum of the compared values, as decimal text. "0" unless a metric is declared. */
534
+ total?: string;
535
+ }
536
+ /** content.experiment_summary request (ContentExperimentSummaryInput). */
537
+ export interface EngineContentExperimentSummaryInput {
538
+ scope: EngineScope;
539
+ content_id: string;
540
+ min_occurrences?: number;
541
+ /** The clock for the 24-hour rule of a declared primary metric. Defaults to the current time. */
542
+ now?: string;
543
+ }
544
+ /** content.experiment_summary reply (ContentExperimentSummaryOutput). */
545
+ export interface EngineContentExperimentSummary {
546
+ scope: EngineScope;
547
+ content_id: string;
548
+ min_occurrences: number;
549
+ verdict: string;
550
+ reason: string;
551
+ /** The primary metric declared for the record, or null. */
552
+ primary_metric?: string | null;
553
+ caption_winner?: string | null;
554
+ cta_winner?: string | null;
555
+ caption: EngineContentVariantCount[];
556
+ cta: EngineContentVariantCount[];
557
+ }
558
+ /** content.declare_metric request (ContentDeclareMetricInput). */
559
+ export interface EngineContentDeclareMetricInput {
560
+ scope: EngineScope;
561
+ content_id: string;
562
+ metric: string;
563
+ now?: string;
564
+ }
565
+ /** content.declare_metric reply (ContentDeclareMetricOutput). `window` is "24h". `created` is false when the same metric was already declared. */
566
+ export interface EngineContentDeclareMetricOutput {
567
+ scope: EngineScope;
568
+ content_id: string;
569
+ metric: string;
570
+ window: string;
571
+ declared_at: string;
572
+ created: boolean;
573
+ }
574
+ /** content.plan_occurrence request (ContentPlanOccurrenceInput). */
575
+ export interface EngineContentPlanOccurrenceInput {
576
+ scope: EngineScope;
577
+ content_id: string;
578
+ platform: string;
579
+ scheduled_at: string;
580
+ caption_variant_id?: string;
581
+ cta_variant_id?: string;
582
+ calendar_entry_id?: string;
583
+ /** On a cooldown conflict, plan at the earliest allowed time instead of refusing. Null or false keeps the refusal. */
584
+ reschedule_on_cooldown?: boolean | null;
585
+ now?: string;
586
+ }
587
+ /** gate_policy.get reply: one stored policy revision (crates/protocol/src/gate.rs, GatePolicy). Thresholds are integers in thousandths. */
588
+ export interface EngineGatePolicy {
589
+ scope: EngineScope;
590
+ revision: number;
591
+ policy: {
592
+ banned_phrases: string[];
593
+ stock_openers: string[];
594
+ min_words: number;
595
+ dash_max_per_100_words_milli: number;
596
+ semicolon_max_per_100_words_milli: number;
597
+ variance_min_milli: number;
598
+ variance_min_sentences: number;
599
+ tricolon_max_per_100_sentences_milli: number;
600
+ tricolon_min_sentences: number;
601
+ required: {
602
+ banned_phrase: boolean;
603
+ dash_density: boolean;
604
+ semicolon_density: boolean;
605
+ sentence_length_variance: boolean;
606
+ tricolon_frequency: boolean;
607
+ stock_opener: boolean;
608
+ };
609
+ };
610
+ created_at: string;
611
+ }
612
+ /** One rule's finding in a gate.check reply (GateRuleResult). */
613
+ export interface EngineGateRule {
614
+ rule_id: string;
615
+ required: boolean;
616
+ verdict: string;
617
+ blocks: boolean;
618
+ reason: string;
619
+ }
620
+ /** gate.check reply (GateCheckOutput). The desktop always sends record false, so recorded is false here. */
621
+ export interface EngineGateCheck {
622
+ scope: EngineScope;
623
+ subject_id: string;
624
+ disposition: string;
625
+ policy_revision: number;
626
+ text_hash: string;
627
+ rules: EngineGateRule[];
628
+ blocking_rules: string[];
629
+ proof_ids_used: string[];
630
+ recorded: boolean;
631
+ record_seq: number | null;
632
+ }
633
+ /** One stored verdict record (GateRecord). The record's own JSON is not listed: the desktop shows these columns only. */
634
+ export interface EngineGateRecord {
635
+ record_seq: number;
636
+ subject_id: string;
637
+ text_hash: string;
638
+ policy_revision: number;
639
+ disposition: string;
640
+ checked_at: string;
641
+ }
642
+ /** gate.records reply, newest first. The records carry no scope of their own, so the scope is the one read. */
643
+ export interface EngineGateRecords {
644
+ scope: EngineScope;
645
+ subject_id: string;
646
+ records: EngineGateRecord[];
647
+ }
648
+ /** One outgoing brief (BriefOutRecord). document is the brief exactly as the engine accepted it. */
649
+ export interface EngineBriefOut {
650
+ scope: EngineScope;
651
+ request_id: string;
652
+ brief_id: string;
653
+ revision: number;
654
+ state: string;
655
+ document: JsonValue;
656
+ /** Every envelope stored for the brief, one per deliverable key. */
657
+ deliveries: EngineDeliveryRecord[];
658
+ created_at: string;
659
+ updated_at: string;
660
+ }
661
+ export interface EngineBriefOutList {
662
+ scope: EngineScope;
663
+ briefs: EngineBriefOut[];
664
+ }
665
+ /** One accepted delivery envelope (DeliveryRecord). */
666
+ export interface EngineDeliveryRecord {
667
+ scope: EngineScope;
668
+ envelope_id: string;
669
+ request_id: string;
670
+ brief_id: string;
671
+ brief_revision: number;
672
+ /** The row key the editor engine gave the envelope; empty when stored without one. */
673
+ deliverable: string;
674
+ document: JsonValue;
675
+ accepted_at: string;
676
+ }
677
+ export interface EngineDeliveryList {
678
+ scope: EngineScope;
679
+ deliveries: EngineDeliveryRecord[];
680
+ }
681
+ /**
682
+ * One dispatch attempt (DispatchAttempt). `detail` is the engine's own JSON object: it carries message and
683
+ * stderr_tail, among other keys. The attempt carries no scope; the scope is the one the list was read in.
684
+ */
685
+ export interface EngineDispatchAttempt {
686
+ attempt_id: number;
687
+ request_id: string;
688
+ engine: string;
689
+ started_at: string;
690
+ finished_at: string | null;
691
+ exit_code: number | null;
692
+ outcome: string;
693
+ detail: JsonValue;
694
+ }
695
+ export interface EngineDispatchList {
696
+ scope: EngineScope;
697
+ attempts: EngineDispatchAttempt[];
698
+ }
699
+ /** One stored channel memory revision without its document (memory.history, crates/protocol/src/memory.rs). */
700
+ export interface EngineMemoryRevisionRow {
701
+ revision: number;
702
+ supersedes: number | null;
703
+ author: string;
704
+ created_at: string;
705
+ content_hash: string;
706
+ }
707
+ /** memory.get reply: one revision with its full document. Absent revision means the latest. */
708
+ export interface EngineMemoryGet extends EngineMemoryRevisionRow {
709
+ scope: EngineScope;
710
+ document: JsonValue;
711
+ }
712
+ /** memory.history reply, newest revision first. Empty when nothing is stored. */
713
+ export interface EngineMemoryHistory {
714
+ scope: EngineScope;
715
+ revisions: EngineMemoryRevisionRow[];
716
+ }
717
+ /** One stored proof (ProofRow, crates/protocol/src/schema.rs). value is the exact decimal as text, never a number. */
718
+ export interface EngineProofRow {
719
+ venture: string;
720
+ channel: string;
721
+ account: string;
722
+ answer_id: string;
723
+ proof_id: string;
724
+ status: string;
725
+ subject: string;
726
+ value: string;
727
+ units: string;
728
+ origin: string;
729
+ observed_from: string;
730
+ observed_to: string;
731
+ source_excerpt: string;
732
+ superseded_by: string | null;
733
+ withdrawal_note: string | null;
734
+ }
735
+ /** proof.list reply: the proofs of exactly one scope, sorted by answer id. */
736
+ export interface EngineProofList {
737
+ scope: EngineScope;
738
+ proofs: EngineProofRow[];
739
+ }
740
+ /** variant.derive request (VariantDeriveInput). Only the fields the desktop would send are listed. */
741
+ export interface EngineVariantDeriveInput {
742
+ scope: EngineScope;
743
+ brief_id: string;
744
+ platforms: string[];
745
+ hashtags?: string[];
746
+ link?: string;
747
+ duration_seconds?: number;
748
+ /** Refuse a platform rule whose fetched_at is more than this many days before now (rule_stale). Null applies no age limit. */
749
+ max_rule_age_days?: number | null;
750
+ now?: string;
751
+ }
752
+ /** One scene of an explainer beat (SceneSpec). Every field is text. */
753
+ export interface EngineSceneSpec {
754
+ teaches: string;
755
+ frame: string;
756
+ motion: string;
757
+ words: string;
758
+ sound: string;
759
+ }
760
+ /** The five beats of an explainer (ExplainerBeats). Present exactly on explainer briefs. */
761
+ export interface EngineExplainerBeats {
762
+ question: EngineSceneSpec;
763
+ model: EngineSceneSpec;
764
+ proof: EngineSceneSpec;
765
+ turn: EngineSceneSpec;
766
+ payoff: EngineSceneSpec;
767
+ }
768
+ /** One product-demo step (DemoStep). */
769
+ export interface EngineDemoStep {
770
+ say: string;
771
+ }
772
+ /** One stored typed brief (TypedBrief), as typed_brief.get and typed_brief.list return it. */
773
+ export interface EngineTypedBrief {
774
+ scope: EngineScope;
775
+ brief_id: string;
776
+ brief_type: string;
777
+ hook: string;
778
+ body: string;
779
+ explainer: EngineExplainerBeats | null;
780
+ demo_steps: EngineDemoStep[];
781
+ revision: number;
782
+ created_at: string;
783
+ updated_at: string;
784
+ }
785
+ /** typed_brief.list reply: every brief in one scope, ordered by brief id. */
786
+ export interface EngineTypedBriefList {
787
+ scope: EngineScope;
788
+ briefs: EngineTypedBrief[];
789
+ }
790
+ /** One platform variant (BriefVariant). The caption is the final text as stored. */
791
+ export interface EngineBriefVariant {
792
+ scope: EngineScope;
793
+ variant_id: string;
794
+ brief_id: string;
795
+ brief_revision: number;
796
+ platform: string;
797
+ rule_revision: string;
798
+ link_placement: string;
799
+ caption: string;
800
+ link: string | null;
801
+ first_comment: string | null;
802
+ bio_link: string | null;
803
+ created_at: string;
804
+ }
805
+ /** variant.list reply: the variants of one brief, ordered by platform then variant id. */
806
+ export interface EngineVariantList {
807
+ scope: EngineScope;
808
+ brief_id: string;
809
+ variants: EngineBriefVariant[];
810
+ }
811
+ /**
812
+ * One summary metric (AnalyticsSummaryMetric). It carries no source field: an import id marks a manual row, and
813
+ * its absence marks an API row. The field is left out of the JSON on API rows.
814
+ */
815
+ export interface EngineAnalyticsSummaryMetric {
816
+ metric: string;
817
+ state: string;
818
+ value: string | null;
819
+ observed_at: string;
820
+ window: string | null;
821
+ pull_id: string | null;
822
+ import_id?: string;
823
+ post_age_secs: number;
824
+ }
825
+ export interface EngineAnalyticsSummaryJob {
826
+ job_id: string;
827
+ platform: string;
828
+ remote_post_id: string;
829
+ published_at: string;
830
+ metrics: EngineAnalyticsSummaryMetric[];
831
+ }
832
+ /** analytics.summary reply: jobs by publish instant, metrics by name. */
833
+ export interface EngineAnalyticsSummary {
834
+ scope: EngineScope;
835
+ jobs: EngineAnalyticsSummaryJob[];
836
+ }
837
+ /** One stored observation (AnalyticsObservation). `source` is `api` or `manual_export`. */
838
+ export interface EngineAnalyticsObservation {
839
+ job_id: string;
840
+ platform: string;
841
+ remote_post_id: string;
842
+ published_at: string;
843
+ metric: string;
844
+ state: string;
845
+ value: string | null;
846
+ observed_at: string;
847
+ window: string | null;
848
+ source: string;
849
+ pull_id: string | null;
850
+ import_id?: string;
851
+ /** Lineage of the publish job, when analytics.lineage_put recorded one. Absent otherwise. */
852
+ variant_id?: string;
853
+ render_hash?: string;
854
+ time_map?: string;
855
+ }
856
+ /** analytics.list reply, ordered by observed instant, job and metric. The scope is the one the read was made in. */
857
+ export interface EngineAnalyticsObservations {
858
+ scope: EngineScope;
859
+ observations: EngineAnalyticsObservation[];
860
+ }
861
+ /** One committed manual import (MetricImportRecord). */
862
+ export interface EngineMetricImportRecord {
863
+ scope: EngineScope;
864
+ import_id: string;
865
+ platform: string;
866
+ source_note: string;
867
+ source: string;
868
+ created_at: string;
869
+ rows_written: number;
870
+ observations_written: number;
871
+ }
872
+ /** metric_import.list reply, ordered by creation instant, then import id. */
873
+ export interface EngineMetricImportList {
874
+ scope: EngineScope;
875
+ imports: EngineMetricImportRecord[];
876
+ }
877
+ /** heartbeat.status reply: the one record the daemon writes. pid, updated_ms and age_secs are null when there is no readable record. */
878
+ export interface EngineHeartbeatStatus {
879
+ now: string;
880
+ stale_after_secs: number;
881
+ all_alive: boolean;
882
+ /** alive | stale | missing | unreadable */
883
+ state: string;
884
+ pid: number | null;
885
+ updated_ms: number | null;
886
+ age_secs: number | null;
887
+ /** The record's own `state` value (the beat note); any JSON value. */
888
+ record_state: unknown;
889
+ error: string | null;
890
+ }
891
+ /** One restore receipt (StoreRestoreReceipt). The schema before and the set-aside path are absent when there were none. */
892
+ export interface EngineRestoreReceipt {
893
+ format: string;
894
+ receipt_id: string;
895
+ restored_at: string;
896
+ source_dir: string;
897
+ manifest_digest: string;
898
+ backup_digest: string;
899
+ backup_created_at: string;
900
+ backup_schema_version: number;
901
+ schema_before?: number | null;
902
+ schema_after: number;
903
+ previous_store?: string | null;
904
+ table_counts_after: Record<string, number>;
905
+ }
906
+ /** store.restore_receipts reply, newest first. `unreadable` names receipt files that did not parse. */
907
+ export interface EngineRestoreReceiptList {
908
+ receipts: EngineRestoreReceipt[];
909
+ unreadable: string[];
910
+ }