@thinkai/tai-api-contract 2.34.0-pr.810.e54f7dcd → 2.35.0-pr.811.d57af044

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.
@@ -1,7 +1,7 @@
1
1
  openapi: 3.0.3
2
2
  info:
3
3
  title: ThinkAI API
4
- version: 2.34.0
4
+ version: 2.35.0
5
5
  description: >
6
6
  Contract surface for the AI Driven SDLC backend used by ThinkAI.
7
7
  Workspace-scoped routes use `/workspaces/{workspaceId}/...`.
@@ -1172,17 +1172,16 @@ paths:
1172
1172
  summary: Productivity insights — contributor drilldown
1173
1173
  description: >
1174
1174
  Weekly and daily activity rollups for a single contributor on
1175
- `/phase-c/c4/contributors/:id`. Distributes weekly merged PR counts from
1176
- precomputed person metrics across weekdays; includes fail-rate signals and
1177
- period-over-period summary deltas. Accepts org-chart person ids (typically email)
1178
- and synthetic GitHub scopes (`__github:{login}`) for contributors not in the org chart.
1175
+ `/insights/productivity/contributors/:loginOrId`. Accepts GitHub login slugs
1176
+ (preferred public URL), org-chart person ids (typically email), and synthetic
1177
+ GitHub scopes (`__github:{login}`) for contributors not in the org chart.
1179
1178
  operationId: getProductivityInsightsContributor
1180
1179
  parameters:
1181
1180
  - $ref: "#/components/parameters/WorkspaceId"
1182
1181
  - name: contributorId
1183
1182
  in: path
1184
1183
  required: true
1185
- description: Org-chart person id or synthetic GitHub scope id (`__github:{login}`).
1184
+ description: GitHub login slug, org-chart person id, or synthetic `__github:{login}` scope id.
1186
1185
  schema:
1187
1186
  type: string
1188
1187
  - $ref: "#/components/parameters/InsightsProductivityRangeId"
@@ -1916,7 +1915,7 @@ paths:
1916
1915
  operationId: postGithubInstallUrl
1917
1916
  description: >
1918
1917
  Creates a GitHub App installation URL scoped to the workspace and caller.
1919
- Body is optional; when omitted, defaults to `/phase-a/p4` return path.
1918
+ Body is optional; when omitted, defaults to `/onboarding/integrations` return path.
1920
1919
  Optional `pickerSession` (from user OAuth org picker) recovers `returnPath` from the server-side picker snapshot when the multi-hop authorize→install flow should return to the page where OAuth started.
1921
1920
  security:
1922
1921
  - bearerAuth: []
@@ -2969,6 +2968,41 @@ paths:
2969
2968
  schema:
2970
2969
  $ref: "#/components/schemas/ErrorMessageDto"
2971
2970
 
2971
+ /workspaces/{workspaceId}/readiness/repos/by-slug/{providerSlug}:
2972
+ get:
2973
+ tags: [RepositoryReadiness]
2974
+ summary: Single repo readiness by provider slug
2975
+ description: >
2976
+ Returns one stored repository scorecard keyed by `providerSlug` (`owner/repo`).
2977
+ Same response as `GET .../readiness/repos/{repoId}`. Unknown slug returns `404`.
2978
+ operationId: getReadinessRepoBySlug
2979
+ parameters:
2980
+ - $ref: "#/components/parameters/WorkspaceId"
2981
+ - $ref: "#/components/parameters/ProviderSlug"
2982
+ responses:
2983
+ "200":
2984
+ description: Repo score
2985
+ content:
2986
+ application/json:
2987
+ schema:
2988
+ $ref: "#/components/schemas/RepoReadinessScoreDetailDto"
2989
+ "400":
2990
+ description: Malformed providerSlug
2991
+ content:
2992
+ application/json:
2993
+ schema:
2994
+ $ref: "#/components/schemas/ErrorMessageDto"
2995
+ "401":
2996
+ $ref: "#/components/responses/Unauthorized"
2997
+ "403":
2998
+ $ref: "#/components/responses/Forbidden"
2999
+ "404":
3000
+ description: Workspace or repository not found
3001
+ content:
3002
+ application/json:
3003
+ schema:
3004
+ $ref: "#/components/schemas/ErrorMessageDto"
3005
+
2972
3006
  /workspaces/{workspaceId}/readiness/repos/{repoId}:
2973
3007
  get:
2974
3008
  tags: [RepositoryReadiness]
@@ -3209,12 +3243,33 @@ paths:
3209
3243
  description: >
3210
3244
  Paginated, chronological feed of workspace-scoped lifecycle events: repository add/remove/re-add
3211
3245
  and GitHub integration add/remove. Inactive repos remain visible in this log.
3212
- Filter by `eventType`, `actorUserId`, or date range (`since`/`until`).
3246
+ Filter by a single `eventType`, a coarse `eventCategory`/`productArea`, an `eventSubcategory`
3247
+ (a dotted event-type prefix that matches a whole lifecycle subgroup in one call, e.g.
3248
+ `integrations.cursor.execution_key`), `actorUserId`, or date range (`since`/`until`).
3213
3249
  parameters:
3214
3250
  - $ref: "#/components/parameters/WorkspaceId"
3215
3251
  - $ref: "#/components/parameters/PaginationLimit"
3216
3252
  - $ref: "#/components/parameters/PaginationOffset"
3217
3253
  - $ref: "#/components/parameters/PaginationOrder"
3254
+ - name: sort
3255
+ in: query
3256
+ required: false
3257
+ description: >
3258
+ Server-side sort column (the activity "5 W's"). Combined with `order` (asc/desc).
3259
+ Defaults to `when` (occurredAt). `occurredAt`/`id` is always the tiebreaker.
3260
+ schema:
3261
+ type: string
3262
+ enum: [when, who, what, why, where]
3263
+ - name: productArea
3264
+ in: query
3265
+ required: false
3266
+ description: >
3267
+ Coarse product-area grouping filter (#156). `integration` = GitHub + AI-tool key events;
3268
+ `agentic_foundation` = repos, readiness scans, fixes; `workspace_team` = members + HRIS;
3269
+ `productivity` = productivity ingest lifecycle events. Omit (or pass `all`) for every area.
3270
+ schema:
3271
+ type: string
3272
+ enum: [integration, agentic_foundation, workspace_team, productivity, all]
3218
3273
  - name: eventType
3219
3274
  in: query
3220
3275
  description: Filter to a specific event type.
@@ -3245,6 +3300,20 @@ paths:
3245
3300
  Filter by event namespace prefix (e.g. "fix", "repo", "integration", "readiness", "config", "member").
3246
3301
  schema:
3247
3302
  type: string
3303
+ - name: eventSubcategory
3304
+ in: query
3305
+ required: false
3306
+ description: >
3307
+ Filter by a dotted event-type *subgroup* (#156): a strict prefix of an event type with one
3308
+ or more segments (shorter than the full event type), matching every lifecycle event under it
3309
+ in a single call. Single-segment values (e.g. `fix`, `readiness`, `repo`, `productivity`)
3310
+ overlap with `eventCategory` so the same control can filter at any depth. Example:
3311
+ `integrations.cursor.execution_key` returns `integrations.cursor.execution_key.added`,
3312
+ `.updated`, `.removed`, and `.check_failed`; `integrations.cursor` returns all Cursor key
3313
+ events; `fix` returns all fix lifecycle events. Must be one of the known subcategories or the
3314
+ request is rejected (400).
3315
+ schema:
3316
+ type: string
3248
3317
  - name: search
3249
3318
  in: query
3250
3319
  required: false
@@ -3278,6 +3347,100 @@ paths:
3278
3347
  schema:
3279
3348
  $ref: "#/components/schemas/ErrorMessageDto"
3280
3349
 
3350
+ /workspaces/{workspaceId}/activity/export:
3351
+ get:
3352
+ tags: [WorkspaceActivity]
3353
+ summary: Export workspace activity log as CSV
3354
+ operationId: exportWorkspaceActivity
3355
+ description: >
3356
+ Export the workspace activity log as an RFC 4180 CSV file (one row per event). Accepts the
3357
+ same filters as `GET /workspaces/{workspaceId}/activity` (`eventType`, `eventCategory`,
3358
+ `eventSubcategory`, `productArea`, `actorUserId`, `since`, `until`, `search`, `sort`, `order`);
3359
+ `limit`/`offset` are ignored — the export returns up to 50000 matching rows within the sort.
3360
+ Columns: occurredAt, eventType, eventCategory, actorType, actorName, actorEmail, repoName,
3361
+ integrationType, metadata. Opaque internal identifiers (actorUserId, repoId, integrationId,
3362
+ fixRequestId, issueId, readinessRunId) are omitted — the human-readable equivalents are
3363
+ already present and the IDs carry no value in a user-facing export.
3364
+ The response sets `Content-Disposition: attachment` with a `.csv` filename.
3365
+ parameters:
3366
+ - $ref: "#/components/parameters/WorkspaceId"
3367
+ - name: sort
3368
+ in: query
3369
+ required: false
3370
+ schema:
3371
+ type: string
3372
+ enum: [when, who, what, why, where]
3373
+ - $ref: "#/components/parameters/PaginationOrder"
3374
+ - name: productArea
3375
+ in: query
3376
+ required: false
3377
+ schema:
3378
+ type: string
3379
+ enum: [integration, agentic_foundation, workspace_team, productivity, all]
3380
+ - name: eventType
3381
+ in: query
3382
+ required: false
3383
+ schema:
3384
+ $ref: "#/components/schemas/ActivityLogEventTypeDto"
3385
+ - name: eventCategory
3386
+ in: query
3387
+ required: false
3388
+ schema:
3389
+ type: string
3390
+ - name: eventSubcategory
3391
+ in: query
3392
+ required: false
3393
+ description: Dotted event-type subgroup prefix (see the activity list endpoint).
3394
+ schema:
3395
+ type: string
3396
+ - name: actorUserId
3397
+ in: query
3398
+ required: false
3399
+ schema:
3400
+ type: string
3401
+ format: uuid
3402
+ - name: since
3403
+ in: query
3404
+ required: false
3405
+ schema:
3406
+ type: string
3407
+ format: date-time
3408
+ - name: until
3409
+ in: query
3410
+ required: false
3411
+ schema:
3412
+ type: string
3413
+ format: date-time
3414
+ - name: search
3415
+ in: query
3416
+ required: false
3417
+ schema:
3418
+ type: string
3419
+ maxLength: 200
3420
+ responses:
3421
+ "200":
3422
+ description: CSV file of activity log entries
3423
+ content:
3424
+ text/csv:
3425
+ schema:
3426
+ type: string
3427
+ "400":
3428
+ description: Invalid query parameters
3429
+ content:
3430
+ application/json:
3431
+ schema:
3432
+ $ref: "#/components/schemas/ErrorMessageDto"
3433
+ "401":
3434
+ $ref: "#/components/responses/Unauthorized"
3435
+ "403":
3436
+ $ref: "#/components/responses/Forbidden"
3437
+ "404":
3438
+ description: Workspace does not exist
3439
+ content:
3440
+ application/json:
3441
+ schema:
3442
+ $ref: "#/components/schemas/ErrorMessageDto"
3443
+
3281
3444
  /workspaces/{workspaceId}/readiness/score-history:
3282
3445
  get:
3283
3446
  tags: [RepositoryReadiness]
@@ -4045,6 +4208,130 @@ paths:
4045
4208
  "403":
4046
4209
  $ref: "#/components/responses/Forbidden"
4047
4210
 
4211
+ /workspaces/{workspaceId}/repo-eligibility:
4212
+ get:
4213
+ tags: [RepositoryReadiness]
4214
+ summary: Get repo-sync eligibility gate (defaults + per-workspace overrides)
4215
+ description: >
4216
+ Returns the effective repo-sync eligibility gate (archived / fork / size / count) for the
4217
+ workspace: the global `defaults`, any per-workspace `overrides`, the merged `effective`
4218
+ values, and whether the caller can edit without platform-admin (`canEditUnrestricted`).
4219
+ Member-level read access.
4220
+ operationId: getWorkspaceRepoEligibility
4221
+ parameters:
4222
+ - $ref: "#/components/parameters/WorkspaceId"
4223
+ responses:
4224
+ "200":
4225
+ description: Effective repo-eligibility configuration
4226
+ content:
4227
+ application/json:
4228
+ schema:
4229
+ $ref: "#/components/schemas/WorkspaceRepoEligibilityDto"
4230
+ "401":
4231
+ $ref: "#/components/responses/Unauthorized"
4232
+ "403":
4233
+ $ref: "#/components/responses/Forbidden"
4234
+ put:
4235
+ tags: [RepositoryReadiness]
4236
+ summary: Set per-workspace repo-sync eligibility overrides
4237
+ description: >
4238
+ Set (or clear, with an empty `overrides`) the per-workspace repo-sync eligibility overrides.
4239
+ **Platform admins** may set any value (raise caps, `0` = unlimited, include archived/forks).
4240
+ **Workspace admins** may only make the gate *more restrictive* than the platform defaults
4241
+ (lower caps, exclude archived/forks) — exceeding a platform limit returns `403`
4242
+ (`repo_eligibility_bound_exceeded`). Requires workspace admin or platform admin.
4243
+ operationId: putWorkspaceRepoEligibility
4244
+ parameters:
4245
+ - $ref: "#/components/parameters/WorkspaceId"
4246
+ requestBody:
4247
+ required: true
4248
+ content:
4249
+ application/json:
4250
+ schema:
4251
+ type: object
4252
+ required: [overrides]
4253
+ properties:
4254
+ overrides:
4255
+ $ref: "#/components/schemas/RepoEligibilityOverridesDto"
4256
+ responses:
4257
+ "200":
4258
+ description: Overrides saved
4259
+ content:
4260
+ application/json:
4261
+ schema:
4262
+ type: object
4263
+ required: [overrides, effective]
4264
+ properties:
4265
+ overrides:
4266
+ $ref: "#/components/schemas/RepoEligibilityOverridesDto"
4267
+ effective:
4268
+ $ref: "#/components/schemas/RepoEligibilityConfigDto"
4269
+ "400":
4270
+ description: Invalid request body
4271
+ content:
4272
+ application/json:
4273
+ schema:
4274
+ $ref: "#/components/schemas/ErrorMessageDto"
4275
+ "401":
4276
+ $ref: "#/components/responses/Unauthorized"
4277
+ "403":
4278
+ description: Forbidden, or a workspace-admin value exceeds a platform limit (`repo_eligibility_bound_exceeded`)
4279
+ content:
4280
+ application/json:
4281
+ schema:
4282
+ $ref: "#/components/schemas/ErrorMessageDto"
4283
+
4284
+ /workspaces/{workspaceId}/repo-eligibility/refresh-languages:
4285
+ post:
4286
+ tags: [RepositoryReadiness]
4287
+ summary: Force a language/stack re-detection on the next sync
4288
+ description: >
4289
+ Admin maintenance action: invalidate the cached language/stack freshness marker so the
4290
+ next GitHub repo sync re-fetches `GET /repos/{owner}/{repo}/languages` and recomputes the
4291
+ per-language breakdown and supported stacks. Use after adding a newly-supported language
4292
+ to a repo, or when a repo's stack detection looks stale. Optionally scope to a single repo
4293
+ via `repoSlug` (`owner/name`); omit it to reset every repo in the workspace. Requires
4294
+ workspace admin or platform admin. The refresh itself happens on the next sync (e.g. when
4295
+ the GitHub repo list is loaded with `refresh=true`); the readiness scan also refreshes the
4296
+ breakdown on each successful run.
4297
+ operationId: refreshWorkspaceRepoLanguages
4298
+ parameters:
4299
+ - $ref: "#/components/parameters/WorkspaceId"
4300
+ requestBody:
4301
+ required: false
4302
+ content:
4303
+ application/json:
4304
+ schema:
4305
+ type: object
4306
+ properties:
4307
+ repoSlug:
4308
+ type: string
4309
+ description: Optional `owner/name` to scope the refresh to a single repo. Omit to reset all repos.
4310
+ responses:
4311
+ "200":
4312
+ description: Freshness invalidated; languages will be re-detected on the next sync.
4313
+ content:
4314
+ application/json:
4315
+ schema:
4316
+ type: object
4317
+ required: [ok, reposReset]
4318
+ properties:
4319
+ ok:
4320
+ type: boolean
4321
+ reposReset:
4322
+ type: integer
4323
+ description: Number of repo rows whose language/stack cache was invalidated.
4324
+ "400":
4325
+ description: Invalid request body
4326
+ content:
4327
+ application/json:
4328
+ schema:
4329
+ $ref: "#/components/schemas/ErrorMessageDto"
4330
+ "401":
4331
+ $ref: "#/components/responses/Unauthorized"
4332
+ "403":
4333
+ $ref: "#/components/responses/Forbidden"
4334
+
4048
4335
  /workspaces/{workspaceId}/readiness/cursor-key-usage:
4049
4336
  get:
4050
4337
  tags: [RepositoryReadiness]
@@ -4247,7 +4534,7 @@ paths:
4247
4534
  - $ref: "#/components/parameters/WorkspaceId"
4248
4535
  responses:
4249
4536
  "200":
4250
- description: Progress (empty completedSteps when no row exists yet; updatedAt is synthetic in that case)
4537
+ description: Progress (empty completedStepIds when no row exists yet; updatedAt is synthetic in that case)
4251
4538
  content:
4252
4539
  application/json:
4253
4540
  schema:
@@ -4554,8 +4841,10 @@ paths:
4554
4841
  tags: [YourAiJourney]
4555
4842
  summary: Workspace journey step completion
4556
4843
  description: >
4557
- Returns the workspace-scoped journey progress state. Returns an empty `completedSteps`
4558
- list with a synthetic `updatedAt` if no row exists yet. Covers issue #271.
4844
+ Returns the workspace-scoped journey progress state. Returns an empty `completedStepIds`
4845
+ array when no row exists yet (updatedAt is synthetic in that case). Values are canonical
4846
+ step IDs (see `JourneyStepId`); legacy route strings are accepted on PUT and normalized.
4847
+ Covers issue #271.
4559
4848
  operationId: getYourAiJourneyProgress
4560
4849
  parameters:
4561
4850
  - $ref: "#/components/parameters/WorkspaceId"
@@ -4860,6 +5149,19 @@ components:
4860
5149
  schema:
4861
5150
  type: string
4862
5151
  format: uuid
5152
+ ProviderSlug:
5153
+ name: providerSlug
5154
+ in: path
5155
+ required: true
5156
+ description: >
5157
+ Provider repository slug in `owner/repo` form (GitHub). Used for shareable public URLs;
5158
+ resolves to the same row as `repoId` UUID internally.
5159
+ schema:
5160
+ type: string
5161
+ minLength: 1
5162
+ maxLength: 512
5163
+ pattern: '^[^/]+/[^/]+$'
5164
+ example: thinkai-llc/thinkai-platform-backend
4863
5165
  ProjectId:
4864
5166
  name: projectId
4865
5167
  in: path
@@ -5732,16 +6034,6 @@ components:
5732
6034
  type: number
5733
6035
  failRatePercent:
5734
6036
  type: number
5735
- description: DORA change failure rate (deployments/incidents), not CI build failures.
5736
- ciFailRatePercent:
5737
- type: number
5738
- description: >
5739
- GitHub Actions / Checks CI build failure rate for the week bucket
5740
- (failed runs / (failed + passed) * 100). Zero when GitHub Actions CI is disabled.
5741
- ciBuildFailuresCount:
5742
- type: integer
5743
- minimum: 0
5744
- description: Count of build.failed events in the week bucket when CI ingest is enabled.
5745
6037
  avgReviewWaitHours:
5746
6038
  type: number
5747
6039
  description: Mean hours from PR creation to first review in this week bucket.
@@ -5801,9 +6093,6 @@ components:
5801
6093
  generatedAt:
5802
6094
  type: string
5803
6095
  format: date-time
5804
- githubActionsCiEnabled:
5805
- type: boolean
5806
- description: True when the workspace has opted in to GitHub Actions CI ingest.
5807
6096
  teams:
5808
6097
  type: array
5809
6098
  items:
@@ -5897,9 +6186,6 @@ components:
5897
6186
  avgFailRatePercent:
5898
6187
  type: number
5899
6188
  description: Average change failure rate over the range when available.
5900
- avgCiFailRatePercent:
5901
- type: number
5902
- description: Average GitHub Actions CI build failure rate over the range when CI ingest is enabled.
5903
6189
 
5904
6190
  ProductivityInsightsTeamSummaryDto:
5905
6191
  type: object
@@ -5912,10 +6198,6 @@ components:
5912
6198
  type: number
5913
6199
  avgFailRatePercent:
5914
6200
  type: number
5915
- description: Average DORA change failure rate over the range when available.
5916
- avgCiFailRatePercent:
5917
- type: number
5918
- description: Average GitHub Actions CI build failure rate over the range when CI ingest is enabled.
5919
6201
  headcount:
5920
6202
  type: integer
5921
6203
  minimum: 0
@@ -5976,9 +6258,6 @@ components:
5976
6258
  generatedAt:
5977
6259
  type: string
5978
6260
  format: date-time
5979
- githubActionsCiEnabled:
5980
- type: boolean
5981
- description: True when the workspace has opted in to GitHub Actions CI ingest.
5982
6261
  items:
5983
6262
  type: array
5984
6263
  description: Present when `teamId` query is omitted — top-ranked teams.
@@ -6100,10 +6379,6 @@ components:
6100
6379
  minimum: 0
6101
6380
  avgFailRate:
6102
6381
  type: number
6103
- description: Average DORA change failure rate over the range when available.
6104
- avgCiFailRate:
6105
- type: number
6106
- description: Average GitHub Actions CI build failure rate over the range when CI ingest is enabled.
6107
6382
  mergedPrDelta:
6108
6383
  type: number
6109
6384
  avgMergedPrsPerWeekDelta:
@@ -6112,9 +6387,6 @@ components:
6112
6387
  type: number
6113
6388
  avgFailRateDelta:
6114
6389
  type: number
6115
- avgCiFailRateDelta:
6116
- type: number
6117
- description: Change in average CI build failure rate vs the prior comparison window.
6118
6390
 
6119
6391
  ProductivityInsightsContributorDetailDto:
6120
6392
  type: object
@@ -6146,9 +6418,6 @@ components:
6146
6418
  generatedAt:
6147
6419
  type: string
6148
6420
  format: date-time
6149
- githubActionsCiEnabled:
6150
- type: boolean
6151
- description: True when the workspace has opted in to GitHub Actions CI ingest.
6152
6421
  contributor:
6153
6422
  $ref: "#/components/schemas/ProductivityInsightsContributorProfileDto"
6154
6423
  weeks:
@@ -6185,9 +6454,6 @@ components:
6185
6454
  avgFailRatePercent:
6186
6455
  type: number
6187
6456
  description: Mean weekly change-failure rate when available.
6188
- avgCiFailRatePercent:
6189
- type: number
6190
- description: Mean weekly GitHub Actions CI build failure rate when CI ingest is enabled.
6191
6457
 
6192
6458
  ProductivityInsightsNeedsAttentionDto:
6193
6459
  type: object
@@ -6207,9 +6473,6 @@ components:
6207
6473
  generatedAt:
6208
6474
  type: string
6209
6475
  format: date-time
6210
- githubActionsCiEnabled:
6211
- type: boolean
6212
- description: True when GitHub Actions CI ingest is enabled for this workspace.
6213
6476
  items:
6214
6477
  type: array
6215
6478
  items:
@@ -6843,6 +7106,195 @@ components:
6843
7106
  format: date-time
6844
7107
  nullable: true
6845
7108
  description: Last push or metadata update from GitHub when available.
7109
+ archived:
7110
+ type: boolean
7111
+ nullable: true
7112
+ description: True when the repository is archived (read-only on GitHub).
7113
+ fork:
7114
+ type: boolean
7115
+ nullable: true
7116
+ description: True when the repository is a fork of another repository.
7117
+ disabled:
7118
+ type: boolean
7119
+ nullable: true
7120
+ description: True when the repository is disabled on GitHub.
7121
+ size:
7122
+ type: integer
7123
+ nullable: true
7124
+ description: Repository size in KB as reported by GitHub.
7125
+ ineligibleReasons:
7126
+ type: array
7127
+ nullable: true
7128
+ items:
7129
+ type: string
7130
+ description: >
7131
+ Hard structural reasons this repo cannot be analyzed (archived, disabled, too-large,
7132
+ workspace repo cap). Each entry is a human-readable explanation (e.g. "This repo is
7133
+ archived"). Empty or absent means no hard block. Forks and unsupported-language repos
7134
+ are NOT listed here — they are advisory `warnings` (#729) and remain analyzable.
7135
+ warnings:
7136
+ type: array
7137
+ nullable: true
7138
+ items:
7139
+ type: string
7140
+ description: >
7141
+ Non-blocking advisories shown alongside an otherwise-analyzable repo (#729). Includes
7142
+ forks ("results reflect the forked code") and repos with no v1-supported stack, where
7143
+ the message embeds the GitHub language mix in percent. Absent/empty when there are no
7144
+ warnings. Unlike `ineligibleReasons`, warnings do NOT disable analyze/score/fix actions.
7145
+ eligibilityStatus:
7146
+ type: string
7147
+ enum: [eligible, ineligible]
7148
+ nullable: true
7149
+ description: >
7150
+ Whether the repo can be analyzed (issue #44/#729). `ineligible` only for HARD
7151
+ structural gates (archived, disabled, too-large, workspace repo cap) — such repos render
7152
+ read-only in the AF list. A repo with no supported stack or that is a fork is `eligible`
7153
+ and carries a non-blocking `warnings` entry instead of being blocked.
7154
+ eligibilityReason:
7155
+ type: string
7156
+ nullable: true
7157
+ description: >
7158
+ Human-readable explanation when `eligibilityStatus` is `ineligible` (e.g. "This repo
7159
+ is archived"). For advisory language/fork notices see `warnings`, not this field.
7160
+ primaryStack:
7161
+ type: string
7162
+ nullable: true
7163
+ description: >
7164
+ Dominant supported stack (by GitHub language bytes), one of
7165
+ backend_jvm | ios_app | web_spa | backend_go | backend_python. Null when no supported
7166
+ stack was detected.
7167
+ secondaryStack:
7168
+ type: string
7169
+ nullable: true
7170
+ description: Second supported stack for a multi-stack repo, or null.
7171
+ supportedStacks:
7172
+ type: array
7173
+ nullable: true
7174
+ items:
7175
+ type: string
7176
+ description: >
7177
+ All supported stacks detected for the repo (ordered, primary first). Empty/null
7178
+ when no supported stack is present. Drives multi-stack scanning and the orange
7179
+ mixed-monorepo box in the AF UI.
7180
+ languageBreakdown:
7181
+ type: array
7182
+ nullable: true
7183
+ description: >
7184
+ Per-language share of the repo from GitHub's `GET /repos/{owner}/{repo}/languages`
7185
+ byte counts, ordered by share descending (#729). Powers the "language mix" shown in
7186
+ the unsupported-stack warning. Absent/null until the repo has been synced with a
7187
+ language resolver.
7188
+ items:
7189
+ type: object
7190
+ required: [language, percent, supported]
7191
+ properties:
7192
+ language:
7193
+ type: string
7194
+ description: GitHub language name (e.g. "TypeScript", "Go").
7195
+ percent:
7196
+ type: number
7197
+ format: float
7198
+ description: >
7199
+ Share of total language bytes, rounded to four decimal places (e.g. 64.2153). The
7200
+ extra precision keeps small/near-tied languages distinguishable for a hover tag;
7201
+ render it rounded for compact labels. May not sum to exactly 100 due to rounding.
7202
+ supported:
7203
+ type: boolean
7204
+ description: >
7205
+ True when this language maps to a v1-supported stack; false when the language
7206
+ is not supported. Lets the UI flag exactly which languages are not (fully)
7207
+ supported in a mixed/monorepo.
7208
+ stack:
7209
+ type: string
7210
+ nullable: true
7211
+ description: >
7212
+ The supported stack this language maps to
7213
+ (backend_jvm | ios_app | web_spa | backend_go | backend_python), or null when
7214
+ the language is unsupported.
7215
+
7216
+ RepoEligibilityConfigDto:
7217
+ type: object
7218
+ description: Resolved repo-sync eligibility gate (defaults or effective). All fields present.
7219
+ required: [excludeArchived, excludeForks, maxRepoSizeKb, maxReposPerWorkspace]
7220
+ properties:
7221
+ excludeArchived:
7222
+ type: boolean
7223
+ description: Skip archived repos during GitHub repo sync.
7224
+ excludeForks:
7225
+ type: boolean
7226
+ description: Skip forked repos. Forks are included by default.
7227
+ maxRepoSizeKb:
7228
+ type: integer
7229
+ description: Max repo size in KB (GitHub-reported). 0 = no limit.
7230
+ maxReposPerWorkspace:
7231
+ type: integer
7232
+ description: Max repos materialized per workspace per sync. 0 = no limit.
7233
+
7234
+ RepoEligibilityOverridesDto:
7235
+ type: object
7236
+ additionalProperties: false
7237
+ description: >
7238
+ Per-workspace overrides for the repo-sync eligibility gate. Any field present wins over the
7239
+ global default; omit a field to inherit the default. An empty object clears all overrides.
7240
+ properties:
7241
+ excludeArchived:
7242
+ type: boolean
7243
+ nullable: true
7244
+ excludeForks:
7245
+ type: boolean
7246
+ nullable: true
7247
+ maxRepoSizeKb:
7248
+ type: integer
7249
+ minimum: 0
7250
+ nullable: true
7251
+ maxReposPerWorkspace:
7252
+ type: integer
7253
+ minimum: 0
7254
+ nullable: true
7255
+
7256
+ WorkspaceRepoEligibilityDto:
7257
+ type: object
7258
+ required: [defaults, overrides, effective, canEditUnrestricted]
7259
+ properties:
7260
+ defaults:
7261
+ $ref: "#/components/schemas/RepoEligibilityConfigDto"
7262
+ overrides:
7263
+ $ref: "#/components/schemas/RepoEligibilityOverridesDto"
7264
+ effective:
7265
+ $ref: "#/components/schemas/RepoEligibilityConfigDto"
7266
+ canEditUnrestricted:
7267
+ type: boolean
7268
+ description: True when the caller is a platform admin (may set any value, incl. raising caps).
7269
+
7270
+ RepoEligibilityLimitsDto:
7271
+ type: object
7272
+ additionalProperties: false
7273
+ description: >
7274
+ Effective repo-eligibility limits applied to the GitHub repo list, plus the current count
7275
+ of eligible repos. Lets the UI render per-repo "size / limit" (compare each repo's `size`
7276
+ in `GithubInstalledRepoDto` to `maxRepoSizeKb`) and workspace "N / cap" usage
7277
+ (`eligibleRepoCount` / `maxReposPerWorkspace`).
7278
+ required: [maxRepoSizeKb, maxReposPerWorkspace, excludeArchived, excludeForks, eligibleRepoCount]
7279
+ properties:
7280
+ maxRepoSizeKb:
7281
+ type: integer
7282
+ description: Per-repo size cap in KB (GitHub-reported). 0 = no limit.
7283
+ maxReposPerWorkspace:
7284
+ type: integer
7285
+ description: Max repos that can be eligible per workspace. 0 = no limit.
7286
+ excludeArchived:
7287
+ type: boolean
7288
+ description: Whether archived repos are treated as a hard block.
7289
+ excludeForks:
7290
+ type: boolean
7291
+ description: Whether forked repos are excluded by the sync gate (forks are a warning, not a block).
7292
+ eligibleRepoCount:
7293
+ type: integer
7294
+ minimum: 0
7295
+ description: >
7296
+ Repos currently counting as eligible (eligibilityStatus != "ineligible"), i.e. those that
7297
+ count toward `maxReposPerWorkspace`.
6846
7298
 
6847
7299
  GithubMissingPermissionDto:
6848
7300
  type: object
@@ -7013,6 +7465,14 @@ components:
7013
7465
  allOf:
7014
7466
  - $ref: "#/components/schemas/GithubInstalledRepoListDto"
7015
7467
  description: Paginated merged installation repositories when `installed` is true.
7468
+ eligibilityLimits:
7469
+ nullable: true
7470
+ allOf:
7471
+ - $ref: "#/components/schemas/RepoEligibilityLimitsDto"
7472
+ description: >
7473
+ Effective size/count limits and current eligible-repo usage for the repo list. Present
7474
+ when `installed` is true. Pair with each repo's `size` and `eligibilityStatus` to show
7475
+ "size / limit" and "N / cap" in the UI.
7016
7476
  manageUrl:
7017
7477
  type: string
7018
7478
  format: uri
@@ -7685,10 +8145,8 @@ components:
7685
8145
  type: array
7686
8146
  description: >
7687
8147
  Individual rubric criterion outcomes from the latest successful scan.
7688
- Always present on the single-repo detail endpoint. When the repo has a
7689
- succeeded scan but a dimension was not evaluated (e.g. Section I on older
7690
- runs), the API returns full rubric placeholders with status `blocked`.
7691
- Empty array only when the repo has no succeeded scan yet.
8148
+ Always present on the single-repo detail endpoint; empty array when no
8149
+ scan has completed yet for this dimension.
7692
8150
  items:
7693
8151
  $ref: "#/components/schemas/CriterionDetailDto"
7694
8152
  issues:
@@ -7873,6 +8331,79 @@ components:
7873
8331
  nullable: true
7874
8332
  enum: [github_removed, installation_disconnected, installation_replaced, superseded]
7875
8333
  description: Why the repo was archived. Only present when `archivedAt` is set.
8334
+ eligibilityStatus:
8335
+ type: string
8336
+ enum: [eligible, ineligible]
8337
+ nullable: true
8338
+ description: >
8339
+ Whether the repo can be analyzed (#44/#729). Language support no longer makes a repo
8340
+ `ineligible` — a missing v1-supported stack is surfaced via `warnings` and the repo
8341
+ stays analyzable. It becomes `ineligible` when the most recent scan hit a hard
8342
+ size/file-count limit (e.g. code-size or file-count exceeded): the repo is then
8343
+ restricted here too so this surface matches the GitHub connect list's size gate after
8344
+ the scan. Null until the first sync/scan computes it.
8345
+ eligibilityReason:
8346
+ type: string
8347
+ nullable: true
8348
+ description: >
8349
+ Human-readable explanation when `eligibilityStatus` is `ineligible` (e.g. the size /
8350
+ file-count limit message from the last scan). For advisory language notices see
8351
+ `warnings`.
8352
+ warnings:
8353
+ type: array
8354
+ nullable: true
8355
+ items:
8356
+ type: string
8357
+ description: >
8358
+ Non-blocking advisories for an analyzable repo (#729): no v1-supported stack (with the
8359
+ language mix), and hard-limit run outcomes (code size / file count exceeded) carried from
8360
+ the last run. Absent/empty when there are no warnings.
8361
+ primaryStack:
8362
+ type: string
8363
+ nullable: true
8364
+ description: Dominant supported stack — backend_jvm | ios_app | web_spa | backend_go | backend_python. Null when no supported stack/uncomputed.
8365
+ secondaryStack:
8366
+ type: string
8367
+ nullable: true
8368
+ description: Second supported stack for a multi-stack repo, or null.
8369
+ supportedStacks:
8370
+ type: array
8371
+ nullable: true
8372
+ items:
8373
+ type: string
8374
+ description: All supported stacks detected (ordered, primary first). Empty/null when none.
8375
+ languageBreakdown:
8376
+ type: array
8377
+ nullable: true
8378
+ description: >
8379
+ Per-language share from GitHub languages (#729), ordered by share descending. Each entry
8380
+ has `supported`/`stack` so the UI can tag which languages are (not) supported. Absent
8381
+ until the repo has been synced with a language resolver.
8382
+ items:
8383
+ type: object
8384
+ required: [language, percent, supported]
8385
+ properties:
8386
+ language:
8387
+ type: string
8388
+ percent:
8389
+ type: number
8390
+ format: float
8391
+ description: Share of total language bytes, rounded to four decimal places (e.g. 64.2153).
8392
+ supported:
8393
+ type: boolean
8394
+ stack:
8395
+ type: string
8396
+ nullable: true
8397
+ sizeKb:
8398
+ type: integer
8399
+ nullable: true
8400
+ minimum: 0
8401
+ description: >
8402
+ GitHub-reported repository size in KB (includes git history), refreshed on each readiness
8403
+ scan (#729). Compare against `eligibilityLimits.maxRepoSizeKb` on the list response to show
8404
+ per-repo "size / limit". When the size exceeds the limit the latest scan is recorded as
8405
+ `partial_failed` with `lastRunErrorCode = exceeded_repo_size_limit` and the repo is marked
8406
+ `ineligible`. Null until a scan has populated it.
7876
8407
 
7877
8408
  RepoReadinessScoreDetailDto:
7878
8409
  type: object
@@ -7943,6 +8474,55 @@ components:
7943
8474
  type: string
7944
8475
  nullable: true
7945
8476
  enum: [github_removed, installation_disconnected, installation_replaced, superseded]
8477
+ eligibilityStatus:
8478
+ type: string
8479
+ enum: [eligible, ineligible]
8480
+ nullable: true
8481
+ description: See RepoReadinessScoreDto.eligibilityStatus. Language support is advisory (#729) and surfaced via `warnings`.
8482
+ eligibilityReason:
8483
+ type: string
8484
+ nullable: true
8485
+ warnings:
8486
+ type: array
8487
+ nullable: true
8488
+ items:
8489
+ type: string
8490
+ description: Non-blocking advisories (no v1-supported stack, hard-limit run outcomes). See RepoReadinessScoreDto.warnings.
8491
+ primaryStack:
8492
+ type: string
8493
+ nullable: true
8494
+ secondaryStack:
8495
+ type: string
8496
+ nullable: true
8497
+ supportedStacks:
8498
+ type: array
8499
+ nullable: true
8500
+ items:
8501
+ type: string
8502
+ languageBreakdown:
8503
+ type: array
8504
+ nullable: true
8505
+ description: Per-language share with `supported`/`stack` tags. See RepoReadinessScoreDto.languageBreakdown.
8506
+ items:
8507
+ type: object
8508
+ required: [language, percent, supported]
8509
+ properties:
8510
+ language:
8511
+ type: string
8512
+ percent:
8513
+ type: number
8514
+ format: float
8515
+ description: Share of total language bytes, rounded to four decimal places (e.g. 64.2153).
8516
+ supported:
8517
+ type: boolean
8518
+ stack:
8519
+ type: string
8520
+ nullable: true
8521
+ sizeKb:
8522
+ type: integer
8523
+ nullable: true
8524
+ minimum: 0
8525
+ description: GitHub-reported repository size in KB, refreshed on each scan. See RepoReadinessScoreDto.sizeKb.
7946
8526
 
7947
8527
  AgenticFoundationDashboardSummaryDto:
7948
8528
  type: object
@@ -8006,6 +8586,34 @@ components:
8006
8586
  type: integer
8007
8587
  minimum: 0
8008
8588
 
8589
+ ReadinessEligibilityLimitsDto:
8590
+ type: object
8591
+ additionalProperties: false
8592
+ description: >
8593
+ Effective size/code limits enforced by readiness scans (#729). Lets the UI render per-repo
8594
+ "size / limit" (compare each repo's `sizeKb` to `maxRepoSizeKb`) and explain why a repo is
8595
+ `ineligible` due to a hard size/file-count limit. A repo over `maxRepoSizeKb` is skipped on the
8596
+ next scan (recorded `partial_failed` with `exceeded_repo_size_limit`); code-line/file counts are
8597
+ evaluated post-clone via `cloc`.
8598
+ required: [maxRepoSizeKb, maxLinesOfCode, maxFileCount, maxReposPerWorkspace]
8599
+ properties:
8600
+ maxRepoSizeKb:
8601
+ type: integer
8602
+ minimum: 0
8603
+ description: Per-repo GitHub size cap in KB (includes git history). 0 = no limit.
8604
+ maxLinesOfCode:
8605
+ type: integer
8606
+ minimum: 0
8607
+ description: Max total lines of code (cloc) before a scan is skipped. 0 = no limit.
8608
+ maxFileCount:
8609
+ type: integer
8610
+ minimum: 0
8611
+ description: Max source file count (cloc) before a scan is skipped. 0 = no limit.
8612
+ maxReposPerWorkspace:
8613
+ type: integer
8614
+ minimum: 0
8615
+ description: Max repos that can be eligible per workspace. 0 = no limit.
8616
+
8009
8617
  ReadinessRepoListDto:
8010
8618
  allOf:
8011
8619
  - $ref: "#/components/schemas/PageMetaDto"
@@ -8016,6 +8624,8 @@ components:
8016
8624
  type: array
8017
8625
  items:
8018
8626
  $ref: "#/components/schemas/RepoReadinessScoreDto"
8627
+ eligibilityLimits:
8628
+ $ref: "#/components/schemas/ReadinessEligibilityLimitsDto"
8019
8629
 
8020
8630
  ReadinessRepoDetailListDto:
8021
8631
  description: >
@@ -8584,12 +9194,38 @@ components:
8584
9194
  items:
8585
9195
  $ref: "#/components/schemas/AiStrategyPhaseBlockDto"
8586
9196
 
9197
+ JourneyStepId:
9198
+ type: string
9199
+ description: Canonical journey step identifier (stable across URL reshuffles).
9200
+ enum:
9201
+ - onboarding.workspace
9202
+ - onboarding.ai_readiness
9203
+ - onboarding.integrations
9204
+ - readiness.dashboard
9205
+ - readiness.fix_queue
9206
+ - readiness.activity
9207
+ - insights.productivity
9208
+ - insights.productivity.by_user
9209
+ - insights.productivity.by_team
9210
+ - insights.ai_usage
9211
+ - insights.ai_usage.by_user
9212
+ - insights.ai_usage.by_team
9213
+ - insights.ai_usage.by_model
9214
+
8587
9215
  JourneyProgressDto:
8588
9216
  type: object
8589
- required: [completedSteps, updatedAt]
9217
+ required: [completedStepIds, updatedAt]
8590
9218
  properties:
9219
+ completedStepIds:
9220
+ type: array
9221
+ items:
9222
+ $ref: "#/components/schemas/JourneyStepId"
9223
+ description: Canonical completed journey step IDs.
8591
9224
  completedSteps:
8592
9225
  type: array
9226
+ deprecated: true
9227
+ description: >
9228
+ Deprecated alias of completedStepIds (legacy clients). Omitted on new responses when empty.
8593
9229
  items:
8594
9230
  type: string
8595
9231
  updatedAt:
@@ -8598,12 +9234,22 @@ components:
8598
9234
 
8599
9235
  JourneyProgressUpdateDto:
8600
9236
  type: object
8601
- required: [completedSteps]
8602
9237
  properties:
9238
+ completedStepIds:
9239
+ type: array
9240
+ items:
9241
+ $ref: "#/components/schemas/JourneyStepId"
9242
+ description: Idempotent replace-all of completed step IDs.
8603
9243
  completedSteps:
8604
9244
  type: array
9245
+ deprecated: true
9246
+ description: >
9247
+ Deprecated input alias — route strings and legacy `/phase-*` paths are normalized to step IDs.
8605
9248
  items:
8606
9249
  type: string
9250
+ anyOf:
9251
+ - required: [completedStepIds]
9252
+ - required: [completedSteps]
8607
9253
 
8608
9254
  ThemePreference:
8609
9255
  type: string
@@ -8852,10 +9498,15 @@ components:
8852
9498
  format: date-time
8853
9499
  journey:
8854
9500
  type: object
8855
- required: [completedSteps, updatedAt]
9501
+ required: [completedStepIds, updatedAt]
8856
9502
  properties:
9503
+ completedStepIds:
9504
+ type: array
9505
+ items:
9506
+ $ref: "#/components/schemas/JourneyStepId"
8857
9507
  completedSteps:
8858
9508
  type: array
9509
+ deprecated: true
8859
9510
  items:
8860
9511
  type: string
8861
9512
  updatedAt:
@@ -9003,18 +9654,39 @@ components:
9003
9654
  - readiness.scan_completed
9004
9655
  - readiness.scan_failed
9005
9656
  - readiness.scan_partial
9006
- - config.cursor.added
9007
- - config.cursor.updated
9008
- - config.cursor.removed
9009
- - config.cursor.platform_key_enabled
9010
- - config.cursor.platform_key_disabled
9011
- - config.claude.added
9012
- - config.claude.updated
9013
- - config.claude.removed
9014
- - config.agent_execution.provider_changed
9657
+ - integrations.agent_execution.provider_changed
9658
+ - integrations.repo_eligibility.overrides_changed
9659
+ - integrations.repo_eligibility.languages_refresh_requested
9660
+ - integrations.cursor.platform_key_enabled
9661
+ - integrations.cursor.platform_key_disabled
9015
9662
  - member.invited
9016
9663
  - member.role_changed
9017
9664
  - member.removed
9665
+ - hris.personio.sync_started
9666
+ - hris.personio.sync_completed
9667
+ - hris.personio.sync_failed
9668
+ - hris.sync_started
9669
+ - hris.sync_completed
9670
+ - hris.sync_failed
9671
+ - repo.sync_skipped
9672
+ - integrations.cursor.execution_key.added
9673
+ - integrations.cursor.execution_key.updated
9674
+ - integrations.cursor.execution_key.removed
9675
+ - integrations.cursor.execution_key.check_failed
9676
+ - integrations.cursor.admin_key.added
9677
+ - integrations.cursor.admin_key.updated
9678
+ - integrations.cursor.admin_key.removed
9679
+ - integrations.claude.execution_key.added
9680
+ - integrations.claude.execution_key.updated
9681
+ - integrations.claude.execution_key.removed
9682
+ - integrations.claude.execution_key.check_failed
9683
+ - integrations.claude.admin_key.added
9684
+ - integrations.claude.admin_key.updated
9685
+ - integrations.claude.admin_key.removed
9686
+ - readiness.scan_precheck_failed
9687
+ - productivity.ingest.completed
9688
+ - productivity.ingest.failed
9689
+ - productivity.ingest.skipped
9018
9690
 
9019
9691
  ActivityLogActorDto:
9020
9692
  type: object