@ever-works/contracts 1.0.0 → 1.0.2

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.
@@ -0,0 +1,1372 @@
1
+ /**
2
+ * Provider selection for each capability category
3
+ */
4
+ interface ProvidersDto {
5
+ /** Search provider plugin ID */
6
+ search?: string;
7
+ /** Screenshot provider plugin ID */
8
+ screenshot?: string;
9
+ /** AI provider plugin ID */
10
+ ai?: string;
11
+ /** Content extractor provider plugin ID */
12
+ contentExtractor?: string;
13
+ /** Pipeline provider plugin ID */
14
+ pipeline?: string;
15
+ }
16
+
17
+ /**
18
+ * Cadence options for work scheduled updates
19
+ */
20
+ declare enum WorkScheduleCadence {
21
+ HOURLY = "hourly",
22
+ EVERY_3_HOURS = "every_3_hours",
23
+ EVERY_8_HOURS = "every_8_hours",
24
+ EVERY_12_HOURS = "every_12_hours",
25
+ DAILY = "daily",
26
+ WEEKLY = "weekly",
27
+ MONTHLY = "monthly"
28
+ }
29
+ /**
30
+ * Status options for work schedule
31
+ */
32
+ declare enum WorkScheduleStatus {
33
+ DISABLED = "disabled",
34
+ ACTIVE = "active",
35
+ PAUSED = "paused",
36
+ CANCELED = "canceled"
37
+ }
38
+ /**
39
+ * Billing mode options for scheduled updates
40
+ */
41
+ declare enum WorkScheduleBillingMode {
42
+ SUBSCRIPTION = "subscription",
43
+ USAGE = "usage"
44
+ }
45
+
46
+ declare const IMPORT_SOURCE_TYPES: readonly ["data_repo", "awesome_readme", "link_existing", "works_config"];
47
+ type ImportSourceType = (typeof IMPORT_SOURCE_TYPES)[number];
48
+ declare const AWESOME_README_IMPORT_MODES: readonly ["clone", "reuse_source"];
49
+ type AwesomeReadmeImportMode = (typeof AWESOME_README_IMPORT_MODES)[number];
50
+ type RepositoryRole = 'data' | 'work' | 'website';
51
+ interface RepositoryTarget {
52
+ owner?: string;
53
+ repo: string;
54
+ }
55
+ interface RelatedRepositories {
56
+ data?: RepositoryTarget;
57
+ work?: RepositoryTarget;
58
+ website?: RepositoryTarget;
59
+ }
60
+ interface WorksConfigSnapshot {
61
+ name?: string;
62
+ initialPrompt?: string;
63
+ model?: string;
64
+ websiteRepo?: string;
65
+ scheduleCadence?: WorkScheduleCadence | null;
66
+ providers?: ProvidersDto;
67
+ }
68
+ interface SourceRepository<TImportedAt = string> {
69
+ url: string;
70
+ owner: string;
71
+ repo: string;
72
+ /**
73
+ * Which kind of import produced this record — and, since APW-01, that an
74
+ * **App Work** did.
75
+ *
76
+ * The widening is additive (APW-01 plan §3.2, `plan.md:310`): `IMPORT_SOURCE_TYPES`
77
+ * keeps its four members and every existing reader still sees the four
78
+ * `ImportSourceType` values it always did. The three `app_*` members are a
79
+ * separate closed set (`APP_SOURCE_REPOSITORY_TYPES`), so an imported entry can
80
+ * never become an App Work and an App Work can never be mistaken for an import
81
+ * (APW-01 FR-54). `supportsWorkSourceSync` answers `false` for all three: an App
82
+ * Work's repository is not an import source.
83
+ */
84
+ type: ImportSourceType | AppSourceRepositoryType;
85
+ importedAt: TImportedAt;
86
+ relatedRepositories?: RelatedRepositories;
87
+ worksConfig?: WorksConfigSnapshot;
88
+ /**
89
+ * APW-01 — the repository a `fork` or a `private-copy` App Work follows.
90
+ *
91
+ * **Absent for a `link`**, which has no upstream at all. The field lives on the
92
+ * shared shape (rather than only on `AppSourceRecord`) so a reader of this DTO
93
+ * can describe an App Work without importing the App-source module
94
+ * (`plan.md:310-317`).
95
+ */
96
+ upstream?: AppUpstreamRef;
97
+ /** APW-01 — the Blueprint shown in the create preview; APW-03 applies it on ready. */
98
+ blueprintId?: string;
99
+ /** APW-01 — how that Blueprint was matched, so every reader sees the same answer. */
100
+ blueprintMatchSource?: AppSourceBlueprintMatchSource;
101
+ /** APW-01 — true only when this App Work's creation made the fork or private copy (R-4). */
102
+ createdByThisWork?: boolean;
103
+ /**
104
+ * APW-01 — the member's decline of FR-29a's automatic start.
105
+ *
106
+ * Written only when the member declined, so an absent field means "on" and no
107
+ * existing row or caller changes meaning (`plan.md:240`, §4.2 step 10).
108
+ */
109
+ autoProvision?: boolean;
110
+ }
111
+ interface RepoVisibility {
112
+ data: boolean;
113
+ website: boolean;
114
+ work: boolean;
115
+ }
116
+ interface ImportEnrichmentConfig {
117
+ expansionFactor?: number;
118
+ }
119
+ interface AnalyzeRepositoryResponseDto {
120
+ sourceUrl: string;
121
+ owner: string;
122
+ repo: string;
123
+ detectedType: ImportSourceType | null;
124
+ isPublic: boolean;
125
+ requiresAuth: boolean;
126
+ structure?: {
127
+ hasDataFolder: boolean;
128
+ hasConfig: boolean;
129
+ hasReadme: boolean;
130
+ hasWorksConfig?: boolean;
131
+ isMultiFile?: boolean;
132
+ itemCount?: number;
133
+ categoryCount?: number;
134
+ };
135
+ worksConfig?: WorksConfigSnapshot;
136
+ relatedDataRepo?: {
137
+ name: string;
138
+ owner: string;
139
+ };
140
+ baseSlug?: string;
141
+ slugConflict?: {
142
+ hasConflict: boolean;
143
+ conflictingRepos: string[];
144
+ suggestedSlug: string;
145
+ };
146
+ hasDataRepoWriteAccess?: boolean;
147
+ error?: string;
148
+ }
149
+ interface ImportWorkDto {
150
+ sourceUrl: string;
151
+ sourceType: ImportSourceType;
152
+ awesomeReadmeImportMode?: AwesomeReadmeImportMode;
153
+ name: string;
154
+ owner?: string;
155
+ organization?: boolean;
156
+ gitProvider: string;
157
+ deployProvider?: string;
158
+ createMissingRepos?: boolean;
159
+ sync?: boolean;
160
+ providers?: ProvidersDto;
161
+ restoreWorksConfig?: boolean;
162
+ enrichmentConfig?: ImportEnrichmentConfig;
163
+ }
164
+
165
+ /**
166
+ * App Works — the Upstream model: fork readiness, Actions hygiene, upstream
167
+ * sync, divergence, and the closed reason-code sets the Upstream card, a test
168
+ * id and a translation key are all derived from.
169
+ *
170
+ * Owning epic: **APW-02** (Fork lifecycle — readiness, Actions hygiene, upstream
171
+ * sync, divergence, checkout keys).
172
+ *
173
+ * Spec: `docs/specs/features/app-works/APW-02-fork-lifecycle/spec.md`
174
+ * Plan: `docs/specs/features/app-works/APW-02-fork-lifecycle/plan.md` §3.4
175
+ * Tasks: `APW-02-fork-lifecycle/tasks.md` T50 (the three closed sets)
176
+ * Bindings: `CONTRACTS.md` §0 (R-8, R-14, R-21), §2, §4 (job table).
177
+ *
178
+ * FR-65 is the reason this file exists: readiness reasons, sync results and
179
+ * warning codes must each be a **closed set with one stable value per
180
+ * user-visible state**, and a provider-specific failure must be reported through
181
+ * the typed provider reason rather than a composed `handler_failed:<code>`
182
+ * string.
183
+ */
184
+
185
+ /**
186
+ * The five readiness states (plan.md:353, data-model.md:105, spec.md:455-460).
187
+ *
188
+ * `waiting_for_setup_pr` is a normal resting state, not a failure: a linked
189
+ * repository and an adopted fork always pass through it (R-4).
190
+ */
191
+ declare const APP_READINESS_STATES: readonly ["preparing", "ready", "timed_out", "failed", "waiting_for_setup_pr"];
192
+ /** Union derived from {@link APP_READINESS_STATES}. */
193
+ type AppReadinessState = (typeof APP_READINESS_STATES)[number];
194
+ /**
195
+ * The eight coarse outcomes a sync run can end in (plan.md:354-363), reported as
196
+ * `sync.lastResult`.
197
+ *
198
+ * Kept alongside {@link APP_SYNC_REASONS} rather than replaced by it: the plan
199
+ * fixes this set, T50 adds a finer one, and nothing is ever removed (R-26).
200
+ */
201
+ declare const APP_SYNC_RESULTS: readonly ["up_to_date", "fast_forwarded", "pull_request_opened", "pull_request_updated", "conflict", "skipped", "paused", "failed"];
202
+ /** Union derived from {@link APP_SYNC_RESULTS}. */
203
+ type AppSyncResult = (typeof APP_SYNC_RESULTS)[number];
204
+ /**
205
+ * The fifteen fine-grained sync reasons (tasks.md:739-742), reported as
206
+ * `sync.lastReason` and written by the sync service — never a composed string.
207
+ */
208
+ declare const APP_SYNC_REASONS: readonly ["up_to_date", "fast_forwarded", "pull_request_opened", "pull_request_updated", "pull_request_merged", "pull_request_closed", "conflict", "held_for_workflow_review", "skipped_rate_limited", "skipped_budget", "license_worse", "disabled_by_spec", "paused", "provider_unsupported", "failed"];
209
+ /** Union derived from {@link APP_SYNC_REASONS}. */
210
+ type AppSyncReason = (typeof APP_SYNC_REASONS)[number];
211
+ /**
212
+ * The ten readiness failure reasons (tasks.md:737-738) — one member per
213
+ * user-visible state, written by the readiness handler and surfaced as
214
+ * `readiness.reason`.
215
+ *
216
+ * `setup_pull_request_closed` (spec.md:309) and `access_revoked` (spec.md:295)
217
+ * are the two the spec names directly; a provider failure is reported through
218
+ * {@link AppReadinessHandlerReason}, never through a composed member.
219
+ */
220
+ declare const APP_READINESS_FAILURE_REASONS: readonly ["access_revoked", "dispatch_unavailable", "copy_refused", "too_large", "provider_unsupported", "timed_out", "setup_pull_request_closed", "handler_failed", "blueprint_apply_failed", "data_repository_missing"];
221
+ /** Union derived from {@link APP_READINESS_FAILURE_REASONS}. */
222
+ type AppReadinessFailureReason = (typeof APP_READINESS_FAILURE_REASONS)[number];
223
+ /**
224
+ * The warning codes of spec §6.2, camelCased (spec.md:519-534, tasks.md:742-743).
225
+ *
226
+ * One member per table row, in table order. The task text says "the ten spec
227
+ * §6.2 rows" while the table has twelve; the table is the source and dropping
228
+ * the two extra rows would be a removal (R-26), so all twelve are here.
229
+ */
230
+ declare const APP_UPSTREAM_WARNING_CODES: readonly ["upstreamArchived", "upstreamUnavailable", "forkMissing", "privateCopyMissing", "rateLimited", "defaultBranchRenamed", "privateCopyTooLarge", "historyRewritten", "needsAdmin", "appPermissionMissing", "notReady", "workflowsGated"];
231
+ /** Union derived from {@link APP_UPSTREAM_WARNING_CODES}. */
232
+ type AppUpstreamWarningCode = (typeof APP_UPSTREAM_WARNING_CODES)[number];
233
+ /**
234
+ * The upstream's own health (plan.md:364), derived from a provider read and
235
+ * cached in the Upstream state row.
236
+ */
237
+ declare const APP_UPSTREAM_STATUSES: readonly ["available", "archived", "unavailable", "none", "unknown"];
238
+ /** Union derived from {@link APP_UPSTREAM_STATUSES}. */
239
+ type AppUpstreamStatus = (typeof APP_UPSTREAM_STATUSES)[number];
240
+ /**
241
+ * The Actions hygiene outcome (plan.md:365-372).
242
+ *
243
+ * `needs_admin` and `permission_missing` are named states that must NOT block
244
+ * readiness or sync (FR-30); `not_applicable` is a linked repository, which
245
+ * hygiene never touches (FR-31).
246
+ */
247
+ declare const APP_ACTIONS_STATES: readonly ["pending", "clean", "needs_admin", "permission_missing", "failed", "not_applicable"];
248
+ /** Union derived from {@link APP_ACTIONS_STATES}. */
249
+ type AppActionsState = (typeof APP_ACTIONS_STATES)[number];
250
+ /** Why a readiness job was dispatched (plan.md:433). */
251
+ declare const APP_FORK_READINESS_REASONS: readonly ["initial", "retry", "redispatch", "setup_merged"];
252
+ /** Union derived from {@link APP_FORK_READINESS_REASONS}. */
253
+ type AppForkReadinessReason = (typeof APP_FORK_READINESS_REASONS)[number];
254
+ /** The Work Repository as the Upstream card reports it (plan.md:376-382). */
255
+ interface AppUpstreamWorkRepositoryView {
256
+ owner: string;
257
+ repo: string;
258
+ url: string;
259
+ defaultBranch: string;
260
+ /** `missing` is the FR-42 state: every background job stops and says so. */
261
+ status: 'available' | 'missing';
262
+ }
263
+ /** The upstream as the Upstream card reports it (plan.md:383-390). */
264
+ interface AppUpstreamView {
265
+ owner: string;
266
+ repo: string;
267
+ url: string;
268
+ defaultBranch: string;
269
+ /** Set when upstream renamed its default branch and sync followed it (FR-43). */
270
+ previousDefaultBranch?: string;
271
+ status: AppUpstreamStatus;
272
+ }
273
+ /**
274
+ * The readiness block of the Upstream response (plan.md:391-399 + tasks.md:743).
275
+ *
276
+ * `manualRetriesLeft` counts FR-19's 3-per-hour **Try again** allowance;
277
+ * `handlerReason` carries the typed provider refusal (reason and the single
278
+ * permission it needs, FR-54) instead of a composed string.
279
+ */
280
+ interface AppUpstreamReadinessView {
281
+ state: AppReadinessState;
282
+ reason?: AppReadinessFailureReason;
283
+ handlerReason?: AppReadinessHandlerReason;
284
+ startedAt: string;
285
+ readyAt?: string;
286
+ setupPullRequestUrl?: string;
287
+ setupPullRequestNumber?: number;
288
+ manualRetriesLeft: number;
289
+ }
290
+ /**
291
+ * A typed provider refusal (tasks.md:743-745, FR-54).
292
+ *
293
+ * `code` is the provider's own reason, not a closed App Works set: the platform
294
+ * layer already owns that union, and restating it here would give it two
295
+ * definitions.
296
+ */
297
+ interface AppReadinessHandlerReason {
298
+ code: string;
299
+ permission?: string;
300
+ }
301
+ /** Commits ahead of and behind upstream, with when they were read (plan.md:400, FR-46/FR-47). */
302
+ interface AppUpstreamDivergenceView {
303
+ aheadBy: number;
304
+ behindBy: number;
305
+ computedAt: string;
306
+ stale: boolean;
307
+ }
308
+ /** The sync block of the Upstream response (plan.md:401-415). */
309
+ interface AppUpstreamSyncView {
310
+ /** The App spec's five-field cron, or `null` when none is configured. */
311
+ schedule: string | null;
312
+ nextRunAt?: string;
313
+ running: boolean;
314
+ lastResult?: AppSyncResult;
315
+ lastReason?: AppSyncReason;
316
+ lastStartedAt?: string;
317
+ lastFinishedAt?: string;
318
+ lastCommitCount?: number;
319
+ pullRequest?: {
320
+ number: number;
321
+ url: string;
322
+ };
323
+ /** The one open conflict Task, reused rather than duplicated (FR-38). */
324
+ conflictTaskId?: string;
325
+ manualSyncsLeft: number;
326
+ rateLimitedUntil?: string;
327
+ rateLimitedPersistent: boolean;
328
+ }
329
+ /** The Actions hygiene block of the Upstream response (plan.md:416-421). */
330
+ interface AppUpstreamActionsView {
331
+ state: AppActionsState;
332
+ disabled: Array<{
333
+ path: string;
334
+ }>;
335
+ kept: Array<{
336
+ path: string;
337
+ }>;
338
+ checkedAt?: string;
339
+ }
340
+ /** One warning, with its code and the parameters its copy interpolates (FR-65). */
341
+ interface AppUpstreamWarning {
342
+ code: AppUpstreamWarningCode;
343
+ params?: Record<string, string>;
344
+ }
345
+ /**
346
+ * `GET /api/works/:id/upstream` (plan.md:373-423, resolution R-8).
347
+ *
348
+ * `relation` reuses APW-01's mode union rather than restating the same three
349
+ * values. `upstream` and `sync` are `null` for a linked App Work, which has no
350
+ * upstream at all (FR-44).
351
+ */
352
+ interface AppUpstreamStateResponse {
353
+ workId: string;
354
+ relation: AppRepositoryMode;
355
+ dataRepository: AppUpstreamWorkRepositoryView;
356
+ upstream: AppUpstreamView | null;
357
+ readiness: AppUpstreamReadinessView;
358
+ divergence: AppUpstreamDivergenceView | null;
359
+ sync: AppUpstreamSyncView | null;
360
+ actions: AppUpstreamActionsView | null;
361
+ warnings: AppUpstreamWarning[];
362
+ }
363
+ /** The probe schedule after the request: 2, 4, 8 and 15 seconds (FR-18, spec.md:288). */
364
+ declare const APP_FORK_READINESS_POLL_DELAYS_MS: readonly [2000, 4000, 8000, 15000];
365
+ /** Then every 15 seconds until the deadline (FR-18, spec.md:288-289). */
366
+ declare const APP_FORK_READINESS_POLL_INTERVAL_MS = 15000;
367
+ /** At most 15 minutes of checking, then **timed out** with one Activity entry (FR-18, spec.md:289). */
368
+ declare const APP_FORK_READINESS_TIMEOUT_MS = 900000;
369
+ /** The p95 target for a fork becoming ready (plan.md:427). */
370
+ declare const APP_FORK_READINESS_READY_LATENCY_MS = 30000;
371
+ /** **Try again** is limited to 3 per App Work per hour (FR-19, spec.md:293-294). */
372
+ declare const APP_FORK_READINESS_MANUAL_RETRIES_PER_HOUR = 3;
373
+ /** A readiness job that never reported for 10 minutes is restarted, at most 3 times (FR-23, spec.md:302-303). */
374
+ declare const APP_FORK_READINESS_MAX_REDISPATCH = 3;
375
+ /** A job that was never started or stopped reporting for 10 minutes is stale (FR-23, spec.md:302). */
376
+ declare const APP_FORK_READINESS_IDLE_MS = 600000;
377
+ /**
378
+ * The floor a non-production installation may shorten the deadline to —
379
+ * **never** applied in production, which always uses the 15 minutes (FR-18a,
380
+ * spec.md:290-292).
381
+ */
382
+ declare const APP_FORK_READINESS_TIMEOUT_OVERRIDE_MIN_MS = 5000;
383
+ /** The environment variable that carries the non-production override (FR-18a). */
384
+ declare const APP_FORK_READINESS_TIMEOUT_ENV = "EVER_WORKS_APP_FORK_READINESS_TIMEOUT_MS";
385
+ /** An open setup pull request is checked at least every 10 minutes (FR-24a, spec.md:306-307). */
386
+ declare const APP_SETUP_PR_CHECK_ON_VIEW_MIN_INTERVAL_MS = 60000;
387
+ /** …and within 60 seconds of the App Work being viewed; at most this many per tick (FR-24a, CONTRACTS.md:480). */
388
+ declare const APP_SETUP_PR_CHECK_BATCH = 50;
389
+ /** Mondays at 06:00 UTC when the App spec declares no schedule (FR-32, spec.md:329-330). */
390
+ declare const APP_UPSTREAM_SYNC_DEFAULT_SCHEDULE = "0 6 * * 1";
391
+ /** A schedule firing more often than once an hour is treated as hourly (FR-32, spec.md:329-330). */
392
+ declare const APP_UPSTREAM_SYNC_MIN_INTERVAL_MS = 3600000;
393
+ /** Each App Work's run is delayed by a stable 0–300 seconds (FR-32, spec.md:330-331). */
394
+ declare const APP_UPSTREAM_SYNC_JITTER_MAX_MS = 300000;
395
+ /** **Sync now** is limited to 6 per App Work per hour (FR-33, spec.md:332-333). */
396
+ declare const APP_UPSTREAM_SYNC_MANUAL_PER_HOUR = 6;
397
+ /** **Sync now** answers within 2 seconds without waiting (FR-33, spec.md:332). */
398
+ declare const APP_UPSTREAM_SYNC_ACK_BUDGET_MS = 2000;
399
+ /** At most one sync runs per App Work at a time — the lock TTL (FR-34, spec.md:334). */
400
+ declare const APP_UPSTREAM_SYNC_LOCK_TTL_MS = 1800000;
401
+ /** The dispatcher tick, every 10 minutes (CONTRACTS.md:480). */
402
+ declare const APP_UPSTREAM_SYNC_DISPATCH_CRON = "*/10 * * * *";
403
+ /** At most 50 syncs per 10-minute tick (FR-53, spec.md:379). */
404
+ declare const APP_UPSTREAM_SYNC_DISPATCH_BATCH = 50;
405
+ /** One sync makes at most 20 provider calls (FR-49, spec.md:373). */
406
+ declare const APP_UPSTREAM_SYNC_MAX_PROVIDER_CALLS = 20;
407
+ /** The branch a sync pull request comes from (FR-36, spec.md:340-342). */
408
+ declare const APP_UPSTREAM_SYNC_BRANCH = "ever-works/upstream-sync";
409
+ /** The conflict Task's label prefix, one open Task per App Work (FR-38, spec.md:345-346). */
410
+ declare const APP_UPSTREAM_CONFLICT_LABEL_PREFIX = "app-upstream-conflict:";
411
+ /** Up to 50 conflicting paths are listed in the conflict Task (FR-38, spec.md:346). */
412
+ declare const APP_UPSTREAM_CONFLICT_MAX_PATHS = 50;
413
+ /** Hygiene is capped at 100 workflows per run, and records at most 100 kept and 100 disabled (FR-28/FR-29). */
414
+ declare const APP_ACTIONS_HYGIENE_MAX_WORKFLOWS = 100;
415
+ /** Fewer than 300 requests left in the member's budget skips the run until the reset plus 60 s (FR-50, spec.md:374-375). */
416
+ declare const APP_RATE_LIMIT_MIN_REMAINING = 300;
417
+ /** The grace period added to the provider's reset time (FR-50, spec.md:374-375). */
418
+ declare const APP_RATE_LIMIT_RESET_GRACE_MS = 60000;
419
+ /** Secondary rate limits back off starting at 60 seconds (FR-51, spec.md:376-377). */
420
+ declare const APP_RATE_LIMIT_BACKOFF_BASE_MS = 60000;
421
+ /** …doubling to at most 60 minutes (FR-51, spec.md:377). */
422
+ declare const APP_RATE_LIMIT_BACKOFF_MAX_MS = 3600000;
423
+ /** Three consecutive rate-limited runs make the notice persistent (FR-52, spec.md:378). */
424
+ declare const APP_RATE_LIMITED_PERSISTENT_AFTER = 3;
425
+ /** Divergence counts are refreshed when the App Work is viewed and they are older than 10 minutes (FR-46). */
426
+ declare const APP_DIVERGENCE_TTL_MS = 600000;
427
+ /** …and at least once a day (FR-46, spec.md:364-365). */
428
+ declare const APP_DIVERGENCE_DAILY_MS = 86400000;
429
+ /** "Upstream behind" is emitted when behind grows by 25 or more since the last emission (FR-48, spec.md:368-369). */
430
+ declare const APP_BEHIND_EVENT_STEP = 25;
431
+ /** An unreadable upstream is re-checked every 24 hours (FR-41, spec.md:354-355). */
432
+ declare const APP_UPSTREAM_UNAVAILABLE_RECHECK_MS = 86400000;
433
+ /**
434
+ * Why APW-03's license gate is asked to re-evaluate an App Work —
435
+ * `AppLicenseService.request(workId, reason)`.
436
+ *
437
+ * Added by **APW-02 T26**, whose task text fixes the contract: "`AppLicenseService.request(workId,
438
+ * reason)` gains its reason union in CONTRACTS §2A as part of this task's PR". The union did not
439
+ * exist anywhere in this package, and it is declared here — in APW-02's own Upstream module, beside
440
+ * the sync limits that produce two of its three members — rather than in a second file, so
441
+ * `AppLicenseService` has exactly one reason vocabulary.
442
+ *
443
+ * Members, and the caller each one comes from:
444
+ *
445
+ * - `upstream_synced` — APW-02 §6.3 step 8 / FR-40: a sync moved the tracked branch
446
+ * (`APW-02/plan.md:751-752`, status service `app-upstream-state.service.ts:989`).
447
+ * - `upstream_merged` — APW-02 FR-62 / T29: a sync pull request was merged, so the license is asked
448
+ * once more for the range that landed (`APW-02/tasks.md:719`).
449
+ * - `blueprint_applied` — APW-03 §2.5 step 0: a Blueprint was applied and its `license` block may
450
+ * have changed the classification (`APW-03/plan.md:286`).
451
+ *
452
+ * APW-03 appends its own triggers (registry refresh, manual re-check, header evidence —
453
+ * `CONTRACTS.md:487`) to this list when its job lands: the union is **append-only** (R-26), and a
454
+ * caller that switches exhaustively over it gains a compile error rather than a silent default.
455
+ */
456
+ declare const APP_LICENSE_EVALUATION_REASONS: readonly ["upstream_synced", "upstream_merged", "blueprint_applied"];
457
+ /** Union derived from {@link APP_LICENSE_EVALUATION_REASONS}. */
458
+ type AppLicenseEvaluationReason = (typeof APP_LICENSE_EVALUATION_REASONS)[number];
459
+ /**
460
+ * Whether a manual **Sync now** may start, given how many ran in the current
461
+ * hour — `at most 6`, so the seventh is refused (FR-33).
462
+ *
463
+ * Fails closed on anything that is not a non-negative count.
464
+ */
465
+ declare function appManualSyncAllowed(manualSyncsThisHour: number): boolean;
466
+ /**
467
+ * Whether the member's remaining provider budget lets a run start — FR-50 says
468
+ * "fewer than 300 remaining", so exactly 300 still runs.
469
+ *
470
+ * Fails closed on an unknown budget.
471
+ */
472
+ declare function appRateLimitAllowsSync(remainingRequests: number): boolean;
473
+
474
+ /**
475
+ * App Works — the App source model: how an App Work relates to the repository
476
+ * it was made from, plus the inspect (preview) and create contracts both doors
477
+ * share.
478
+ *
479
+ * Owning epic: **APW-01** (App Work kind & create from any repository URL).
480
+ * The persisted source record and the App spec's `source` block are APW-01's
481
+ * (CONTRACTS.md §1 `source`, §2, §2A), so they live here and APW-03/04/09/11
482
+ * read them rather than restating them.
483
+ *
484
+ * Spec: `docs/specs/features/app-works/APW-01-app-work-kind/spec.md`
485
+ * Plan: `docs/specs/features/app-works/APW-01-app-work-kind/plan.md` §3.2
486
+ * Bindings: `docs/specs/features/app-works/CONTRACTS.md` §0 (R-1, R-2, R-12),
487
+ * §2, §2A, §7A, §12.
488
+ *
489
+ * Three things this file deliberately does NOT do:
490
+ * - it does not redeclare `RepositoryRole`, `RelatedRepositories`,
491
+ * `ImportSourceType` or `SourceRepository` — they already ship in
492
+ * `../api/work/import-source.dto.ts` and are imported here;
493
+ * - it does not widen `IMPORT_SOURCE_TYPES` (Work Import validates against it,
494
+ * CONTRACTS.md §2) — the `app_*` types are a separate closed set;
495
+ * - it declares no canonical App-spec type (`LicenseClass`,
496
+ * `BlueprintMatchSource`, `AppSpec` …): those are APW-03's, and the preview
497
+ * subsets here carry source-prefixed names on purpose so the apps barrel can
498
+ * never see the same export twice.
499
+ */
500
+
501
+ /**
502
+ * The persisted `works.sourceRepository.type` values an App Work may carry
503
+ * (APW-01 plan.md:293, CONTRACTS.md:266).
504
+ *
505
+ * A new constant on purpose: `IMPORT_SOURCE_TYPES` is **not** widened, because
506
+ * Work Import validates against it and an imported entry must never become an
507
+ * App Work (APW-01 FR-54).
508
+ */
509
+ declare const APP_SOURCE_REPOSITORY_TYPES: readonly ["app_link", "app_fork", "app_private_copy"];
510
+ /** Union derived from {@link APP_SOURCE_REPOSITORY_TYPES}. */
511
+ type AppSourceRepositoryType = (typeof APP_SOURCE_REPOSITORY_TYPES)[number];
512
+ /**
513
+ * The upstream a fork or private copy follows (APW-01 plan.md:295-299).
514
+ *
515
+ * This is the **persisted** shape (`{ owner, repo }`); the App spec's own
516
+ * `source.upstream.repo` is the single `owner/name` string — see
517
+ * {@link AppSourceBlock}.
518
+ */
519
+ interface AppUpstreamRef {
520
+ owner: string;
521
+ repo: string;
522
+ defaultBranch: string;
523
+ }
524
+ /**
525
+ * The role the App Work's code repository is persisted under — **`website`**,
526
+ * whose UI label is literally "Work Repository" (APW-01 FR-2, CONTRACTS.md
527
+ * §2 vocabulary fix). It is never `data`: `data` holds the Work's *content*.
528
+ *
529
+ * Reused from the shipping DTO rather than redeclared, so the two cannot drift.
530
+ */
531
+ declare const APP_WORK_REPOSITORY_ROLE: RepositoryRole;
532
+ /**
533
+ * The relation (mode) the member chose, as every API surface spells it
534
+ * (APW-01 plan.md:325; openapi `AppWorkCreateRequest.repositoryMode`).
535
+ *
536
+ * The nine deploy-target literals of R-12 are the *other* axis; this one is
537
+ * "how did we get a Work Repository".
538
+ */
539
+ declare const APP_REPOSITORY_MODES: readonly ["link", "fork", "private-copy"];
540
+ /** Union derived from {@link APP_REPOSITORY_MODES}. */
541
+ type AppRepositoryMode = (typeof APP_REPOSITORY_MODES)[number];
542
+ /**
543
+ * Mode → persisted source type (CONTRACTS.md:266). One entry per mode and no
544
+ * value twice, so a reader can never map two modes onto one record.
545
+ */
546
+ declare const APP_SOURCE_REPOSITORY_TYPE_BY_MODE: Readonly<Record<AppRepositoryMode, AppSourceRepositoryType>>;
547
+ /**
548
+ * The Work Repository name suffixes (APW-01 FR-20a, spec.md:341-349).
549
+ *
550
+ * `-app` when the App Work was created from an app template, `-website`
551
+ * otherwise — the unchanged default for Website/Work Templates and for every
552
+ * non-`app` kind. A naming convention ONLY: the persisted role stays
553
+ * {@link APP_WORK_REPOSITORY_ROLE} and no new role value is added.
554
+ */
555
+ declare const APP_SOURCE_REPOSITORY_NAME_SUFFIXES: {
556
+ readonly app: "-app";
557
+ readonly default: "-website";
558
+ };
559
+ /** The Work Repository file that carries the App spec (APW-01 FR-29, spec.md:374). */
560
+ declare const APP_SOURCE_SPEC_FILE = ".works/works.yml";
561
+ /** The spec version an App Work records — `.works/works.yml` version 2 (spec.md:374). */
562
+ declare const APP_SOURCE_SPEC_VERSION = 2;
563
+ /** The kind discriminator an App Work records (spec.md:375). */
564
+ declare const APP_SOURCE_SPEC_KIND = "app";
565
+ /**
566
+ * The App spec's `source` block as written into the Work Repository
567
+ * (APW-01 FR-29, CONTRACTS.md:102-105, APW-03 schema.md §5).
568
+ *
569
+ * Field names are the schema's, not this file's: `upstream.repo` is the single
570
+ * `owner/name` string, and `branch` is the Work Repository branch that is built
571
+ * and deployed. `relation` must equal the relation recorded at creation
572
+ * (`source_relation_mismatch`, schema.md:119-120) — a hand edit cannot turn a
573
+ * fork into a link.
574
+ */
575
+ interface AppSourceBlock {
576
+ /** `link` · `fork` · `private-copy` (schema.md:114). */
577
+ relation: AppRepositoryMode;
578
+ /** Absent when `relation` is `link`, which forbids it (schema.md:115, R13). */
579
+ upstream?: {
580
+ /** `owner/name`, matching `^[A-Za-z0-9-]{1,39}/[A-Za-z0-9._-]{1,100}$`. */
581
+ repo: string;
582
+ /** Upstream's default branch at creation; a Git ref name, 1–255 chars. */
583
+ defaultBranch?: string;
584
+ };
585
+ /** The Work Repository branch that is built and deployed; 1–255 chars. */
586
+ branch?: string;
587
+ }
588
+ /**
589
+ * `works.sourceRepository` for `kind: app` (APW-01 plan.md:240).
590
+ *
591
+ * Extends the shipping {@link SourceRepository} so the shared fields
592
+ * (`url`, `owner`, `repo`, `importedAt`, `relatedRepositories`) keep exactly one
593
+ * definition; `type` is narrowed to the three `app_*` values. Top-level
594
+ * `owner`/`repo` are the **Work Repository** (the `website` role) — the app-code
595
+ * fork is recorded there, never under `data` (CONTRACTS.md:267).
596
+ *
597
+ * `worksConfig` is inherited from the shared shape and is deliberately kept:
598
+ * FR-43 forbids *writing* generator settings into an App Work's file, and
599
+ * removing the field would narrow a shape other readers still type against.
600
+ */
601
+ interface AppSourceRecord<TImportedAt = string> extends Omit<SourceRepository<TImportedAt>, 'type'> {
602
+ type: AppSourceRepositoryType;
603
+ /** Present for `fork` and `private-copy`; absent for `link`. */
604
+ upstream?: AppUpstreamRef;
605
+ /** The Blueprint resolved server-side at create time (APW-01 FR-29b). */
606
+ blueprintId?: string;
607
+ /** How that Blueprint was matched, so every caller sees the same decision. */
608
+ blueprintMatchSource?: AppSourceBlueprintMatchSource;
609
+ /** True only when THIS creation issued the fork request or made the copy (R-4). */
610
+ createdByThisWork?: boolean;
611
+ /**
612
+ * The member's decline of FR-29a's automatic start (App spec plan.md:240,
613
+ * APW-01 plan.md §3.1, §4.2 step 10).
614
+ *
615
+ * **Written only when the member declined**, so an absent property means "on":
616
+ * no migration, no backfill, and no existing caller or stored row changes
617
+ * meaning. It is what `AppSourceInitializerService` step 8 reads to skip the
618
+ * automatic provisioning start, leaving the Overview's Provisioning card in its
619
+ * **Not started** state with a **Provision** button instead. It is never cleared
620
+ * automatically.
621
+ *
622
+ * `boolean` rather than the literal `false` so a future "explicitly on" value is
623
+ * expressible without changing this shape (R-26, additive only).
624
+ */
625
+ autoProvision?: boolean;
626
+ }
627
+ /**
628
+ * The value `SourceRepository.type` accepts once APW-01's widening lands
629
+ * (plan.md:310). Declared here so that edit — which belongs to
630
+ * `../api/work/import-source.dto.ts`, not to this file — has one name to import.
631
+ */
632
+ type WorkSourceRepositoryType = ImportSourceType | AppSourceRepositoryType;
633
+ /** Re-exported for readers of an App source record; the DTO is the definition. */
634
+ type AppSourceRelatedRepositories = RelatedRepositories;
635
+ /**
636
+ * The three deploy targets, and the ONLY definition of them
637
+ * (CONTRACTS.md:335): APW-06 imports and re-exports this as
638
+ * `APP_DEPLOY_TARGETS` instead of writing a second array.
639
+ *
640
+ * `none` is "None — don't deploy yet" and is the default; there is no separate
641
+ * deferred-deploy state (R-12, CONTRACTS.md:55).
642
+ */
643
+ declare const APP_DEPLOY_TARGET_CHOICES: readonly ["none", "your-cluster", "ever-works-apps"];
644
+ /** Union derived from {@link APP_DEPLOY_TARGET_CHOICES}. */
645
+ type AppDeployTargetChoice = (typeof APP_DEPLOY_TARGET_CHOICES)[number];
646
+ /**
647
+ * The closed set of user-facing inspect and create reason codes — the 24 rows of
648
+ * APW-01 spec §6.3 (spec.md:606-633), in table order. Append-only: a member is
649
+ * never renamed or removed, and a code is never reused for another situation
650
+ * (CONTRACTS.md §12).
651
+ */
652
+ declare const APP_SOURCE_REASON_CODES: readonly ["invalid_url", "provider_not_connected", "insufficient_scope", "not_found", "sso_authorization_required", "oauth_app_restricted", "empty_repository", "no_push_access", "archived", "forking_disabled", "own_repository", "target_owner_unavailable", "target_owner_forbidden", "too_large_for_private_copy", "uses_lfs", "copy_name_unavailable", "in_use_by_another_account", "app_work_exists", "create_in_progress", "rate_limited", "managed_hosting_unavailable", "cluster_target_unavailable", "app_works_disabled", "blueprint_mismatch"];
653
+ /** Union derived from {@link APP_SOURCE_REASON_CODES}. */
654
+ type AppSourceReasonCode = (typeof APP_SOURCE_REASON_CODES)[number];
655
+ /**
656
+ * Fail-closed guard for a reason code arriving off the wire, out of a job
657
+ * payload or out of a test fixture: anything that is not a member is `false`,
658
+ * never a coerced string.
659
+ */
660
+ declare function isAppSourceReasonCode(value: unknown): value is AppSourceReasonCode;
661
+ /**
662
+ * Whether a mode or a deploy target is offered, and — when it is not — the ONE
663
+ * stable code that explains it (APW-01 FR-5, FR-12, FR-33).
664
+ *
665
+ * `reason` is absent exactly when `available` is true, so a disabled option
666
+ * always has text a card, a test id and a translation key can be derived from.
667
+ */
668
+ interface AppModeAvailability {
669
+ available: boolean;
670
+ reason?: AppSourceReasonCode;
671
+ }
672
+ /**
673
+ * A deploy target's availability (APW-01 FR-33/FR-34, tasks.md:82-83).
674
+ *
675
+ * `providerId` is set only when the target is available **and** is not `none`
676
+ * — it is the plugin the create request persists, from which APW-06 derives the
677
+ * runtime's target exactly once (FR-34).
678
+ */
679
+ interface AppDeployTargetAvailability extends AppModeAvailability {
680
+ providerId?: string;
681
+ }
682
+ /** The three states a Blueprint preview can be in (plan.md:396, openapi:228). */
683
+ declare const APP_SOURCE_BLUEPRINT_STATUSES: readonly ["matched", "none", "unavailable"];
684
+ /** Union derived from {@link APP_SOURCE_BLUEPRINT_STATUSES}. */
685
+ type AppSourceBlueprintStatus = (typeof APP_SOURCE_BLUEPRINT_STATUSES)[number];
686
+ /**
687
+ * How the Blueprint was matched (APW-01 plan.md:240).
688
+ *
689
+ * APW-03 owns the canonical `BlueprintMatchSource` (CONTRACTS.md §2A); this is
690
+ * the source record's spelling of the same five members and carries the prefix
691
+ * so the apps barrel never re-exports one name twice.
692
+ */
693
+ declare const APP_SOURCE_BLUEPRINT_MATCH_SOURCES: readonly ["manifest", "alias", "fork", "probe", "explicit"];
694
+ /** Union derived from {@link APP_SOURCE_BLUEPRINT_MATCH_SOURCES}. */
695
+ type AppSourceBlueprintMatchSource = (typeof APP_SOURCE_BLUEPRINT_MATCH_SOURCES)[number];
696
+ /**
697
+ * One prompted value a Blueprint asks for (APW-01 FR-55, tasks.md:85).
698
+ *
699
+ * **Never a value**: the preview shows the name, the description and whether
700
+ * the value is required; the member's answers travel write-only on the create
701
+ * request and are never echoed by any read.
702
+ */
703
+ interface AppBlueprintPrompt {
704
+ name: string;
705
+ description?: string;
706
+ required: boolean;
707
+ }
708
+ /** The Blueprint the create preview shows and the platform settles server-side. */
709
+ interface AppBlueprintPreview {
710
+ status: AppSourceBlueprintStatus;
711
+ id?: string;
712
+ version?: string;
713
+ verified?: boolean;
714
+ /** Display name, shown when present (APW-01 tasks.md:778). */
715
+ name?: string;
716
+ /** The entry's trademark notice, shown when present (APW-01 tasks.md:778). */
717
+ notice?: string;
718
+ matchSource?: AppSourceBlueprintMatchSource;
719
+ prompts?: AppBlueprintPrompt[];
720
+ }
721
+ /**
722
+ * The four license classes (APW-01 FR-8, R-3 in CONTRACTS.md:46).
723
+ *
724
+ * `unknown` is a first-class answer, never a guessed class: when the lookup is
725
+ * unavailable inspect still answers, with the license marked unknown.
726
+ */
727
+ declare const APP_SOURCE_LICENSE_CLASSES: readonly ["green", "amber", "red", "unknown"];
728
+ /** Union derived from {@link APP_SOURCE_LICENSE_CLASSES}. */
729
+ type AppSourceLicenseClass = (typeof APP_SOURCE_LICENSE_CLASSES)[number];
730
+ /** The three evidence sources of the App spec's `license` block (APW-03 schema.md:143). */
731
+ declare const APP_SOURCE_LICENSE_SOURCES: readonly ["detected", "blueprint", "user"];
732
+ /** Union derived from {@link APP_SOURCE_LICENSE_SOURCES}. */
733
+ type AppSourceLicenseSource = (typeof APP_SOURCE_LICENSE_SOURCES)[number];
734
+ /**
735
+ * The license preview inspect returns (plan.md:402).
736
+ *
737
+ * `source` cannot be `user` here: nothing is persisted before create, so the
738
+ * only evidence available is what was detected or what the Blueprint declares.
739
+ */
740
+ interface AppSourceLicensePreview {
741
+ spdx: string | null;
742
+ class: AppSourceLicenseClass;
743
+ source: Exclude<AppSourceLicenseSource, 'user'>;
744
+ }
745
+ /** What inspect is asked for (openapi `AppSourceInspectRequest`). */
746
+ interface AppSourceInspectRequest {
747
+ /** GitHub repository URL; trimmed before parsing, at most 400 characters (FR-6). */
748
+ repositoryUrl: string;
749
+ /** Validated against the URL parser's host rules, not a literal list. */
750
+ gitProvider?: string;
751
+ /**
752
+ * A catalog id. When sent, the resolver previews exactly that entry; when it
753
+ * does not match the repository, create answers `blueprint_mismatch`
754
+ * (APW-01 FR-56).
755
+ */
756
+ blueprintId?: string;
757
+ }
758
+ /**
759
+ * One owner the caller can fork into, with the state of its existing-fork check
760
+ * (APW-01 FR-9, plan.md:192-194).
761
+ *
762
+ * `existingForkChecked` is REQUIRED: an owner the 15-call budget did not reach
763
+ * keeps its computed `available`, carries **no** reason code and is reported as
764
+ * not checked — never as "no fork". Creating into it still adopts a fork that
765
+ * exists there (FR-19).
766
+ */
767
+ interface AppTargetOwner {
768
+ login: string;
769
+ type: 'user' | 'organization';
770
+ available: boolean;
771
+ reason?: AppSourceReasonCode;
772
+ /** Present only when the scan reached this owner and found a fork. */
773
+ existingFork?: {
774
+ owner: string;
775
+ repo: string;
776
+ fullName: string;
777
+ url: string;
778
+ inUseByAnotherAccount: boolean;
779
+ };
780
+ existingForkChecked: boolean;
781
+ }
782
+ /**
783
+ * The inspection result (plan.md:371-406; openapi `AppSourceInspectResponse`).
784
+ *
785
+ * Inspect writes nothing: no repository, no row, no Activity, no file (FR-5),
786
+ * which is why a provider-side refusal still answers 200 with every mode marked
787
+ * unavailable and a classified reason.
788
+ */
789
+ interface AppSourceInspectResponse {
790
+ repository: {
791
+ owner: string;
792
+ repo: string;
793
+ fullName: string;
794
+ url: string;
795
+ description?: string;
796
+ defaultBranch: string;
797
+ stars: number;
798
+ sizeKb: number;
799
+ visibility: 'public' | 'private' | 'internal';
800
+ archived: boolean;
801
+ empty: boolean;
802
+ isFork: boolean;
803
+ /** The immediate parent, when the repository is a fork. */
804
+ parent?: string;
805
+ /** The fork network's root, when the provider reports one. */
806
+ source?: string;
807
+ allowForking: boolean;
808
+ /** Set when the repository moved; the old coordinates (APW-02 FR-15). */
809
+ movedFrom?: string;
810
+ usesLfs: boolean;
811
+ };
812
+ access: {
813
+ canPush: boolean;
814
+ canAdmin: boolean;
815
+ };
816
+ modes: Record<AppRepositoryMode, AppModeAvailability>;
817
+ /** `null` when neither Link nor Fork is available. */
818
+ defaultMode: AppRepositoryMode | null;
819
+ /** The caller first, then the offered organizations A–Z (≤ 30 in P1, ≤ 200 in P2). */
820
+ targetOwners: AppTargetOwner[];
821
+ blueprint: AppBlueprintPreview;
822
+ /** `source` is `detected` or `blueprint`; `unknown` is a real answer (FR-8). */
823
+ license: AppSourceLicensePreview;
824
+ deployTargets: Record<AppDeployTargetChoice, AppDeployTargetAvailability>;
825
+ /** The CALLER's own existing App Work — never another account's. */
826
+ existingAppWork?: {
827
+ id: string;
828
+ name: string;
829
+ slug: string;
830
+ };
831
+ /**
832
+ * True when the existing-fork scan did not reach every offered owner
833
+ * (APW-01 FR-9, tasks.md:84-85).
834
+ *
835
+ * Required, not optional: a client that forgets it would silently render a
836
+ * partial scan as complete. (APW-01 tasks.md:748 later calls it optional,
837
+ * which would weaken this; R-26 forbids that, so the required reading wins.)
838
+ */
839
+ scanIncomplete: boolean;
840
+ /** ISO timestamp, present when `rate_limited` refused something. */
841
+ retryAfter?: string;
842
+ }
843
+ /**
844
+ * The repository facts the mode resolver reads. Deliberately narrower than
845
+ * {@link AppSourceInspectResponse} so it can be built from a provider read, a
846
+ * cached inspect or a test fixture without inventing a response.
847
+ */
848
+ interface AppRepositoryModeFacts {
849
+ canPush: boolean;
850
+ archived: boolean;
851
+ empty: boolean;
852
+ allowForking: boolean;
853
+ usesLfs: boolean;
854
+ /** The provider-reported size in KB; absent or unmeasurable fails closed. */
855
+ sizeKb?: number | null;
856
+ visibility: 'public' | 'private' | 'internal';
857
+ /** The pasted repository is itself a fork. */
858
+ isFork: boolean;
859
+ /** The member owns this repository in the target account (FR-18). */
860
+ isOwnRepository: boolean;
861
+ /** Another account already uses this repository in Ever Works (FR-26). */
862
+ isInUseByAnotherAccount: boolean;
863
+ }
864
+ /** The resolver's answer: every mode, plus the one the form should pre-select. */
865
+ interface AppRepositoryModeResolution {
866
+ modes: Record<AppRepositoryMode, AppModeAvailability>;
867
+ defaultMode: AppRepositoryMode | null;
868
+ }
869
+ /**
870
+ * Which modes the create form may offer, and which one it pre-selects —
871
+ * FR-17, FR-18 and FR-20 exactly, in the order those requirements list their
872
+ * conditions, so a disabled card always has the reason the spec gives it.
873
+ *
874
+ * Fails closed on an unmeasurable `sizeKb`: a repository whose size could not be
875
+ * read is NOT offered as a private copy, because "we could not measure it" must
876
+ * never be rendered as "it fits".
877
+ */
878
+ declare function resolveAppRepositoryModes(factsInput: AppRepositoryModeFacts): AppRepositoryModeResolution;
879
+ /**
880
+ * The fields APW-01 ADDS to the existing create request (plan.md:421-428;
881
+ * openapi `AppWorkCreateRequest`). The rest of the create DTO is unchanged and
882
+ * is deliberately not restated here.
883
+ */
884
+ interface AppWorkCreateRequest {
885
+ kind: 'app';
886
+ repositoryUrl: string;
887
+ /** Required for `kind: app`; the three {@link APP_REPOSITORY_MODES}. */
888
+ repositoryMode?: AppRepositoryMode;
889
+ /** Required for `fork` and `private-copy`; the caller's account or organization. */
890
+ targetOwner?: string;
891
+ /** The supported way to give a Blueprint to a repository no catalog entry lists (APW-03 FR-81). */
892
+ blueprintId?: string;
893
+ /**
894
+ * Write-only prompted App env values (APW-01 FR-55). Never echoed by any
895
+ * read; handed to APW-07 and stored encrypted once the App spec exists.
896
+ */
897
+ appEnv?: Record<string, string>;
898
+ }
899
+ /**
900
+ * The `appSource` block of the create answer (openapi:274-282).
901
+ *
902
+ * Every client — form, chat, MCP server, command line — reads the platform's
903
+ * own decision here instead of re-deriving it.
904
+ */
905
+ interface AppSourceCreatedView {
906
+ relation: AppRepositoryMode;
907
+ /** `preparing` on create; the closed set is APW-02's `APP_READINESS_STATES`. */
908
+ readiness: AppReadinessState;
909
+ dataRepository: {
910
+ owner: string;
911
+ repo: string;
912
+ url?: string;
913
+ };
914
+ /** Absent for `link`. */
915
+ upstream?: AppUpstreamRef;
916
+ deployTarget: AppDeployTargetChoice;
917
+ /** The Blueprint the platform settled server-side (APW-01 FR-29b). */
918
+ blueprint?: {
919
+ id: string;
920
+ version?: string;
921
+ name?: string;
922
+ matchSource?: AppSourceBlueprintMatchSource;
923
+ };
924
+ }
925
+ /** The create answer (openapi `AppWorkCreateResponse`). */
926
+ interface AppWorkCreateResponse {
927
+ status: 'success';
928
+ appSource?: AppSourceCreatedView;
929
+ /** Present and true when an equivalent App Work already existed (FR-23). */
930
+ alreadyExisted?: boolean;
931
+ }
932
+ /**
933
+ * The delete body's App-Work fields (openapi:160-173, plan.md:433-435).
934
+ *
935
+ * `delete_data_repository` keeps its existing meaning — the fork or the private
936
+ * copy (FR-38) — and is refused for a `link` relation. `delete_stored_data` is a
937
+ * SEPARATE choice (R-15) and needs `confirm_slug` to equal the App Work's slug,
938
+ * checked server-side before anything else happens (FR-40b). Omitting either
939
+ * flag means "keep" for every caller, including chat and MCP (FR-39).
940
+ */
941
+ interface AppWorkDeleteRequest {
942
+ delete_data_repository?: boolean;
943
+ delete_stored_data?: boolean;
944
+ confirm_slug?: string;
945
+ }
946
+ /** The shared error body for the App-source routes (openapi `AppSourceError`). */
947
+ interface AppSourceErrorBody {
948
+ status: 'error';
949
+ code: AppSourceReasonCode;
950
+ message: string;
951
+ /** Only the caller's own identifiers ever appear here (FR-51). */
952
+ details?: {
953
+ owner?: string;
954
+ fullName?: string;
955
+ workId?: string;
956
+ workName?: string;
957
+ retryAfter?: string;
958
+ };
959
+ }
960
+ /**
961
+ * At most 15 provider API calls per inspect, the existing-fork scan included
962
+ * (APW-01 FR-7, spec.md:290). The single biggest number in the create path.
963
+ */
964
+ declare const APP_INSPECT_MAX_PROVIDER_CALLS = 15;
965
+ /**
966
+ * The fixed checks that precede the fork scan — repository read 1, default-branch
967
+ * read at most 1, caller read 1, organizations read 1, `.gitattributes` read 1 —
968
+ * bounded so the scan always has room (APW-01 FR-9, spec.md:302, plan.md:187-190).
969
+ */
970
+ declare const APP_INSPECT_FIXED_PROVIDER_CALLS = 5;
971
+ /**
972
+ * A new owner is started only while at least this many calls remain
973
+ * (APW-01 FR-9, spec.md:303, plan.md:191).
974
+ */
975
+ declare const APP_INSPECT_OWNER_MIN_CALLS_REMAINING = 3;
976
+ /** Whether the budget still allows starting the scan of one more owner. */
977
+ declare function canStartTargetOwnerScan(callsRemaining: number): boolean;
978
+ /** Inspect answers within 8 seconds at p95 (APW-01 FR-7, spec.md:291). */
979
+ declare const APP_INSPECT_P95_BUDGET_MS = 8000;
980
+ /** Inspect caches its answer per member and repository for 60 seconds (spec.md:291). */
981
+ declare const APP_INSPECT_CACHE_TTL_MS = 60000;
982
+ /** Inspect is rate-limited to 30 requests per minute per member (spec.md:292). */
983
+ declare const APP_INSPECT_RATE_LIMIT_PER_MINUTE = 30;
984
+ /** Owners offered in P1: the caller's account first, then organizations A–Z (spec.md:300). */
985
+ declare const APP_TARGET_OWNER_SCAN_LIMIT_P1 = 30;
986
+ /** Owners offered in P2 — the same scan, paginated further (spec.md:300, tasks.md:745). */
987
+ declare const APP_TARGET_OWNER_SCAN_LIMIT_P2 = 200;
988
+ /**
989
+ * The private copy ceiling, 500 MB as GitHub reports size in KB
990
+ * (APW-01 FR-20, spec.md:337, plan.md:412).
991
+ *
992
+ * APW-02 imports THIS constant for `createRepositoryCopy({ maxSizeKb })`; it is
993
+ * never restated (plan.md:460-461).
994
+ */
995
+ declare const APP_PRIVATE_COPY_MAX_SIZE_KB = 512000;
996
+ /**
997
+ * How many names a private copy may try: the copy, then `-copy-2` … `-copy-5`
998
+ * (APW-01 FR-20, spec.md:340, plan.md:413).
999
+ */
1000
+ declare const APP_PRIVATE_COPY_NAME_ATTEMPTS = 5;
1001
+ /** Concurrent creates for one member/upstream/mode/owner are serialised this long (FR-22, spec.md:356). */
1002
+ declare const APP_CREATE_LOCK_TTL_MS = 120000;
1003
+ /** The idempotency window: an identical create returns the same App Work (FR-23, spec.md:358). */
1004
+ declare const APP_CREATE_IDEMPOTENCY_WINDOW_MS = 600000;
1005
+ /** The create response returns within 10 seconds and never waits for a fork (FR-21, spec.md:350). */
1006
+ declare const APP_CREATE_RESPONSE_BUDGET_MS = 10000;
1007
+ /**
1008
+ * The repository URL ceiling, reused from the Repository Work rules that
1009
+ * inspect and create must follow exactly (APW-01 FR-6, spec.md:289).
1010
+ */
1011
+ declare const APP_REPOSITORY_URL_MAX_LENGTH = 400;
1012
+ /**
1013
+ * One predicate for both doors, so inspect's URL field and create's cannot
1014
+ * drift apart. Fails closed on a non-string body arriving off the wire.
1015
+ */
1016
+ declare function appRepositoryUrlLengthExceeded(repositoryUrl: string): boolean;
1017
+
1018
+ /**
1019
+ * Merge policy — the configurable enforcement matrix for agent-driven merges
1020
+ * (Wave 3, founder decision D4).
1021
+ *
1022
+ * The platform does NOT hardcode whether an agent may merge its own pull
1023
+ * request. Whether it may is a POLICY, resolvable at four scopes
1024
+ * (tenant → organization → Work → Agent) and layered over a conservative
1025
+ * platform DEFAULT. Operators keep the safe posture by doing nothing and can
1026
+ * opt into "agents merge when green" — or anything in between — per scope.
1027
+ *
1028
+ * This package holds the zero-dependency storage/wire shapes only. The
1029
+ * resolution algorithm, the deep merge and the single decision point
1030
+ * (`canAgentMerge`) live in `@ever-works/agent` (`policy/`), and enforcement
1031
+ * lives at the git facade + the Task finalize path.
1032
+ */
1033
+ /** Merge strategy a provider can be asked to use when landing a pull request. */
1034
+ type MergeMethod = 'merge' | 'squash' | 'rebase';
1035
+ /**
1036
+ * Canonical list of merge methods. Kept as a const so validators (DTO
1037
+ * `@IsIn`, import sanitizers) share one source of truth with the type.
1038
+ */
1039
+ declare const MERGE_METHODS: readonly MergeMethod[];
1040
+ /**
1041
+ * The fully-resolved policy. Every field is REQUIRED here — a resolved policy
1042
+ * is always complete, because unset fields fall through to the next scope and
1043
+ * ultimately to {@link PLATFORM_DEFAULT_MERGE_POLICY}.
1044
+ */
1045
+ interface MergePolicy {
1046
+ /**
1047
+ * May an agent land a pull request at all? `false` does not stop the agent
1048
+ * from OPENING one (that is `AgentPermissions.canOpenPullRequests`) — it
1049
+ * stops the merge itself.
1050
+ */
1051
+ allowAgentMerge: boolean;
1052
+ /** Require the run's quality gate to be green before an agent may merge. */
1053
+ requireGreenGate: boolean;
1054
+ /** Require a recorded human approval before an agent may merge. */
1055
+ requireHumanApproval: boolean;
1056
+ /** Merge strategies an agent may use. An empty list refuses every merge. */
1057
+ allowedMergeMethods: MergeMethod[];
1058
+ /**
1059
+ * Branch names an agent may never merge INTO, matched case-insensitively
1060
+ * against the pull request's base branch (a leading `refs/heads/` is
1061
+ * stripped before comparison).
1062
+ */
1063
+ protectedBranches: string[];
1064
+ }
1065
+ /**
1066
+ * The scopes a policy can be stored at, from least to most specific. The
1067
+ * most specific scope that declares a field wins for THAT field
1068
+ * (see {@link MERGE_POLICY_SCOPE_PRECEDENCE}).
1069
+ */
1070
+ type MergePolicyScope = 'tenant' | 'organization' | 'work' | 'agent';
1071
+ /**
1072
+ * Documented precedence, least specific first:
1073
+ *
1074
+ * platform default < tenant < organization < Work < Agent
1075
+ *
1076
+ * Resolution is FIELD-BY-FIELD (a deep merge, not a whole-object override):
1077
+ * a Work that sets only `allowAgentMerge` inherits the other four fields from
1078
+ * its organization / tenant / the platform default. `null` or an omitted key
1079
+ * at any scope means "inherit", never "false".
1080
+ */
1081
+ declare const MERGE_POLICY_SCOPE_PRECEDENCE: readonly MergePolicyScope[];
1082
+ /**
1083
+ * What a scope actually stores: a PARTIAL policy. Absent/`null` fields
1084
+ * inherit from the next-least-specific scope. This is the shape of the
1085
+ * additive `mergePolicy` `simple-json` column on `tenants`, `organizations`,
1086
+ * `works` and `agents`.
1087
+ */
1088
+ type MergePolicyOverride = Partial<MergePolicy>;
1089
+ /**
1090
+ * Which scope a resolved policy (or one of its fields) came from. `'default'`
1091
+ * means no scope in the chain declared it and the platform default applies.
1092
+ */
1093
+ type MergePolicySource = MergePolicyScope | 'default';
1094
+ /**
1095
+ * The platform DEFAULT — deliberately conservative, and deliberately NOT a
1096
+ * hardcode: every field is overridable at any of the four scopes. An operator
1097
+ * who wants agents to land their own green work sets
1098
+ * `{ allowAgentMerge: true, requireHumanApproval: false }` at the scope of
1099
+ * their choosing.
1100
+ */
1101
+ declare const PLATFORM_DEFAULT_MERGE_POLICY: MergePolicy;
1102
+ /** Every field name of {@link MergePolicy}; the deep-merge iterates this. */
1103
+ declare const MERGE_POLICY_FIELDS: readonly (keyof MergePolicy)[];
1104
+ /** One link of the resolution chain, reported so a preview can explain itself. */
1105
+ interface MergePolicyChainEntry {
1106
+ /** The scope this link represents (`'default'` is always the first link). */
1107
+ scope: MergePolicySource;
1108
+ /** Row id of the scope entity; `null` for the platform default. */
1109
+ id: string | null;
1110
+ /**
1111
+ * Fields this link CONTRIBUTED to the final policy — i.e. it declared them
1112
+ * and no more specific link overrode them. An empty array means the link
1113
+ * exists in the ancestry but was fully shadowed (or declared nothing).
1114
+ */
1115
+ fields: (keyof MergePolicy)[];
1116
+ }
1117
+ /** Result of one policy resolution. */
1118
+ interface ResolvedMergePolicy {
1119
+ /** The complete, effective policy. */
1120
+ policy: MergePolicy;
1121
+ /**
1122
+ * The MOST SPECIFIC scope that contributed at least one field, or
1123
+ * `'default'` when nothing in the chain declared anything.
1124
+ */
1125
+ source: MergePolicySource;
1126
+ /** Least → most specific, starting at the platform default. */
1127
+ chain: MergePolicyChainEntry[];
1128
+ }
1129
+ /**
1130
+ * Stable refusal codes from the single decision point. Kept machine-readable
1131
+ * so callers (facade, worker, UI) can branch without string-matching prose.
1132
+ */
1133
+ type MergeRefusalCode = 'agent-merge-disabled' | 'protected-branch' | 'target-branch-unknown' | 'merge-method-not-allowed' | 'gate-not-green' | 'human-approval-required'
1134
+ /** No recorded approval names this pull request at all. */
1135
+ | 'approval-missing'
1136
+ /** An approval exists for this pull request, but for an EARLIER head commit. */
1137
+ | 'approval-stale'
1138
+ /** A matching approval exists but is older than `MERGE_APPROVAL_MAX_AGE_MS`. */
1139
+ | 'approval-expired'
1140
+ /** The recorded decision was not made by a human (guardrail / no decider). */
1141
+ | 'approval-not-human'
1142
+ /** The approver is not entitled to approve for this Task's scope. */
1143
+ | 'approver-not-entitled'
1144
+ /** The pull request is draft/closed/merged at merge time. */
1145
+ | 'pull-request-not-open'
1146
+ /** Provider CI is not green at merge time (it may have been at approval time). */
1147
+ | 'pull-request-not-green'
1148
+ /** The live head commit could not be read, so nothing can be pinned to it. */
1149
+ | 'head-sha-unknown';
1150
+ /** Outcome of the single decision point (`canAgentMerge`). */
1151
+ interface MergeDecision {
1152
+ allowed: boolean;
1153
+ /** Human-readable explanation; present only when `allowed === false`. */
1154
+ reason?: string;
1155
+ /** Machine-readable counterpart of `reason`. */
1156
+ code?: MergeRefusalCode;
1157
+ /** The policy the decision was made against, and where it came from. */
1158
+ source?: MergePolicySource;
1159
+ }
1160
+
1161
+ /**
1162
+ * Connection credential transport (AW-15) — the organization setting and the
1163
+ * pure verdict every create, update and connection attempt shares.
1164
+ *
1165
+ * ## What already worked, and what is new
1166
+ *
1167
+ * An MCP connection whose auth headers hold LITERAL values has always been
1168
+ * able to use a plain `http://` endpoint. That keeps working: such a
1169
+ * connection is allowed and flagged `insecure_transport` (a warning) so the
1170
+ * owner sees the credential travels unencrypted.
1171
+ *
1172
+ * Resolving `{{cred.key}}` references inside headers is new, so nothing relies
1173
+ * on sending a resolved secret over plain http. A reference aimed at a
1174
+ * plain-http endpoint is refused (`https_required`) and the secret is never
1175
+ * looked up.
1176
+ *
1177
+ * An organization can opt into refusing literal credentials over plain http
1178
+ * too, with the setting below. It is OFF unless the organization turns it on.
1179
+ */
1180
+ /** Stored on `organizations.connection_policy`. `null` / `{}` = every default. */
1181
+ interface OrganizationConnectionPolicy {
1182
+ /**
1183
+ * "Require https for connection credentials". When `true`, a connection
1184
+ * whose auth headers carry ANY value (literal or reference) must use an
1185
+ * `https:` endpoint. Default `false`: literal credentials over plain http
1186
+ * keep working, with a warning.
1187
+ */
1188
+ requireHttpsForCredentials?: boolean;
1189
+ }
1190
+ /** The setting's key inside `OrganizationConnectionPolicy`. */
1191
+ declare const REQUIRE_HTTPS_FOR_CREDENTIALS_SETTING: "requireHttpsForCredentials";
1192
+ /** The setting's human name, used verbatim in every refusal it causes. */
1193
+ declare const REQUIRE_HTTPS_FOR_CREDENTIALS_SETTING_LABEL = "Require https for connection credentials";
1194
+ /**
1195
+ * Shape guard for the stored / submitted policy. Unknown keys are dropped and
1196
+ * only a real boolean is kept, so a junk value can never switch enforcement on
1197
+ * or off by accident. An object with nothing left is `null` ("all defaults").
1198
+ */
1199
+ declare function sanitizeOrganizationConnectionPolicy(raw: unknown): OrganizationConnectionPolicy | null;
1200
+ /** Does this stored policy refuse literal credentials over plain http? Default: no. */
1201
+ declare function organizationRequiresHttpsForCredentials(policy: unknown): boolean;
1202
+ /**
1203
+ * The verdict for one endpoint + header map.
1204
+ *
1205
+ * secure no credential leaves in cleartext (https, stdio, or no headers)
1206
+ * insecure literal credentials over plain http — allowed, with a warning
1207
+ * refused nothing may be sent; `reason` says why
1208
+ */
1209
+ type CredentialTransportVerdict = {
1210
+ verdict: 'secure';
1211
+ } | {
1212
+ verdict: 'insecure';
1213
+ } | {
1214
+ verdict: 'refused';
1215
+ reason: CredentialTransportRefusalReason;
1216
+ };
1217
+ /**
1218
+ * credential_references a `{{cred.key}}` reference aimed at plain http
1219
+ * organization_policy literal credentials over plain http while the
1220
+ * organization requires https
1221
+ */
1222
+ type CredentialTransportRefusalReason = 'credential_references' | 'organization_policy';
1223
+ interface CredentialTransportInput {
1224
+ url: string | null | undefined;
1225
+ transport?: string | null;
1226
+ headers: Readonly<Record<string, string>> | null | undefined;
1227
+ /** The organization setting. Omitted / `false` = literal credentials over http stay allowed. */
1228
+ requireHttpsForCredentials?: boolean;
1229
+ }
1230
+ /**
1231
+ * Decide how one connection may send its headers.
1232
+ *
1233
+ * `stdio` rows are exempt — they never dial a network address. A header map
1234
+ * with no non-empty value carries no credential, so plain http without
1235
+ * headers is `secure` in every case (it sends nothing to protect).
1236
+ */
1237
+ declare function assessCredentialTransport(input: CredentialTransportInput): CredentialTransportVerdict;
1238
+
1239
+ /**
1240
+ * Live Feed — wire types for the narrated view of the activity log.
1241
+ *
1242
+ * The Live Feed is a reading surface over the `activity_log` rows Ever Works
1243
+ * already writes. It owns no store of its own: every entry below is one
1244
+ * existing activity record, projected into a line a person can read without
1245
+ * decoding an action token.
1246
+ *
1247
+ * The API returns STRUCTURE, never English. A narration is a message key plus
1248
+ * sanitized parameters, and a destination is a typed pointer, so the web
1249
+ * renders both through its own translations and route constants and any
1250
+ * other client (CLI, MCP) can do the same.
1251
+ */
1252
+ /** The five buckets every entry classifies into. Derived, never stored. */
1253
+ type FeedKind = 'work' | 'decision' | 'delivery' | 'problem' | 'system';
1254
+ /** Display order of the kind chips (keyboard `1`-`5` follows this order). */
1255
+ declare const FEED_KINDS: readonly FeedKind[];
1256
+ /**
1257
+ * Who did the thing: an agent, the signed-in user, an external source
1258
+ * (a connector, a repository, a deployed site), or the platform itself.
1259
+ */
1260
+ type FeedActorKind = 'agent' | 'user' | 'external' | 'system';
1261
+ declare const FEED_ACTOR_KINDS: readonly FeedActorKind[];
1262
+ /** Default page size. */
1263
+ declare const FEED_PAGE_SIZE_DEFAULT = 30;
1264
+ /** A page never holds more than this many entries. */
1265
+ declare const FEED_PAGE_SIZE_MAX = 50;
1266
+ /** At most this many agents can be watched at once. */
1267
+ declare const FEED_MAX_AGENT_FILTER = 20;
1268
+ /** How far back the feed reads. Older records stay on the Activity log. */
1269
+ declare const FEED_HISTORY_DAYS = 90;
1270
+ /** Automatic paging stops after this many pages in one visit. */
1271
+ declare const FEED_MAX_AUTO_PAGES = 20;
1272
+ /** Every interpolated narration value is truncated to this many characters. */
1273
+ declare const FEED_NARRATION_PARAM_MAX_CHARS = 120;
1274
+ /** Default and maximum look-back window of the actor roster, in hours. */
1275
+ declare const FEED_ACTORS_WINDOW_HOURS_DEFAULT = 168;
1276
+ declare const FEED_ACTORS_WINDOW_HOURS_MAX = 720;
1277
+ interface FeedActorDto {
1278
+ kind: FeedActorKind;
1279
+ /** Set when `kind === 'agent'`. */
1280
+ agentId?: string | null;
1281
+ /**
1282
+ * Display name. For an agent, the name captured when the record was
1283
+ * written, else the agent's current name. `null` when no name is known,
1284
+ * in which case the renderer uses its own label for the kind.
1285
+ */
1286
+ label: string | null;
1287
+ /** An agent's avatar mode, when it still exists. */
1288
+ avatarMode?: string | null;
1289
+ }
1290
+ interface FeedNarrationDto {
1291
+ /** A leaf key under the renderer's narration namespace, or `fallback`. */
1292
+ key: string;
1293
+ /** Sanitized values. Only fields allowed for the action type ever appear. */
1294
+ params: Record<string, string | number>;
1295
+ }
1296
+ /** What an entry can point at. */
1297
+ type FeedTargetType = 'run' | 'task' | 'mission' | 'idea' | 'agent' | 'work' | 'inbox' | 'skill';
1298
+ declare const FEED_TARGET_TYPES: readonly FeedTargetType[];
1299
+ /**
1300
+ * The most specific thing an entry is about. `null` on the entry when there
1301
+ * is nothing to open (for example the agent was deleted), in which case the
1302
+ * entry renders as plain text rather than a dead link.
1303
+ */
1304
+ interface FeedTargetDto {
1305
+ type: FeedTargetType;
1306
+ id: string;
1307
+ }
1308
+ interface FeedEntryDto {
1309
+ /** The activity record id. */
1310
+ id: string;
1311
+ /** ISO timestamp of when it happened. */
1312
+ createdAt: string;
1313
+ kind: FeedKind;
1314
+ /** The record's own status (`pending`, `in_progress`, `completed`, `failed`, `cancelled`). */
1315
+ status: string;
1316
+ /** The record's action type, for clients that want to group or count. */
1317
+ actionType: string;
1318
+ actor: FeedActorDto;
1319
+ narration: FeedNarrationDto;
1320
+ target: FeedTargetDto | null;
1321
+ workId?: string | null;
1322
+ }
1323
+ interface FeedPageDto {
1324
+ /** Newest first. */
1325
+ items: FeedEntryDto[];
1326
+ /** Opaque cursor for the next older page, or `null` at the end. */
1327
+ nextCursor: string | null;
1328
+ hasMore: boolean;
1329
+ /** Oldest point the feed reads back to (ISO). Paging stops here. */
1330
+ historyFloor: string;
1331
+ /** Populated once per-user seen state is available. */
1332
+ unseenCount?: number;
1333
+ lastSeenAt?: string | null;
1334
+ }
1335
+ interface FeedActorSummaryDto {
1336
+ agentId: string;
1337
+ label: string;
1338
+ /** The agent's current status (`active`, `running`, `paused`, ...). */
1339
+ status: string;
1340
+ avatarMode?: string | null;
1341
+ /** Entries attributed to the agent inside the requested window. */
1342
+ count: number;
1343
+ /** ISO timestamp of the agent's newest entry in the window, if any. */
1344
+ lastActivityAt: string | null;
1345
+ }
1346
+ interface FeedActorsDto {
1347
+ actors: FeedActorSummaryDto[];
1348
+ windowHours: number;
1349
+ }
1350
+ /** Computed while-you-were-away payload. Never stored. */
1351
+ interface FeedAwaySummaryDto {
1352
+ awayForMs: number;
1353
+ windowStart: string;
1354
+ windowEnd: string;
1355
+ truncatedToWindow: boolean;
1356
+ truncatedToScanCap: boolean;
1357
+ total: number;
1358
+ byKind: Record<FeedKind, number>;
1359
+ topActors: FeedActorSummaryDto[];
1360
+ otherActorCount: number;
1361
+ decisionsWaiting: number;
1362
+ failures: number;
1363
+ narrative?: {
1364
+ text: string;
1365
+ model: string;
1366
+ tokens: number;
1367
+ } | null;
1368
+ }
1369
+ /** Stable error codes the feed endpoints answer with. */
1370
+ type FeedErrorCode = 'invalid-cursor' | 'too-many-agents';
1371
+
1372
+ export { APP_RATE_LIMIT_MIN_REMAINING as $, AWESOME_README_IMPORT_MODES as A, APP_FORK_READINESS_POLL_INTERVAL_MS as B, APP_FORK_READINESS_READY_LATENCY_MS as C, APP_FORK_READINESS_REASONS as D, APP_FORK_READINESS_TIMEOUT_ENV as E, type FeedNarrationDto as F, APP_FORK_READINESS_TIMEOUT_MS as G, APP_FORK_READINESS_TIMEOUT_OVERRIDE_MIN_MS as H, IMPORT_SOURCE_TYPES as I, APP_INSPECT_CACHE_TTL_MS as J, APP_INSPECT_FIXED_PROVIDER_CALLS as K, APP_INSPECT_MAX_PROVIDER_CALLS as L, type MergePolicyOverride as M, APP_INSPECT_OWNER_MIN_CALLS_REMAINING as N, type OrganizationConnectionPolicy as O, type ProvidersDto as P, APP_INSPECT_P95_BUDGET_MS as Q, type RelatedRepositories as R, type SourceRepository as S, APP_INSPECT_RATE_LIMIT_PER_MINUTE as T, APP_LICENSE_EVALUATION_REASONS as U, APP_PRIVATE_COPY_MAX_SIZE_KB as V, WorkScheduleCadence as W, APP_PRIVATE_COPY_NAME_ATTEMPTS as X, APP_RATE_LIMITED_PERSISTENT_AFTER as Y, APP_RATE_LIMIT_BACKOFF_BASE_MS as Z, APP_RATE_LIMIT_BACKOFF_MAX_MS as _, WorkScheduleBillingMode as a, type AppSourceRelatedRepositories as a$, APP_RATE_LIMIT_RESET_GRACE_MS as a0, APP_READINESS_FAILURE_REASONS as a1, APP_READINESS_STATES as a2, APP_REPOSITORY_MODES as a3, APP_REPOSITORY_URL_MAX_LENGTH as a4, APP_SETUP_PR_CHECK_BATCH as a5, APP_SETUP_PR_CHECK_ON_VIEW_MIN_INTERVAL_MS as a6, APP_SOURCE_BLUEPRINT_MATCH_SOURCES as a7, APP_SOURCE_BLUEPRINT_STATUSES as a8, APP_SOURCE_LICENSE_CLASSES as a9, APP_UPSTREAM_WARNING_CODES as aA, APP_WORK_REPOSITORY_ROLE as aB, type AppActionsState as aC, type AppBlueprintPreview as aD, type AppDeployTargetAvailability as aE, type AppDeployTargetChoice as aF, type AppForkReadinessReason as aG, type AppLicenseEvaluationReason as aH, type AppModeAvailability as aI, type AppReadinessFailureReason as aJ, type AppReadinessHandlerReason as aK, type AppReadinessState as aL, type AppRepositoryMode as aM, type AppRepositoryModeFacts as aN, type AppRepositoryModeResolution as aO, type AppSourceBlock as aP, type AppSourceBlueprintMatchSource as aQ, type AppSourceBlueprintStatus as aR, type AppSourceCreatedView as aS, type AppSourceErrorBody as aT, type AppSourceInspectRequest as aU, type AppSourceInspectResponse as aV, type AppSourceLicenseClass as aW, type AppSourceLicensePreview as aX, type AppSourceLicenseSource as aY, type AppSourceReasonCode as aZ, type AppSourceRecord as a_, APP_SOURCE_LICENSE_SOURCES as aa, APP_SOURCE_REASON_CODES as ab, APP_SOURCE_REPOSITORY_NAME_SUFFIXES as ac, APP_SOURCE_REPOSITORY_TYPES as ad, APP_SOURCE_REPOSITORY_TYPE_BY_MODE as ae, APP_SOURCE_SPEC_FILE as af, APP_SOURCE_SPEC_KIND as ag, APP_SOURCE_SPEC_VERSION as ah, APP_SYNC_REASONS as ai, APP_SYNC_RESULTS as aj, APP_TARGET_OWNER_SCAN_LIMIT_P1 as ak, APP_TARGET_OWNER_SCAN_LIMIT_P2 as al, APP_UPSTREAM_CONFLICT_LABEL_PREFIX as am, APP_UPSTREAM_CONFLICT_MAX_PATHS as an, APP_UPSTREAM_STATUSES as ao, APP_UPSTREAM_SYNC_ACK_BUDGET_MS as ap, APP_UPSTREAM_SYNC_BRANCH as aq, APP_UPSTREAM_SYNC_DEFAULT_SCHEDULE as ar, APP_UPSTREAM_SYNC_DISPATCH_BATCH as as, APP_UPSTREAM_SYNC_DISPATCH_CRON as at, APP_UPSTREAM_SYNC_JITTER_MAX_MS as au, APP_UPSTREAM_SYNC_LOCK_TTL_MS as av, APP_UPSTREAM_SYNC_MANUAL_PER_HOUR as aw, APP_UPSTREAM_SYNC_MAX_PROVIDER_CALLS as ax, APP_UPSTREAM_SYNC_MIN_INTERVAL_MS as ay, APP_UPSTREAM_UNAVAILABLE_RECHECK_MS as az, WorkScheduleStatus as b, organizationRequiresHttpsForCredentials as b$, type AppSourceRepositoryType as b0, type AppSyncReason as b1, type AppSyncResult as b2, type AppTargetOwner as b3, type AppUpstreamActionsView as b4, type AppUpstreamDivergenceView as b5, type AppUpstreamReadinessView as b6, type AppUpstreamRef as b7, type AppUpstreamStateResponse as b8, type AppUpstreamStatus as b9, type FeedAwaySummaryDto as bA, type FeedErrorCode as bB, type FeedKind as bC, type FeedPageDto as bD, type FeedTargetDto as bE, type FeedTargetType as bF, MERGE_METHODS as bG, MERGE_POLICY_FIELDS as bH, MERGE_POLICY_SCOPE_PRECEDENCE as bI, type MergeDecision as bJ, type MergeMethod as bK, type MergePolicy as bL, type MergePolicyChainEntry as bM, type MergePolicyScope as bN, type MergePolicySource as bO, type MergeRefusalCode as bP, PLATFORM_DEFAULT_MERGE_POLICY as bQ, REQUIRE_HTTPS_FOR_CREDENTIALS_SETTING as bR, REQUIRE_HTTPS_FOR_CREDENTIALS_SETTING_LABEL as bS, type ResolvedMergePolicy as bT, type WorkSourceRepositoryType as bU, appManualSyncAllowed as bV, appRateLimitAllowsSync as bW, appRepositoryUrlLengthExceeded as bX, assessCredentialTransport as bY, canStartTargetOwnerScan as bZ, isAppSourceReasonCode as b_, type AppUpstreamSyncView as ba, type AppUpstreamView as bb, type AppUpstreamWarning as bc, type AppUpstreamWarningCode as bd, type AppUpstreamWorkRepositoryView as be, type AppWorkCreateRequest as bf, type AppWorkCreateResponse as bg, type AppWorkDeleteRequest as bh, type CredentialTransportInput as bi, type CredentialTransportRefusalReason as bj, type CredentialTransportVerdict as bk, FEED_ACTORS_WINDOW_HOURS_DEFAULT as bl, FEED_ACTORS_WINDOW_HOURS_MAX as bm, FEED_ACTOR_KINDS as bn, FEED_HISTORY_DAYS as bo, FEED_KINDS as bp, FEED_MAX_AGENT_FILTER as bq, FEED_MAX_AUTO_PAGES as br, FEED_NARRATION_PARAM_MAX_CHARS as bs, FEED_PAGE_SIZE_DEFAULT as bt, FEED_PAGE_SIZE_MAX as bu, FEED_TARGET_TYPES as bv, type FeedActorDto as bw, type FeedActorKind as bx, type FeedActorSummaryDto as by, type FeedActorsDto as bz, type AnalyzeRepositoryResponseDto as c, resolveAppRepositoryModes as c0, sanitizeOrganizationConnectionPolicy as c1, type AwesomeReadmeImportMode as d, type ImportEnrichmentConfig as e, type ImportSourceType as f, type ImportWorkDto as g, type RepoVisibility as h, type RepositoryRole as i, type RepositoryTarget as j, type WorksConfigSnapshot as k, type AppBlueprintPrompt as l, type FeedEntryDto as m, APP_ACTIONS_HYGIENE_MAX_WORKFLOWS as n, APP_ACTIONS_STATES as o, APP_BEHIND_EVENT_STEP as p, APP_CREATE_IDEMPOTENCY_WINDOW_MS as q, APP_CREATE_LOCK_TTL_MS as r, APP_CREATE_RESPONSE_BUDGET_MS as s, APP_DEPLOY_TARGET_CHOICES as t, APP_DIVERGENCE_DAILY_MS as u, APP_DIVERGENCE_TTL_MS as v, APP_FORK_READINESS_IDLE_MS as w, APP_FORK_READINESS_MANUAL_RETRIES_PER_HOUR as x, APP_FORK_READINESS_MAX_REDISPATCH as y, APP_FORK_READINESS_POLL_DELAYS_MS as z };