@company-semantics/contracts 92.0.0 → 93.0.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 (61) hide show
  1. package/package.json +9 -9
  2. package/src/action-items/README.md +12 -4
  3. package/src/action-items/schemas.ts +10 -0
  4. package/src/affordances/README.md +52 -1
  5. package/src/affordances/__tests__/README.md +10 -1
  6. package/src/affordances/__tests__/affordances.test.ts +13 -1
  7. package/src/affordances/__tests__/catalog-wave.test.ts +237 -0
  8. package/src/affordances/affordance.ts +56 -4
  9. package/src/affordances/args.ts +44 -1
  10. package/src/affordances/available.ts +59 -0
  11. package/src/affordances/coverage.ts +51 -0
  12. package/src/affordances/ids.ts +28 -0
  13. package/src/affordances/index.ts +17 -0
  14. package/src/api/README.md +1 -0
  15. package/src/api/generated-spec-hash.ts +2 -2
  16. package/src/api/generated.ts +397 -1
  17. package/src/api/primitives.ts +13 -0
  18. package/src/billing/README.md +1 -0
  19. package/src/billing/refusals.ts +12 -0
  20. package/src/message-parts/README.md +5 -0
  21. package/src/message-parts/affordance-offer.ts +44 -0
  22. package/src/message-parts/index.ts +7 -0
  23. package/src/message-parts/types.ts +7 -1
  24. package/src/message-parts/wire.ts +18 -0
  25. package/src/notifications/README.md +17 -3
  26. package/src/notifications/__tests__/README.md +4 -0
  27. package/src/notifications/__tests__/__snapshots__/render-snapshot.test.ts.snap +27 -25
  28. package/src/notifications/__tests__/fixtures.ts +7 -1
  29. package/src/notifications/__tests__/grounded-ctas.test.ts +103 -0
  30. package/src/notifications/__tests__/render-snapshot.test.ts +1 -1
  31. package/src/notifications/content.ts +9 -0
  32. package/src/notifications/kinds/billing-auto-recharge-failed.ts +4 -2
  33. package/src/notifications/kinds/billing-payment-past-due.ts +2 -0
  34. package/src/notifications/kinds/billing-suspended.ts +2 -0
  35. package/src/notifications/kinds/chat-shared.ts +10 -3
  36. package/src/notifications/kinds/company-md-access-approved.ts +13 -6
  37. package/src/notifications/kinds/share-granted.ts +1 -1
  38. package/src/notifications/kinds/unit-owner-granted.ts +9 -2
  39. package/src/notifications/payloads.ts +6 -0
  40. package/src/proactive/README.md +18 -2
  41. package/src/proactive/__tests__/README.md +11 -1
  42. package/src/proactive/__tests__/chat-templates.test.ts +7 -6
  43. package/src/proactive/__tests__/proactive-offers.test.ts +124 -0
  44. package/src/proactive/__tests__/vocabulary.test.ts +1 -1
  45. package/src/proactive/composer.ts +11 -0
  46. package/src/proactive/templates/README.md +11 -3
  47. package/src/proactive/templates/billing-auto-recharge-failed.ts +1 -0
  48. package/src/proactive/templates/billing-balance-exhausted.ts +2 -6
  49. package/src/proactive/templates/billing-payment-past-due.ts +1 -0
  50. package/src/proactive/templates/billing-subscription-canceled.ts +1 -5
  51. package/src/proactive/templates/billing-suspended.ts +1 -0
  52. package/src/proactive/templates/morning-brief.ts +1 -0
  53. package/src/proactive/templates/org-became-shared.ts +4 -3
  54. package/src/proactive/templates/source-sync-review-ready.ts +3 -8
  55. package/src/proactive/templates/workflow-needs-attention.ts +1 -0
  56. package/src/rate-limit/README.md +27 -1
  57. package/src/rate-limit/__tests__/README.md +23 -0
  58. package/src/rate-limit/__tests__/rate-limited-error.test.ts +53 -0
  59. package/src/rate-limit/index.ts +33 -0
  60. package/src/root-exports/agent-runtime.ts +14 -2
  61. package/src/root-exports/delivery.ts +15 -0
@@ -0,0 +1,59 @@
1
+ /**
2
+ * "What can I do here": the RESULT shape of the context tool (control ADR
3
+ * affordance-system, amended by PRD-01135).
4
+ *
5
+ * The tool reads the offer rules for the current context, drops what the
6
+ * viewer's policy blocks, and pairs each remaining instance with its live
7
+ * availability. It NEVER enumerates the catalog: existing is not a reason to
8
+ * offer (INV-AFFORD-RELEVANT), so an empty context returns an empty list.
9
+ *
10
+ * INVARIANTS:
11
+ * - POLICY-FILTERED. An entry is present only when the viewer's policy allows
12
+ * it, so the shape carries no policy field and cannot leak a blocked one.
13
+ * - AVAILABILITY IS LIVE and non-authoritative; only the server executes.
14
+ * - BOUNDED and DISTINCT. At most MAX_OFFERED_AFFORDANCES entries, no
15
+ * instance twice.
16
+ */
17
+ import { z } from "zod";
18
+
19
+ import {
20
+ AffordanceSchema,
21
+ MAX_OFFERED_AFFORDANCES,
22
+ sameAffordances,
23
+ } from "./affordance";
24
+ import { AffordanceAvailabilitySchema } from "./availability";
25
+
26
+ /** One affordance the viewer may take here, with its live availability. */
27
+ export const AvailableAffordanceSchema = z
28
+ .object({
29
+ affordance: AffordanceSchema,
30
+ availability: AffordanceAvailabilitySchema,
31
+ })
32
+ .strict();
33
+ export type AvailableAffordance = z.infer<typeof AvailableAffordanceSchema>;
34
+
35
+ /** The tool result: the offered, policy-allowed instances for this context. */
36
+ export const AvailableAffordancesSchema = z
37
+ .object({
38
+ affordances: z
39
+ .array(AvailableAffordanceSchema)
40
+ .max(MAX_OFFERED_AFFORDANCES),
41
+ })
42
+ .strict()
43
+ .superRefine((value, ctx) => {
44
+ const seen = value.affordances.map((entry) => entry.affordance);
45
+ seen.forEach((affordance, i) => {
46
+ if (
47
+ seen
48
+ .slice(0, i)
49
+ .some((earlier) => sameAffordances([earlier], [affordance]))
50
+ ) {
51
+ ctx.addIssue({
52
+ code: "custom",
53
+ path: ["affordances", i],
54
+ message: "an available affordance appears at most once",
55
+ });
56
+ }
57
+ });
58
+ });
59
+ export type AvailableAffordances = z.infer<typeof AvailableAffordancesSchema>;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Reverse coverage: every capability a person can act on DECLARES its
3
+ * affordance, or why it has none (control ADR affordance-system, amended by
4
+ * PRD-01135).
5
+ *
6
+ * The forward direction (an affordance resolves to a real capability) is
7
+ * proven by each binding repo's architecture test. This is the reverse: a
8
+ * mounted backend command operation, an app navigate route or an app launch
9
+ * surface either names the affordance that offers it, or names a reason from a
10
+ * CLOSED vocabulary — so "nobody decided" is not a representable state.
11
+ *
12
+ * INVARIANTS:
13
+ * - CLOSED. NO_AFFORDANCE_REASONS is append-only and never prose; a reason is
14
+ * a classification an architecture test can count, not an excuse.
15
+ * - EXACTLY ONE. A declaration is `{ affordance }` or `{ noAffordance }`,
16
+ * never both (strict members of a union).
17
+ */
18
+ import { z } from "zod";
19
+
20
+ import { AffordanceIdSchema, type AffordanceId } from "./ids";
21
+
22
+ /**
23
+ * Why a capability offers no affordance. Measured 2026-10-06 against backend
24
+ * routeRegistry (725 GET, the rest mutating; seams for auth-identity,
25
+ * internal-admin, test-only, webhooks and factory ingest, chat / comments
26
+ * inline actions) and the app's routes and launch surfaces.
27
+ */
28
+ export const NO_AFFORDANCE_REASONS = [
29
+ /** Reads only (a POST that searches, previews or resolves); nothing to offer. */
30
+ "readOnly",
31
+ /** Performed by the control that shows it (send, post a comment, save a form). */
32
+ "inlineControl",
33
+ /** Staff-only internal administration. */
34
+ "internalAdmin",
35
+ /** Machine to machine: webhooks, ingest, station/factory, test-only. */
36
+ "systemOnly",
37
+ /** Part of sign-in, sign-up, invite acceptance or session handling. */
38
+ "authFlow",
39
+ ] as const;
40
+ export type NoAffordanceReason = (typeof NO_AFFORDANCE_REASONS)[number];
41
+ export const NoAffordanceReasonSchema = z.enum(NO_AFFORDANCE_REASONS);
42
+
43
+ /** One capability's reverse-coverage declaration. */
44
+ export type AffordanceCoverage =
45
+ | { readonly affordance: AffordanceId }
46
+ | { readonly noAffordance: NoAffordanceReason };
47
+
48
+ export const AffordanceCoverageSchema = z.union([
49
+ z.object({ affordance: AffordanceIdSchema }).strict(),
50
+ z.object({ noAffordance: NoAffordanceReasonSchema }).strict(),
51
+ ]);
@@ -38,6 +38,34 @@ export const AFFORDANCE_IDS = [
38
38
  * workflow outcome's `review` disposition). See PROJECTED_AFFORDANCE_IDS.
39
39
  */
40
40
  "review.open",
41
+ // ---------------------------------------------------------------------------
42
+ // Burn-down wave (PRD-01137): the next steps the 2026-10-06 census found
43
+ // carried as prose. Appended, never inserted.
44
+ // ---------------------------------------------------------------------------
45
+ /** Open Settings → Integrations. */
46
+ "integrations.open",
47
+ /** Connect the HR system (BambooHR), or reconnect it when its sign-in died. */
48
+ "hris.connect",
49
+ /** Open the person's own profile (their name). */
50
+ "account.editProfile",
51
+ /** Open the org's settings. */
52
+ "workspace.openOrgSettings",
53
+ /** Add one file to Source Sync by hand. */
54
+ "sourceSync.addFile",
55
+ /** Open one Source Sync update (a proposal) for review, in chat. */
56
+ "sourceSync.openUpdate",
57
+ /** Open the org-structure review of one proposal (in chat). */
58
+ "orgStructure.openReview",
59
+ /** Open one chat. */
60
+ "chat.open",
61
+ /** Open one company.md document. */
62
+ "companyMd.openDoc",
63
+ /** Open one company.md document's version history. */
64
+ "companyMd.openHistory",
65
+ /** Open one team (org unit). */
66
+ "team.open",
67
+ /** Open one execution's detail (the target of an execution confirmation). */
68
+ "execution.open",
41
69
  ] as const;
42
70
 
43
71
  export type AffordanceId = (typeof AFFORDANCE_IDS)[number];
@@ -6,8 +6,14 @@ export { AFFORDANCE_IDS, AffordanceIdSchema } from "./ids";
6
6
  export type { AffordanceId } from "./ids";
7
7
  export {
8
8
  AFFORDANCE_ARGS,
9
+ ChatOpenArgsSchema,
10
+ CompanyMdDocArgsSchema,
11
+ ExecutionOpenArgsSchema,
9
12
  NO_ARG_AFFORDANCE_IDS,
13
+ OrgStructureOpenReviewArgsSchema,
10
14
  ReviewOpenArgsSchema,
15
+ SourceSyncOpenUpdateArgsSchema,
16
+ TeamOpenArgsSchema,
11
17
  } from "./args";
12
18
  export type { AffordanceArgs } from "./args";
13
19
  export {
@@ -37,3 +43,14 @@ export type {
37
43
  OfferedAffordance,
38
44
  ProjectedAffordanceId,
39
45
  } from "./affordance";
46
+ export {
47
+ AffordanceCoverageSchema,
48
+ NO_AFFORDANCE_REASONS,
49
+ NoAffordanceReasonSchema,
50
+ } from "./coverage";
51
+ export type { AffordanceCoverage, NoAffordanceReason } from "./coverage";
52
+ export {
53
+ AvailableAffordanceSchema,
54
+ AvailableAffordancesSchema,
55
+ } from "./available";
56
+ export type { AvailableAffordance, AvailableAffordances } from "./available";
package/src/api/README.md CHANGED
@@ -48,6 +48,7 @@ The file is committed to the repo (not .gitignored) so consumers can import type
48
48
 
49
49
  **Internal domains:**
50
50
 
51
+ - `affordances`
51
52
  - `mcp`
52
53
  - `resource-response`
53
54
 
@@ -1,3 +1,3 @@
1
1
  // AUTO-GENERATED — do not edit. Run pnpm generate:spec-hash to regenerate.
2
- export const SPEC_HASH = '9937d3953931' as const;
3
- export const SPEC_HASH_FULL = '9937d39539319f5173df9f15191c8dc5af40aca8c8cd62a9995f7221436909d2' as const;
2
+ export const SPEC_HASH = '4eb1b17b3340' as const;
3
+ export const SPEC_HASH_FULL = '4eb1b17b3340b7613c5f8189f7fef55164ea1d859c67b31790297ce5709b2db4' as const;
@@ -7161,6 +7161,63 @@ export interface components {
7161
7161
  } | {
7162
7162
  /** @constant */
7163
7163
  id: "hris.resyncDirectory";
7164
+ } | {
7165
+ /** @constant */
7166
+ id: "integrations.open";
7167
+ } | {
7168
+ /** @constant */
7169
+ id: "hris.connect";
7170
+ } | {
7171
+ /** @constant */
7172
+ id: "account.editProfile";
7173
+ } | {
7174
+ /** @constant */
7175
+ id: "workspace.openOrgSettings";
7176
+ } | {
7177
+ /** @constant */
7178
+ id: "sourceSync.addFile";
7179
+ } | {
7180
+ /** @constant */
7181
+ id: "sourceSync.openUpdate";
7182
+ args: {
7183
+ proposalId: string;
7184
+ };
7185
+ } | {
7186
+ /** @constant */
7187
+ id: "orgStructure.openReview";
7188
+ args: {
7189
+ proposalId: string;
7190
+ };
7191
+ } | {
7192
+ /** @constant */
7193
+ id: "chat.open";
7194
+ args: {
7195
+ chatId: string;
7196
+ };
7197
+ } | {
7198
+ /** @constant */
7199
+ id: "companyMd.openDoc";
7200
+ args: {
7201
+ docId: string;
7202
+ };
7203
+ } | {
7204
+ /** @constant */
7205
+ id: "companyMd.openHistory";
7206
+ args: {
7207
+ docId: string;
7208
+ };
7209
+ } | {
7210
+ /** @constant */
7211
+ id: "team.open";
7212
+ args: {
7213
+ unitId: string;
7214
+ };
7215
+ } | {
7216
+ /** @constant */
7217
+ id: "execution.open";
7218
+ args: {
7219
+ executionId: string;
7220
+ };
7164
7221
  })[];
7165
7222
  } | {
7166
7223
  /** @constant */
@@ -7202,6 +7259,63 @@ export interface components {
7202
7259
  } | {
7203
7260
  /** @constant */
7204
7261
  id: "hris.resyncDirectory";
7262
+ } | {
7263
+ /** @constant */
7264
+ id: "integrations.open";
7265
+ } | {
7266
+ /** @constant */
7267
+ id: "hris.connect";
7268
+ } | {
7269
+ /** @constant */
7270
+ id: "account.editProfile";
7271
+ } | {
7272
+ /** @constant */
7273
+ id: "workspace.openOrgSettings";
7274
+ } | {
7275
+ /** @constant */
7276
+ id: "sourceSync.addFile";
7277
+ } | {
7278
+ /** @constant */
7279
+ id: "sourceSync.openUpdate";
7280
+ args: {
7281
+ proposalId: string;
7282
+ };
7283
+ } | {
7284
+ /** @constant */
7285
+ id: "orgStructure.openReview";
7286
+ args: {
7287
+ proposalId: string;
7288
+ };
7289
+ } | {
7290
+ /** @constant */
7291
+ id: "chat.open";
7292
+ args: {
7293
+ chatId: string;
7294
+ };
7295
+ } | {
7296
+ /** @constant */
7297
+ id: "companyMd.openDoc";
7298
+ args: {
7299
+ docId: string;
7300
+ };
7301
+ } | {
7302
+ /** @constant */
7303
+ id: "companyMd.openHistory";
7304
+ args: {
7305
+ docId: string;
7306
+ };
7307
+ } | {
7308
+ /** @constant */
7309
+ id: "team.open";
7310
+ args: {
7311
+ unitId: string;
7312
+ };
7313
+ } | {
7314
+ /** @constant */
7315
+ id: "execution.open";
7316
+ args: {
7317
+ executionId: string;
7318
+ };
7205
7319
  })[];
7206
7320
  } | {
7207
7321
  /** @constant */
@@ -7245,6 +7359,63 @@ export interface components {
7245
7359
  } | {
7246
7360
  /** @constant */
7247
7361
  id: "hris.resyncDirectory";
7362
+ } | {
7363
+ /** @constant */
7364
+ id: "integrations.open";
7365
+ } | {
7366
+ /** @constant */
7367
+ id: "hris.connect";
7368
+ } | {
7369
+ /** @constant */
7370
+ id: "account.editProfile";
7371
+ } | {
7372
+ /** @constant */
7373
+ id: "workspace.openOrgSettings";
7374
+ } | {
7375
+ /** @constant */
7376
+ id: "sourceSync.addFile";
7377
+ } | {
7378
+ /** @constant */
7379
+ id: "sourceSync.openUpdate";
7380
+ args: {
7381
+ proposalId: string;
7382
+ };
7383
+ } | {
7384
+ /** @constant */
7385
+ id: "orgStructure.openReview";
7386
+ args: {
7387
+ proposalId: string;
7388
+ };
7389
+ } | {
7390
+ /** @constant */
7391
+ id: "chat.open";
7392
+ args: {
7393
+ chatId: string;
7394
+ };
7395
+ } | {
7396
+ /** @constant */
7397
+ id: "companyMd.openDoc";
7398
+ args: {
7399
+ docId: string;
7400
+ };
7401
+ } | {
7402
+ /** @constant */
7403
+ id: "companyMd.openHistory";
7404
+ args: {
7405
+ docId: string;
7406
+ };
7407
+ } | {
7408
+ /** @constant */
7409
+ id: "team.open";
7410
+ args: {
7411
+ unitId: string;
7412
+ };
7413
+ } | {
7414
+ /** @constant */
7415
+ id: "execution.open";
7416
+ args: {
7417
+ executionId: string;
7418
+ };
7248
7419
  })[];
7249
7420
  } | {
7250
7421
  /** @constant */
@@ -7288,6 +7459,63 @@ export interface components {
7288
7459
  } | {
7289
7460
  /** @constant */
7290
7461
  id: "hris.resyncDirectory";
7462
+ } | {
7463
+ /** @constant */
7464
+ id: "integrations.open";
7465
+ } | {
7466
+ /** @constant */
7467
+ id: "hris.connect";
7468
+ } | {
7469
+ /** @constant */
7470
+ id: "account.editProfile";
7471
+ } | {
7472
+ /** @constant */
7473
+ id: "workspace.openOrgSettings";
7474
+ } | {
7475
+ /** @constant */
7476
+ id: "sourceSync.addFile";
7477
+ } | {
7478
+ /** @constant */
7479
+ id: "sourceSync.openUpdate";
7480
+ args: {
7481
+ proposalId: string;
7482
+ };
7483
+ } | {
7484
+ /** @constant */
7485
+ id: "orgStructure.openReview";
7486
+ args: {
7487
+ proposalId: string;
7488
+ };
7489
+ } | {
7490
+ /** @constant */
7491
+ id: "chat.open";
7492
+ args: {
7493
+ chatId: string;
7494
+ };
7495
+ } | {
7496
+ /** @constant */
7497
+ id: "companyMd.openDoc";
7498
+ args: {
7499
+ docId: string;
7500
+ };
7501
+ } | {
7502
+ /** @constant */
7503
+ id: "companyMd.openHistory";
7504
+ args: {
7505
+ docId: string;
7506
+ };
7507
+ } | {
7508
+ /** @constant */
7509
+ id: "team.open";
7510
+ args: {
7511
+ unitId: string;
7512
+ };
7513
+ } | {
7514
+ /** @constant */
7515
+ id: "execution.open";
7516
+ args: {
7517
+ executionId: string;
7518
+ };
7291
7519
  })[];
7292
7520
  }) | null;
7293
7521
  error?: string;
@@ -7316,7 +7544,7 @@ export interface components {
7316
7544
  AffordanceStateResponse: {
7317
7545
  entries: {
7318
7546
  /** @enum {string} */
7319
- id: "sourceSync.findFiles" | "integrations.connectGoogleDrive" | "sourceSync.enable" | "billing.open" | "orgStructure.reanalyze" | "hris.resyncDirectory" | "review.open";
7547
+ id: "sourceSync.findFiles" | "integrations.connectGoogleDrive" | "sourceSync.enable" | "billing.open" | "orgStructure.reanalyze" | "hris.resyncDirectory" | "review.open" | "integrations.open" | "hris.connect" | "account.editProfile" | "workspace.openOrgSettings" | "sourceSync.addFile" | "sourceSync.openUpdate" | "orgStructure.openReview" | "chat.open" | "companyMd.openDoc" | "companyMd.openHistory" | "team.open" | "execution.open";
7320
7548
  /** @enum {string} */
7321
7549
  policy: "allowed" | "blocked";
7322
7550
  availability: {
@@ -8415,6 +8643,90 @@ export interface components {
8415
8643
  contextLabel: string;
8416
8644
  provider: string | null;
8417
8645
  href: string;
8646
+ affordance?: {
8647
+ /** @constant */
8648
+ id: "sourceSync.findFiles";
8649
+ } | {
8650
+ /** @constant */
8651
+ id: "integrations.connectGoogleDrive";
8652
+ } | {
8653
+ /** @constant */
8654
+ id: "sourceSync.enable";
8655
+ } | {
8656
+ /** @constant */
8657
+ id: "billing.open";
8658
+ } | {
8659
+ /** @constant */
8660
+ id: "orgStructure.reanalyze";
8661
+ } | {
8662
+ /** @constant */
8663
+ id: "hris.resyncDirectory";
8664
+ } | {
8665
+ /** @constant */
8666
+ id: "integrations.open";
8667
+ } | {
8668
+ /** @constant */
8669
+ id: "hris.connect";
8670
+ } | {
8671
+ /** @constant */
8672
+ id: "account.editProfile";
8673
+ } | {
8674
+ /** @constant */
8675
+ id: "workspace.openOrgSettings";
8676
+ } | {
8677
+ /** @constant */
8678
+ id: "sourceSync.addFile";
8679
+ } | {
8680
+ /** @constant */
8681
+ id: "sourceSync.openUpdate";
8682
+ args: {
8683
+ proposalId: string;
8684
+ };
8685
+ } | {
8686
+ /** @constant */
8687
+ id: "orgStructure.openReview";
8688
+ args: {
8689
+ proposalId: string;
8690
+ };
8691
+ } | {
8692
+ /** @constant */
8693
+ id: "chat.open";
8694
+ args: {
8695
+ chatId: string;
8696
+ };
8697
+ } | {
8698
+ /** @constant */
8699
+ id: "companyMd.openDoc";
8700
+ args: {
8701
+ docId: string;
8702
+ };
8703
+ } | {
8704
+ /** @constant */
8705
+ id: "companyMd.openHistory";
8706
+ args: {
8707
+ docId: string;
8708
+ };
8709
+ } | {
8710
+ /** @constant */
8711
+ id: "team.open";
8712
+ args: {
8713
+ unitId: string;
8714
+ };
8715
+ } | {
8716
+ /** @constant */
8717
+ id: "execution.open";
8718
+ args: {
8719
+ executionId: string;
8720
+ };
8721
+ } | {
8722
+ /** @constant */
8723
+ id: "review.open";
8724
+ args: {
8725
+ /** @enum {string} */
8726
+ requestType: "org-structure/review" | "source-sync/candidates" | "source-sync/synthesis";
8727
+ requestId: string;
8728
+ };
8729
+ };
8418
8730
  createdAt: string;
8419
8731
  }[];
8420
8732
  };
@@ -8437,6 +8749,90 @@ export interface components {
8437
8749
  contextLabel: string;
8438
8750
  provider: string | null;
8439
8751
  href: string;
8752
+ affordance?: {
8753
+ /** @constant */
8754
+ id: "sourceSync.findFiles";
8755
+ } | {
8756
+ /** @constant */
8757
+ id: "integrations.connectGoogleDrive";
8758
+ } | {
8759
+ /** @constant */
8760
+ id: "sourceSync.enable";
8761
+ } | {
8762
+ /** @constant */
8763
+ id: "billing.open";
8764
+ } | {
8765
+ /** @constant */
8766
+ id: "orgStructure.reanalyze";
8767
+ } | {
8768
+ /** @constant */
8769
+ id: "hris.resyncDirectory";
8770
+ } | {
8771
+ /** @constant */
8772
+ id: "integrations.open";
8773
+ } | {
8774
+ /** @constant */
8775
+ id: "hris.connect";
8776
+ } | {
8777
+ /** @constant */
8778
+ id: "account.editProfile";
8779
+ } | {
8780
+ /** @constant */
8781
+ id: "workspace.openOrgSettings";
8782
+ } | {
8783
+ /** @constant */
8784
+ id: "sourceSync.addFile";
8785
+ } | {
8786
+ /** @constant */
8787
+ id: "sourceSync.openUpdate";
8788
+ args: {
8789
+ proposalId: string;
8790
+ };
8791
+ } | {
8792
+ /** @constant */
8793
+ id: "orgStructure.openReview";
8794
+ args: {
8795
+ proposalId: string;
8796
+ };
8797
+ } | {
8798
+ /** @constant */
8799
+ id: "chat.open";
8800
+ args: {
8801
+ chatId: string;
8802
+ };
8803
+ } | {
8804
+ /** @constant */
8805
+ id: "companyMd.openDoc";
8806
+ args: {
8807
+ docId: string;
8808
+ };
8809
+ } | {
8810
+ /** @constant */
8811
+ id: "companyMd.openHistory";
8812
+ args: {
8813
+ docId: string;
8814
+ };
8815
+ } | {
8816
+ /** @constant */
8817
+ id: "team.open";
8818
+ args: {
8819
+ unitId: string;
8820
+ };
8821
+ } | {
8822
+ /** @constant */
8823
+ id: "execution.open";
8824
+ args: {
8825
+ executionId: string;
8826
+ };
8827
+ } | {
8828
+ /** @constant */
8829
+ id: "review.open";
8830
+ args: {
8831
+ /** @enum {string} */
8832
+ requestType: "org-structure/review" | "source-sync/candidates" | "source-sync/synthesis";
8833
+ requestId: string;
8834
+ };
8835
+ };
8440
8836
  createdAt: string;
8441
8837
  };
8442
8838
  } | {
@@ -1,5 +1,10 @@
1
1
  import { z } from "zod";
2
2
 
3
+ import {
4
+ AffordanceSchema,
5
+ MAX_OFFERED_AFFORDANCES,
6
+ } from "../affordances/affordance";
7
+
3
8
  /** Generic factory for cursor-paginated responses. */
4
9
  export function CursorPageSchema<T extends z.ZodTypeAny>(itemSchema: T) {
5
10
  return z.object({
@@ -15,6 +20,14 @@ export const ErrorResponseSchema = z.object({
15
20
  code: z.string(),
16
21
  message: z.string(),
17
22
  retryable: z.boolean(),
23
+ /**
24
+ * The catalog affordances that resolve this error, when any do (control ADR
25
+ * affordance-system) — e.g. billing.open on a billing refusal for a viewer
26
+ * who may open billing. Present only when non-empty; the message states the
27
+ * fact and never tells the reader what to do.
28
+ */
29
+ // prettier-ignore
30
+ affordances: z.array(AffordanceSchema).min(1).max(MAX_OFFERED_AFFORDANCES).optional(),
18
31
  }),
19
32
  });
20
33
 
@@ -221,6 +221,7 @@ owner is always its owner contradicts ADR-BE-296, and nothing imported them.
221
221
 
222
222
  **Internal domains:**
223
223
 
224
+ - `affordances`
224
225
  - `api`
225
226
 
226
227
  **External packages:**