@company-semantics/contracts 91.0.0 → 92.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@company-semantics/contracts",
3
- "version": "91.0.0",
3
+ "version": "92.0.0",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
@@ -179,6 +179,7 @@
179
179
  "esbuild@<0.28.1": ">=0.28.1",
180
180
  "linkify-it@<5.0.2": ">=5.0.2",
181
181
  "postcss@<8.5.23": ">=8.5.23",
182
+ "source-map-js@<1.2.2": ">=1.2.2",
182
183
  "markdown-it@<14.2.0": ">=14.2.0",
183
184
  "@humanfs/node@<0.16.8": ">=0.16.8 <0.17.0"
184
185
  }
@@ -188,5 +189,5 @@
188
189
  "*.md": "markdownlint-cli2",
189
190
  "package.json": "node -e \"JSON.parse(require('fs').readFileSync('package.json'))\""
190
191
  },
191
- "securityRequirementsVersion": "8700b9fe36f8c948f12970ec54128e4f1955986dd9b634114f7501fdb1884267"
192
+ "securityRequirementsVersion": "4b88755e9a43a82b2f5eb55b953581526f1982de362da77bc579888d1f6a1bb0"
192
193
  }
@@ -1,3 +1,3 @@
1
1
  // AUTO-GENERATED — do not edit. Run pnpm generate:spec-hash to regenerate.
2
- export const SPEC_HASH = 'b2a6eec5dea4' as const;
3
- export const SPEC_HASH_FULL = 'b2a6eec5dea4f72290740a1cf16608a826ece2e3654ba64d2bc5e3794d571809' as const;
2
+ export const SPEC_HASH = '9937d3953931' as const;
3
+ export const SPEC_HASH_FULL = '9937d39539319f5173df9f15191c8dc5af40aca8c8cd62a9995f7221436909d2' as const;
@@ -1566,6 +1566,23 @@ export interface paths {
1566
1566
  patch?: never;
1567
1567
  trace?: never;
1568
1568
  };
1569
+ "/api/integrations/bamboohr/sync": {
1570
+ parameters: {
1571
+ query?: never;
1572
+ header?: never;
1573
+ path?: never;
1574
+ cookie?: never;
1575
+ };
1576
+ get?: never;
1577
+ put?: never;
1578
+ /** Run a BambooHR sync now (returns the run summary) */
1579
+ post: operations["syncBambooHrNow"];
1580
+ delete?: never;
1581
+ options?: never;
1582
+ head?: never;
1583
+ patch?: never;
1584
+ trace?: never;
1585
+ };
1569
1586
  "/api/org/reconciliation": {
1570
1587
  parameters: {
1571
1588
  query?: never;
@@ -1666,6 +1683,26 @@ export interface paths {
1666
1683
  patch?: never;
1667
1684
  trace?: never;
1668
1685
  };
1686
+ "/api/org/structure-inference/runs": {
1687
+ parameters: {
1688
+ query?: never;
1689
+ header?: never;
1690
+ path?: never;
1691
+ cookie?: never;
1692
+ };
1693
+ get?: never;
1694
+ put?: never;
1695
+ /**
1696
+ * Launch one org-structure reanalyze workflow and its inference run
1697
+ * @description Mints an org-structure/reanalyze analysis workflow, opens its pending run and schedules the job, all in one transaction (ADR-BE-606, ADR-BE-703): the snapshot, the model calls and the deterministic gate execute on the worker, and the outcome is read back by polling GET /api/org/structure-inference/proposal, whose run field carries this run’s id and status, or GET /api/analysis-workflows/{workflowId} for the workflow. At most one inference is in flight per org — a second POST joins the run already under way. Explicitly operator-triggered: there is no schedule and no sync hook.
1698
+ */
1699
+ post: operations["runOrgStructureInference"];
1700
+ delete?: never;
1701
+ options?: never;
1702
+ head?: never;
1703
+ patch?: never;
1704
+ trace?: never;
1705
+ };
1669
1706
  "/api/analysis-workflows/{id}": {
1670
1707
  parameters: {
1671
1708
  query?: never;
@@ -1726,6 +1763,26 @@ export interface paths {
1726
1763
  patch?: never;
1727
1764
  trace?: never;
1728
1765
  };
1766
+ "/api/affordances/state": {
1767
+ parameters: {
1768
+ query?: never;
1769
+ header?: never;
1770
+ path?: never;
1771
+ cookie?: never;
1772
+ };
1773
+ /**
1774
+ * Read the live policy and availability of offered affordances
1775
+ * @description For exactly the affordance ids named in `ids` (the ids a settled outcome offered — never the catalog), whether the viewer is shown each one (`policy`, from the same capability derivation as GET /api/capabilities) and whether the org’s current state permits it (`availability`). Entries come back in request order, deduped. NON-AUTHORITATIVE: this answer is advisory UX state; the route each affordance binds to stays the only enforcement and may still refuse. Org-scoped: requires active membership of the session org, because availability discloses org state.
1776
+ */
1777
+ get: operations["getAffordanceState"];
1778
+ put?: never;
1779
+ post?: never;
1780
+ delete?: never;
1781
+ options?: never;
1782
+ head?: never;
1783
+ patch?: never;
1784
+ trace?: never;
1785
+ };
1729
1786
  "/api/company-md/tree": {
1730
1787
  parameters: {
1731
1788
  query?: never;
@@ -4879,7 +4936,7 @@ export interface paths {
4879
4936
  put?: never;
4880
4937
  /**
4881
4938
  * Approve the draft candidate set as reviewed, per scope
4882
- * @description Approves the named scopes (or every scope still open) at the revision the person reviewed. Per scope, the items freeze, a hash binds them to that scope’s share of the spending cap, and a landing job is scheduled on one landing-and-synthesis workflow.
4939
+ * @description Approves the named scopes (or every scope still open) at the revision the person reviewed. Per scope, the items freeze, a hash binds the approval to exactly those files and treatments, and a landing job is scheduled on one landing-and-synthesis workflow. Approval authorizes the revision only; it carries no spend.
4883
4940
  */
4884
4941
  post: operations["approveSourceCandidateSet"];
4885
4942
  delete?: never;
@@ -6808,6 +6865,34 @@ export interface components {
6808
6865
  requiredScope?: string;
6809
6866
  };
6810
6867
  };
6868
+ integrations?: {
6869
+ manage: {
6870
+ /** @enum {string} */
6871
+ state: "allowed" | "blocked";
6872
+ requiredScope?: string;
6873
+ };
6874
+ };
6875
+ sourceSync?: {
6876
+ manage: {
6877
+ /** @enum {string} */
6878
+ state: "allowed" | "blocked";
6879
+ requiredScope?: string;
6880
+ };
6881
+ };
6882
+ billing?: {
6883
+ view: {
6884
+ /** @enum {string} */
6885
+ state: "allowed" | "blocked";
6886
+ requiredScope?: string;
6887
+ };
6888
+ };
6889
+ orgStructure?: {
6890
+ analyze: {
6891
+ /** @enum {string} */
6892
+ state: "allowed" | "blocked";
6893
+ requiredScope?: string;
6894
+ };
6895
+ };
6811
6896
  };
6812
6897
  chatMentions: boolean;
6813
6898
  chatMultiParty: boolean;
@@ -6816,6 +6901,17 @@ export interface components {
6816
6901
  reason: ("BILLING_INACTIVE" | "SEAT_SUBSCRIPTION_PAST_DUE" | "AI_BALANCE_EXHAUSTED" | "AI_BUDGET_EXHAUSTED" | "BYO_KEY_INVALID") | null;
6817
6902
  };
6818
6903
  };
6904
+ BambooHrSyncRunResponse: {
6905
+ /** Format: uuid */
6906
+ runId: string;
6907
+ processed: number;
6908
+ changed: number;
6909
+ skipped: number;
6910
+ conflicts: number;
6911
+ failures: number;
6912
+ sinceCursor: string | null;
6913
+ status: string;
6914
+ };
6819
6915
  ResolveOrgDivergenceRequest: {
6820
6916
  /** @constant */
6821
6917
  resolution: "acknowledged";
@@ -6993,6 +7089,23 @@ export interface components {
6993
7089
  fingerprint: string;
6994
7090
  note?: string;
6995
7091
  };
7092
+ RunStructureInferenceRefusal: {
7093
+ /** @constant */
7094
+ ran: false;
7095
+ /** @enum {string} */
7096
+ reason: "no_sync_run" | "no_persons" | "reporting_not_keyed";
7097
+ message: string;
7098
+ };
7099
+ RunStructureInferenceAccepted: {
7100
+ /** @constant */
7101
+ ran: true;
7102
+ /** Format: uuid */
7103
+ runId: string;
7104
+ workflowId: string | null;
7105
+ /** @enum {string} */
7106
+ status: "pending" | "running";
7107
+ alreadyRunning: boolean;
7108
+ };
6996
7109
  AnalysisWorkflowProjectionResponse: {
6997
7110
  /** Format: uuid */
6998
7111
  id: string;
@@ -7003,7 +7116,180 @@ export interface components {
7003
7116
  completedAt: string | null;
7004
7117
  progress: unknown | null;
7005
7118
  result: unknown | null;
7006
- outcome: unknown | null;
7119
+ outcome: ({
7120
+ /** @constant */
7121
+ workflowType: "source-sync/discover";
7122
+ executionEpoch: number;
7123
+ /** @enum {string} */
7124
+ kind: "produced" | "empty" | "partial" | "stopped" | "failed" | "abandoned" | "unknown";
7125
+ /** @enum {string} */
7126
+ reason: "candidates_found" | "nothing_found" | "nothing_relevant" | "budget_exhausted" | "file_ceiling" | "stopped_by_user" | "plan_coverage_refused" | "billing_refused" | "drive_auth" | "drive_unavailable" | "no_connection" | "source_sync_off" | "internal_error" | "abandoned" | "unrecognized_terminal_state";
7127
+ facts: {
7128
+ probesTotal: number;
7129
+ probesDone: number;
7130
+ filesSeen: number;
7131
+ filesShown: number;
7132
+ filesHidden: number;
7133
+ filesDropped: number;
7134
+ coveragePercent: number | null;
7135
+ } | null;
7136
+ disposition: {
7137
+ /** @constant */
7138
+ kind: "review";
7139
+ /** @enum {string} */
7140
+ requestType: "org-structure/review" | "source-sync/candidates" | "source-sync/synthesis";
7141
+ requestId: string;
7142
+ } | {
7143
+ /** @constant */
7144
+ kind: "narrate";
7145
+ };
7146
+ affordances: ({
7147
+ /** @constant */
7148
+ id: "sourceSync.findFiles";
7149
+ } | {
7150
+ /** @constant */
7151
+ id: "integrations.connectGoogleDrive";
7152
+ } | {
7153
+ /** @constant */
7154
+ id: "sourceSync.enable";
7155
+ } | {
7156
+ /** @constant */
7157
+ id: "billing.open";
7158
+ } | {
7159
+ /** @constant */
7160
+ id: "orgStructure.reanalyze";
7161
+ } | {
7162
+ /** @constant */
7163
+ id: "hris.resyncDirectory";
7164
+ })[];
7165
+ } | {
7166
+ /** @constant */
7167
+ workflowType: "source-sync/synthesize";
7168
+ executionEpoch: number;
7169
+ /** @enum {string} */
7170
+ kind: "produced" | "empty" | "partial" | "stopped" | "failed" | "abandoned" | "unknown";
7171
+ /** @enum {string} */
7172
+ reason: "updates_ready" | "updates_applied" | "stopped_by_user" | "paused_billing" | "run_ceiling_reached" | "pricing_unconfigured" | "synthesis_incomplete" | "approval_mismatch" | "landing_refused" | "standing_order_refused" | "no_connection" | "source_sync_off" | "internal_error" | "abandoned" | "unrecognized_terminal_state";
7173
+ facts: {
7174
+ scopeCount: number;
7175
+ violationCount: number;
7176
+ } | null;
7177
+ disposition: {
7178
+ /** @constant */
7179
+ kind: "review";
7180
+ /** @enum {string} */
7181
+ requestType: "org-structure/review" | "source-sync/candidates" | "source-sync/synthesis";
7182
+ requestId: string;
7183
+ } | {
7184
+ /** @constant */
7185
+ kind: "narrate";
7186
+ };
7187
+ affordances: ({
7188
+ /** @constant */
7189
+ id: "sourceSync.findFiles";
7190
+ } | {
7191
+ /** @constant */
7192
+ id: "integrations.connectGoogleDrive";
7193
+ } | {
7194
+ /** @constant */
7195
+ id: "sourceSync.enable";
7196
+ } | {
7197
+ /** @constant */
7198
+ id: "billing.open";
7199
+ } | {
7200
+ /** @constant */
7201
+ id: "orgStructure.reanalyze";
7202
+ } | {
7203
+ /** @constant */
7204
+ id: "hris.resyncDirectory";
7205
+ })[];
7206
+ } | {
7207
+ /** @constant */
7208
+ workflowType: "org-structure/hris-connect";
7209
+ executionEpoch: number;
7210
+ /** @enum {string} */
7211
+ kind: "produced" | "empty" | "partial" | "stopped" | "failed" | "abandoned" | "unknown";
7212
+ /** @enum {string} */
7213
+ reason: "proposal_ready" | "directory_synced" | "analysis_already_running" | "proposal_blocked" | "no_sync_run" | "no_persons" | "reporting_not_keyed" | "stopped_by_user" | "sync_failed" | "snapshot_too_large" | "model_failed" | "run_too_large" | "placement_failed" | "internal_error" | "abandoned" | "unrecognized_terminal_state";
7214
+ facts: {
7215
+ departmentCount: number;
7216
+ teamCount: number;
7217
+ placedCount: number;
7218
+ reviewItemCount: number;
7219
+ } | null;
7220
+ disposition: {
7221
+ /** @constant */
7222
+ kind: "review";
7223
+ /** @enum {string} */
7224
+ requestType: "org-structure/review" | "source-sync/candidates" | "source-sync/synthesis";
7225
+ requestId: string;
7226
+ } | {
7227
+ /** @constant */
7228
+ kind: "narrate";
7229
+ };
7230
+ affordances: ({
7231
+ /** @constant */
7232
+ id: "sourceSync.findFiles";
7233
+ } | {
7234
+ /** @constant */
7235
+ id: "integrations.connectGoogleDrive";
7236
+ } | {
7237
+ /** @constant */
7238
+ id: "sourceSync.enable";
7239
+ } | {
7240
+ /** @constant */
7241
+ id: "billing.open";
7242
+ } | {
7243
+ /** @constant */
7244
+ id: "orgStructure.reanalyze";
7245
+ } | {
7246
+ /** @constant */
7247
+ id: "hris.resyncDirectory";
7248
+ })[];
7249
+ } | {
7250
+ /** @constant */
7251
+ workflowType: "org-structure/reanalyze";
7252
+ executionEpoch: number;
7253
+ /** @enum {string} */
7254
+ kind: "produced" | "empty" | "partial" | "stopped" | "failed" | "abandoned" | "unknown";
7255
+ /** @enum {string} */
7256
+ reason: "proposal_ready" | "directory_synced" | "analysis_already_running" | "proposal_blocked" | "no_sync_run" | "no_persons" | "reporting_not_keyed" | "stopped_by_user" | "sync_failed" | "snapshot_too_large" | "model_failed" | "run_too_large" | "placement_failed" | "internal_error" | "abandoned" | "unrecognized_terminal_state";
7257
+ facts: {
7258
+ departmentCount: number;
7259
+ teamCount: number;
7260
+ placedCount: number;
7261
+ reviewItemCount: number;
7262
+ } | null;
7263
+ disposition: {
7264
+ /** @constant */
7265
+ kind: "review";
7266
+ /** @enum {string} */
7267
+ requestType: "org-structure/review" | "source-sync/candidates" | "source-sync/synthesis";
7268
+ requestId: string;
7269
+ } | {
7270
+ /** @constant */
7271
+ kind: "narrate";
7272
+ };
7273
+ affordances: ({
7274
+ /** @constant */
7275
+ id: "sourceSync.findFiles";
7276
+ } | {
7277
+ /** @constant */
7278
+ id: "integrations.connectGoogleDrive";
7279
+ } | {
7280
+ /** @constant */
7281
+ id: "sourceSync.enable";
7282
+ } | {
7283
+ /** @constant */
7284
+ id: "billing.open";
7285
+ } | {
7286
+ /** @constant */
7287
+ id: "orgStructure.reanalyze";
7288
+ } | {
7289
+ /** @constant */
7290
+ id: "hris.resyncDirectory";
7291
+ })[];
7292
+ }) | null;
7007
7293
  error?: string;
7008
7294
  capabilities: {
7009
7295
  canStop: boolean;
@@ -7027,6 +7313,26 @@ export interface components {
7027
7313
  /** @enum {string} */
7028
7314
  result: "delivered" | "deferred" | "busy" | "skipped" | "not_settled";
7029
7315
  };
7316
+ AffordanceStateResponse: {
7317
+ entries: {
7318
+ /** @enum {string} */
7319
+ id: "sourceSync.findFiles" | "integrations.connectGoogleDrive" | "sourceSync.enable" | "billing.open" | "orgStructure.reanalyze" | "hris.resyncDirectory" | "review.open";
7320
+ /** @enum {string} */
7321
+ policy: "allowed" | "blocked";
7322
+ availability: {
7323
+ /** @constant */
7324
+ state: "available";
7325
+ } | {
7326
+ /** @constant */
7327
+ state: "already_satisfied";
7328
+ } | {
7329
+ /** @constant */
7330
+ state: "unavailable";
7331
+ /** @enum {string} */
7332
+ reason: "conflicting_operation" | "missing_dependency" | "resource_gone" | "temporarily_disabled";
7333
+ };
7334
+ }[];
7335
+ };
7030
7336
  CompanyMdListResponse: {
7031
7337
  items: {
7032
7338
  id: string;
@@ -9523,11 +9829,6 @@ export interface components {
9523
9829
  } | null;
9524
9830
  approvedAt: string | null;
9525
9831
  }[];
9526
- estimate: {
9527
- lowMicroUsd: string;
9528
- highMicroUsd: string;
9529
- capMicroUsd: string;
9530
- } | null;
9531
9832
  discovery: {
9532
9833
  foundThisRun: number;
9533
9834
  retainedDecisions: number;
@@ -9603,7 +9904,7 @@ export interface components {
9603
9904
  workflowId: string;
9604
9905
  batchId: string | null;
9605
9906
  /** @enum {string} */
9606
- phase: "landing" | "drafting" | "waiting_for_review" | "paused_billing" | "applied" | "applied_partial" | "failed" | "closed";
9907
+ phase: "landing" | "drafting" | "waiting_for_review" | "paused_billing" | "paused_ceiling" | "applied" | "applied_partial" | "failed" | "closed";
9607
9908
  fileCount: number | null;
9608
9909
  proposedDocumentCount: number;
9609
9910
  appliedAt: string | null;
@@ -12949,6 +13250,33 @@ export interface operations {
12949
13250
  };
12950
13251
  };
12951
13252
  };
13253
+ syncBambooHrNow: {
13254
+ parameters: {
13255
+ query?: never;
13256
+ header?: never;
13257
+ path?: never;
13258
+ cookie?: never;
13259
+ };
13260
+ requestBody?: never;
13261
+ responses: {
13262
+ /** @description Sync run summary */
13263
+ 200: {
13264
+ headers: {
13265
+ [name: string]: unknown;
13266
+ };
13267
+ content: {
13268
+ "application/json": components["schemas"]["BambooHrSyncRunResponse"];
13269
+ };
13270
+ };
13271
+ /** @description No active BambooHR connection, or BambooHR no longer recognizes the organization */
13272
+ 400: {
13273
+ headers: {
13274
+ [name: string]: unknown;
13275
+ };
13276
+ content?: never;
13277
+ };
13278
+ };
13279
+ };
12952
13280
  getOrgReconciliation: {
12953
13281
  parameters: {
12954
13282
  query?: never;
@@ -13096,6 +13424,35 @@ export interface operations {
13096
13424
  };
13097
13425
  };
13098
13426
  };
13427
+ runOrgStructureInference: {
13428
+ parameters: {
13429
+ query?: never;
13430
+ header?: never;
13431
+ path?: never;
13432
+ cookie?: never;
13433
+ };
13434
+ requestBody?: never;
13435
+ responses: {
13436
+ /** @description A named refusal with its operator-facing next step: no directory imported yet, a sync that imported nobody, or a credential whose sync could not key reporting edges (reporting_not_keyed) */
13437
+ 200: {
13438
+ headers: {
13439
+ [name: string]: unknown;
13440
+ };
13441
+ content: {
13442
+ "application/json": components["schemas"]["RunStructureInferenceRefusal"];
13443
+ };
13444
+ };
13445
+ /** @description A run is under way — freshly launched, or already in flight (alreadyRunning: true). Carries the runId the poll surface matches against and the workflowId of the org-structure/reanalyze workflow it executes (null only when the joined run predates the workflow launch) */
13446
+ 202: {
13447
+ headers: {
13448
+ [name: string]: unknown;
13449
+ };
13450
+ content: {
13451
+ "application/json": components["schemas"]["RunStructureInferenceAccepted"];
13452
+ };
13453
+ };
13454
+ };
13455
+ };
13099
13456
  getAnalysisWorkflow: {
13100
13457
  parameters: {
13101
13458
  query?: never;
@@ -13213,6 +13570,42 @@ export interface operations {
13213
13570
  };
13214
13571
  };
13215
13572
  };
13573
+ getAffordanceState: {
13574
+ parameters: {
13575
+ query: {
13576
+ ids: string;
13577
+ };
13578
+ header?: never;
13579
+ path?: never;
13580
+ cookie?: never;
13581
+ };
13582
+ requestBody?: never;
13583
+ responses: {
13584
+ /** @description Policy and availability per requested affordance id, in request order */
13585
+ 200: {
13586
+ headers: {
13587
+ [name: string]: unknown;
13588
+ };
13589
+ content: {
13590
+ "application/json": components["schemas"]["AffordanceStateResponse"];
13591
+ };
13592
+ };
13593
+ /** @description An id is not a known affordance, the list is empty, or it is too long */
13594
+ 400: {
13595
+ headers: {
13596
+ [name: string]: unknown;
13597
+ };
13598
+ content?: never;
13599
+ };
13600
+ /** @description The viewer is not an active member of the session org */
13601
+ 403: {
13602
+ headers: {
13603
+ [name: string]: unknown;
13604
+ };
13605
+ content?: never;
13606
+ };
13607
+ };
13608
+ };
13216
13609
  getCompanyMdTree: {
13217
13610
  parameters: {
13218
13611
  query?: {
@@ -19586,7 +19979,6 @@ export interface operations {
19586
19979
  content: {
19587
19980
  "application/json": {
19588
19981
  revision: number;
19589
- spendCapMicroUsd: string;
19590
19982
  scopeKeys?: string[];
19591
19983
  };
19592
19984
  };
@@ -19601,7 +19993,7 @@ export interface operations {
19601
19993
  "application/json": components["schemas"]["SourceSyncApproveResponse"];
19602
19994
  };
19603
19995
  };
19604
- /** @description Invalid request, a scope with no files (SOURCE_SYNC_SCOPE_UNKNOWN), or a cap too large to hold exactly (SOURCE_SYNC_SPEND_CAP_INVALID) */
19996
+ /** @description Invalid request (an unknown field such as a spend cap is refused by the schema), or a scope with no files (SOURCE_SYNC_SCOPE_UNKNOWN) */
19605
19997
  400: {
19606
19998
  headers: {
19607
19999
  [name: string]: unknown;
@@ -9,6 +9,7 @@ export const openApiRoutes = {
9
9
  '/api/account/deletion-eligibility': ['GET'],
10
10
  '/api/account/sessions': ['GET'],
11
11
  '/api/account/sessions/{sessionId}': ['DELETE'],
12
+ '/api/affordances/state': ['GET'],
12
13
  '/api/analysis-workflows/{id}': ['GET'],
13
14
  '/api/analysis-workflows/{id}/settlement': ['POST'],
14
15
  '/api/analysis-workflows/{id}/stop': ['POST'],
@@ -101,6 +102,7 @@ export const openApiRoutes = {
101
102
  '/api/factory/quality/plans/{planId}/decision': ['GET'],
102
103
  '/api/factory/snapshot': ['GET'],
103
104
  '/api/ingestion/operations/{id}': ['GET'],
105
+ '/api/integrations/bamboohr/sync': ['POST'],
104
106
  '/api/internal-admin/impersonate/end': ['POST'],
105
107
  '/api/internal-admin/impersonate/session': ['GET'],
106
108
  '/api/internal-admin/impersonate/start': ['POST'],
@@ -181,6 +183,7 @@ export const openApiRoutes = {
181
183
  '/api/org/structure-findings': ['GET'],
182
184
  '/api/org/structure-findings/{findingId}/dismiss': ['POST'],
183
185
  '/api/org/structure-findings/{findingId}/reopen': ['POST'],
186
+ '/api/org/structure-inference/runs': ['POST'],
184
187
  '/api/org/system-events': ['GET'],
185
188
  '/api/org/system-events/{id}/acknowledge': ['POST'],
186
189
  '/api/org/transfer-eligibility': ['GET'],
@@ -305,7 +305,8 @@ in `attention-evidence.ts`.
305
305
  `attentionEvidence` (null before index-first discovery).
306
306
  - `SourceSyncCandidateSetResponseSchema` / `SourceSyncCandidateSetResponse` —
307
307
  the draft set under review: its revision, items, presented questions,
308
- distinct-file `totals` and cost estimate.
308
+ distinct-file `totals`. No cost estimate: approval authorizes the files,
309
+ never a spend.
309
310
  - `SourceSyncCandidateTotalsSchema` / `SourceSyncCandidateTotals` and
310
311
  `candidateTotalsOf(items)` — THE file count: distinct `sourceId`, never lines
311
312
  (ADR-CONTRACTS-195).
@@ -48,7 +48,6 @@ function addCandidate(overrides: Record<string, unknown> = {}) {
48
48
  function approveRequest(overrides: Record<string, unknown> = {}) {
49
49
  return {
50
50
  revision: 7,
51
- spendCapMicroUsd: "2500000",
52
51
  ...overrides,
53
52
  };
54
53
  }
@@ -112,20 +111,10 @@ describe("SourceSyncApproveRequestSchema", () => {
112
111
  expect(refused.error?.issues[0]?.path).toEqual(["revision"]);
113
112
  });
114
113
 
115
- it("refuses an approval with no spend cap", () => {
116
- const { spendCapMicroUsd: _cap, ...withoutCap } = approveRequest();
117
- const refused = SourceSyncApproveRequestSchema.safeParse(withoutCap);
118
- expect(refused.success).toBe(false);
119
- expect(refused.error?.issues[0]?.path).toEqual(["spendCapMicroUsd"]);
120
-
121
- expect(
122
- SourceSyncApproveRequestSchema.safeParse(
123
- approveRequest({ spendCapMicroUsd: "2.50" }),
124
- ).success,
125
- ).toBe(false);
114
+ it("refuses a spend cap: an approval authorizes files, never a spend", () => {
126
115
  expect(
127
116
  SourceSyncApproveRequestSchema.safeParse(
128
- approveRequest({ spendCapMicroUsd: 2500000 }),
117
+ approveRequest({ spendCapMicroUsd: "2500000" }),
129
118
  ).success,
130
119
  ).toBe(false);
131
120
  });
@@ -43,6 +43,7 @@ describe("SOURCE_SYNC_SYNTHESIS_PHASES", () => {
43
43
  "drafting",
44
44
  "waiting_for_review",
45
45
  "paused_billing",
46
+ "paused_ceiling",
46
47
  "applied",
47
48
  "applied_partial",
48
49
  "failed",