@thinkai/tai-api-contract 2.125.0 → 2.127.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.
@@ -1,7 +1,7 @@
1
1
  openapi: 3.0.3
2
2
  info:
3
3
  title: ThinkAI API
4
- version: 2.125.0
4
+ version: 2.127.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}/...`.
@@ -86,6 +86,12 @@ tags:
86
86
  (LOC, cyclomatic complexity, duplication), hotspots, and playbook-threshold
87
87
  findings collected during readiness scans. Every metric carries
88
88
  `measured | derived | estimated | unavailable` provenance.
89
+ - name: TestPyramidInsights
90
+ description: >
91
+ Test pyramid assessment (`/insights/test-pyramid`) — workspace and per-repo
92
+ classified test-file inventory (unit, integration, acceptance/BDD, contract, E2E)
93
+ with count-based presence and advisory 70/20/10 shape. Distinct from Agentic
94
+ Foundation readiness `/readiness/test-pyramid*` (signal-inclusive presence).
89
95
 
90
96
  paths:
91
97
  /admin/users/{userId}:
@@ -3831,6 +3837,84 @@ paths:
3831
3837
  schema:
3832
3838
  $ref: "#/components/schemas/ErrorMessageDto"
3833
3839
 
3840
+ /workspaces/{workspaceId}/insights/test-pyramid/summary:
3841
+ get:
3842
+ tags: [TestPyramidInsights]
3843
+ summary: Test pyramid assessment — workspace summary
3844
+ operationId: getInsightsTestPyramidSummary
3845
+ description: >
3846
+ Org-level Test pyramid assessment for `/insights/test-pyramid`. Aggregates each
3847
+ active repo's **latest** readiness-scan test-pyramid snapshot. Layer **presence
3848
+ is count-based** (`fileCount > 0`); CI/dependency-only AF `present` flags are
3849
+ ignored. Shape uses fixed advisory targets (base ~70% unit, middle ~20%
3850
+ integration+contract+acceptance/BDD, top ~10% E2E) and returns
3851
+ `insufficient_data` when total classified test files < 10. Does not change
3852
+ Agentic Foundation `/readiness/test-pyramid*` responses.
3853
+ parameters:
3854
+ - $ref: "#/components/parameters/WorkspaceId"
3855
+ responses:
3856
+ "200":
3857
+ description: Test pyramid assessment workspace summary
3858
+ content:
3859
+ application/json:
3860
+ schema:
3861
+ $ref: "#/components/schemas/InsightsTestPyramidSummaryDto"
3862
+ "401":
3863
+ $ref: "#/components/responses/Unauthorized"
3864
+ "403":
3865
+ $ref: "#/components/responses/Forbidden"
3866
+ "404":
3867
+ description: Workspace does not exist or malformed workspaceId
3868
+ "501":
3869
+ description: Test pyramid history not supported by store
3870
+ content:
3871
+ application/json:
3872
+ schema:
3873
+ $ref: "#/components/schemas/ErrorMessageDto"
3874
+
3875
+ /workspaces/{workspaceId}/insights/test-pyramid/repos:
3876
+ get:
3877
+ tags: [TestPyramidInsights]
3878
+ summary: Test pyramid assessment — per-repo list (paginated)
3879
+ operationId: listInsightsTestPyramidRepos
3880
+ description: >
3881
+ Page of repos with latest classified test-file counts, count-based presence,
3882
+ presence maturity, and shape assessment. Use `gapsByLayer` on the summary
3883
+ endpoint (or filter this list via layerPresent) to answer “who lacks layer X?”.
3884
+ No v1 repo-detail Insights route — link repo names to AF readiness inventory.
3885
+ parameters:
3886
+ - $ref: "#/components/parameters/WorkspaceId"
3887
+ - $ref: "#/components/parameters/PaginationLimit"
3888
+ - $ref: "#/components/parameters/PaginationOffset"
3889
+ - $ref: "#/components/parameters/InsightsTestPyramidRepoSort"
3890
+ - $ref: "#/components/parameters/PaginationOrder"
3891
+ - $ref: "#/components/parameters/InsightsTestPyramidRepoSearch"
3892
+ responses:
3893
+ "200":
3894
+ description: Paginated test pyramid assessment repo rows
3895
+ content:
3896
+ application/json:
3897
+ schema:
3898
+ $ref: "#/components/schemas/InsightsTestPyramidRepoListDto"
3899
+ "400":
3900
+ description: Invalid pagination or sort query
3901
+ content:
3902
+ application/json:
3903
+ schema:
3904
+ $ref: "#/components/schemas/ErrorMessageDto"
3905
+ "401":
3906
+ $ref: "#/components/responses/Unauthorized"
3907
+ "403":
3908
+ $ref: "#/components/responses/Forbidden"
3909
+ "404":
3910
+ description: Workspace does not exist or malformed workspaceId
3911
+ "501":
3912
+ description: Test pyramid history not supported by store
3913
+ content:
3914
+ application/json:
3915
+ schema:
3916
+ $ref: "#/components/schemas/ErrorMessageDto"
3917
+
3834
3918
  /workspaces/{workspaceId}/integrations/ai-tool/{provider}/members:
3835
3919
  get:
3836
3920
  tags: [Workspace]
@@ -6420,6 +6504,134 @@ paths:
6420
6504
  schema:
6421
6505
  $ref: "#/components/schemas/ErrorMessageDto"
6422
6506
 
6507
+ /workspaces/{workspaceId}/readiness/test-pyramid:
6508
+ get:
6509
+ tags: [RepositoryReadiness]
6510
+ summary: Latest test-pyramid report and progress per repository
6511
+ description: >
6512
+ Returns the latest test inventory for every repository with a pyramid snapshot,
6513
+ deltas from the previous and baseline scans, and workspace layer coverage.
6514
+ Repositories whose historical runs predate pyramid snapshots are omitted.
6515
+ operationId: getReadinessTestPyramid
6516
+ parameters:
6517
+ - $ref: "#/components/parameters/WorkspaceId"
6518
+ responses:
6519
+ "200":
6520
+ description: Latest test-pyramid report and progress
6521
+ content:
6522
+ application/json:
6523
+ schema:
6524
+ $ref: "#/components/schemas/WorkspaceTestPyramidProgressDto"
6525
+ "401":
6526
+ $ref: "#/components/responses/Unauthorized"
6527
+ "403":
6528
+ $ref: "#/components/responses/Forbidden"
6529
+ "404":
6530
+ description: Workspace does not exist
6531
+ content:
6532
+ application/json:
6533
+ schema:
6534
+ $ref: "#/components/schemas/ErrorMessageDto"
6535
+ "501":
6536
+ description: Readiness history is not supported by the configured store
6537
+ content:
6538
+ application/json:
6539
+ schema:
6540
+ $ref: "#/components/schemas/ErrorMessageDto"
6541
+
6542
+ /workspaces/{workspaceId}/readiness/test-pyramid/history:
6543
+ get:
6544
+ tags: [RepositoryReadiness]
6545
+ summary: Historical test-pyramid snapshots per repository
6546
+ description: >
6547
+ Returns succeeded readiness runs containing test-pyramid snapshots, ordered oldest
6548
+ to newest per repository. Older runs without snapshots are omitted, not treated as gaps.
6549
+ operationId: getReadinessTestPyramidHistory
6550
+ parameters:
6551
+ - $ref: "#/components/parameters/WorkspaceId"
6552
+ - name: since
6553
+ in: query
6554
+ schema:
6555
+ type: string
6556
+ format: date-time
6557
+ - name: limitPerRepo
6558
+ in: query
6559
+ schema:
6560
+ type: integer
6561
+ minimum: 1
6562
+ maximum: 200
6563
+ default: 50
6564
+ responses:
6565
+ "200":
6566
+ description: Test-pyramid history grouped by repository
6567
+ content:
6568
+ application/json:
6569
+ schema:
6570
+ $ref: "#/components/schemas/WorkspaceTestPyramidHistoryDto"
6571
+ "400":
6572
+ description: Invalid query
6573
+ content:
6574
+ application/json:
6575
+ schema:
6576
+ $ref: "#/components/schemas/ErrorMessageDto"
6577
+ "401":
6578
+ $ref: "#/components/responses/Unauthorized"
6579
+ "403":
6580
+ $ref: "#/components/responses/Forbidden"
6581
+ "501":
6582
+ description: Readiness history is not supported by the configured store
6583
+ content:
6584
+ application/json:
6585
+ schema:
6586
+ $ref: "#/components/schemas/ErrorMessageDto"
6587
+
6588
+ /workspaces/{workspaceId}/readiness/test-pyramid/progress:
6589
+ get:
6590
+ tags: [RepositoryReadiness]
6591
+ summary: Test-pyramid code progress from successive scans
6592
+ description: >
6593
+ Compares each repository's latest pyramid snapshot with its previous and baseline
6594
+ snapshots. Reports layer adoption/removal, file-count and Tests & QA score deltas,
6595
+ criterion changes, and current workspace coverage.
6596
+ operationId: getReadinessTestPyramidProgress
6597
+ parameters:
6598
+ - $ref: "#/components/parameters/WorkspaceId"
6599
+ - name: since
6600
+ in: query
6601
+ schema:
6602
+ type: string
6603
+ format: date-time
6604
+ - name: limitPerRepo
6605
+ in: query
6606
+ schema:
6607
+ type: integer
6608
+ minimum: 1
6609
+ maximum: 200
6610
+ default: 50
6611
+ responses:
6612
+ "200":
6613
+ description: Test-pyramid code progress
6614
+ content:
6615
+ application/json:
6616
+ schema:
6617
+ $ref: "#/components/schemas/WorkspaceTestPyramidProgressDto"
6618
+ "400":
6619
+ description: Invalid query
6620
+ content:
6621
+ application/json:
6622
+ schema:
6623
+ $ref: "#/components/schemas/ErrorMessageDto"
6624
+ "401":
6625
+ $ref: "#/components/responses/Unauthorized"
6626
+ "403":
6627
+ $ref: "#/components/responses/Forbidden"
6628
+ "501":
6629
+ description: Readiness history is not supported by the configured store
6630
+ content:
6631
+ application/json:
6632
+ schema:
6633
+ $ref: "#/components/schemas/ErrorMessageDto"
6634
+
6423
6635
  /workspaces/{workspaceId}/readiness/score-history:
6424
6636
  get:
6425
6637
  tags: [RepositoryReadiness]
@@ -9923,6 +10135,23 @@ components:
9923
10135
  description: Case-insensitive substring filter on repo name / provider slug.
9924
10136
  schema:
9925
10137
  type: string
10138
+ InsightsTestPyramidRepoSort:
10139
+ name: sort
10140
+ in: query
10141
+ required: false
10142
+ description: Allowlisted Test pyramid assessment repo sort field.
10143
+ schema:
10144
+ type: string
10145
+ enum: [repoName, totalClassifiedFiles, scannedAt, maturity]
10146
+ default: repoName
10147
+ InsightsTestPyramidRepoSearch:
10148
+ name: search
10149
+ in: query
10150
+ required: false
10151
+ description: Case-insensitive substring filter on repository name.
10152
+ schema:
10153
+ type: string
10154
+ maxLength: 256
9926
10155
  ReadinessRepoSearch:
9927
10156
  name: search
9928
10157
  in: query
@@ -15902,6 +16131,406 @@ components:
15902
16131
  maximum: 100
15903
16132
  description: Dimension score as a percentage (0–100) for this scan run.
15904
16133
 
16134
+ TestPyramidLayerSnapshotDto:
16135
+ type: object
16136
+ required: [present, applicable, confidence, fileCount, frameworks, evidence]
16137
+ properties:
16138
+ present:
16139
+ type: boolean
16140
+ applicable:
16141
+ type: boolean
16142
+ description: False when the repository archetype makes this layer not applicable.
16143
+ confidence:
16144
+ type: string
16145
+ enum: [high, medium, low]
16146
+ fileCount:
16147
+ type: integer
16148
+ minimum: 0
16149
+ frameworks:
16150
+ type: array
16151
+ items:
16152
+ type: string
16153
+ evidence:
16154
+ type: array
16155
+ maxItems: 8
16156
+ items:
16157
+ type: string
16158
+ description: Capped relative file paths or script names supporting the classification.
16159
+ lineCoverage:
16160
+ $ref: "#/components/schemas/TestPyramidLineCoverageDto"
16161
+
16162
+ TestPyramidLayersDto:
16163
+ type: object
16164
+ required: [unit, integration, acceptance_bdd, contract, e2e]
16165
+ properties:
16166
+ unit:
16167
+ $ref: "#/components/schemas/TestPyramidLayerSnapshotDto"
16168
+ integration:
16169
+ $ref: "#/components/schemas/TestPyramidLayerSnapshotDto"
16170
+ acceptance_bdd:
16171
+ $ref: "#/components/schemas/TestPyramidLayerSnapshotDto"
16172
+ contract:
16173
+ $ref: "#/components/schemas/TestPyramidLayerSnapshotDto"
16174
+ e2e:
16175
+ $ref: "#/components/schemas/TestPyramidLayerSnapshotDto"
16176
+
16177
+ TestPyramidSnapshotDto:
16178
+ type: object
16179
+ required: [version, layers, e2eCrossRepoCandidate, e2eReferencedTargets]
16180
+ properties:
16181
+ version:
16182
+ type: integer
16183
+ enum: [1]
16184
+ layers:
16185
+ $ref: "#/components/schemas/TestPyramidLayersDto"
16186
+ e2eCrossRepoCandidate:
16187
+ type: boolean
16188
+ description: Evidence suggests the repository's E2E suite exercises multiple services.
16189
+ e2eReferencedTargets:
16190
+ type: array
16191
+ maxItems: 20
16192
+ items:
16193
+ type: string
16194
+ description: Hostnames or compose service names referenced by the E2E suite.
16195
+ lineCoverage:
16196
+ $ref: "#/components/schemas/TestPyramidLineCoverageDto"
16197
+
16198
+ TestPyramidLineCoverageDto:
16199
+ type: object
16200
+ nullable: true
16201
+ required: [linePercent, branchPercent, source]
16202
+ properties:
16203
+ linePercent:
16204
+ type: number
16205
+ minimum: 0
16206
+ maximum: 100
16207
+ description: Line coverage percent from Sonar or a committed coverage report.
16208
+ branchPercent:
16209
+ type: number
16210
+ minimum: 0
16211
+ maximum: 100
16212
+ nullable: true
16213
+ source:
16214
+ type: string
16215
+ enum: [sonar, jacoco, lcov, cobertura, clover, go_cover]
16216
+ reportPath:
16217
+ type: string
16218
+ nullable: true
16219
+ description: Path of the scanned report when the source is not Sonar.
16220
+
16221
+ TestPyramidCriteriaDto:
16222
+ type: object
16223
+ properties:
16224
+ D1:
16225
+ type: string
16226
+ D2:
16227
+ type: string
16228
+ D3:
16229
+ type: string
16230
+ D4:
16231
+ type: string
16232
+
16233
+ TestPyramidRunStatusDto:
16234
+ type: string
16235
+ description: >-
16236
+ Run state the snapshot came from. The pyramid is derived from the filesystem scan, which
16237
+ finishes before rubric grading, so `partial_failed` and `failed` runs still carry a valid
16238
+ snapshot but no scores.
16239
+ enum: [succeeded, partial_failed, failed]
16240
+
16241
+ TestPyramidHistoryPointDto:
16242
+ type: object
16243
+ required:
16244
+ [finishedAt, runStatus, overallScore, testsQaPercent, testPyramid, testPyramidCriteria]
16245
+ properties:
16246
+ finishedAt:
16247
+ type: string
16248
+ format: date-time
16249
+ runStatus:
16250
+ $ref: "#/components/schemas/TestPyramidRunStatusDto"
16251
+ overallScore:
16252
+ type: integer
16253
+ minimum: 0
16254
+ maximum: 100
16255
+ nullable: true
16256
+ testsQaPercent:
16257
+ type: integer
16258
+ minimum: 0
16259
+ maximum: 100
16260
+ nullable: true
16261
+ testPyramid:
16262
+ $ref: "#/components/schemas/TestPyramidSnapshotDto"
16263
+ testPyramidCriteria:
16264
+ $ref: "#/components/schemas/TestPyramidCriteriaDto"
16265
+
16266
+ TestPyramidRepoHistoryDto:
16267
+ type: object
16268
+ required: [repoId, repoName, connectedAt, points]
16269
+ properties:
16270
+ repoId:
16271
+ type: string
16272
+ format: uuid
16273
+ repoName:
16274
+ type: string
16275
+ connectedAt:
16276
+ type: string
16277
+ format: date-time
16278
+ points:
16279
+ type: array
16280
+ items:
16281
+ $ref: "#/components/schemas/TestPyramidHistoryPointDto"
16282
+
16283
+ WorkspaceTestPyramidHistoryDto:
16284
+ type: object
16285
+ required: [workspaceId, generatedAt, repos]
16286
+ properties:
16287
+ workspaceId:
16288
+ type: string
16289
+ format: uuid
16290
+ generatedAt:
16291
+ type: string
16292
+ format: date-time
16293
+ repos:
16294
+ type: array
16295
+ items:
16296
+ $ref: "#/components/schemas/TestPyramidRepoHistoryDto"
16297
+
16298
+ TestPyramidLayerDeltaDto:
16299
+ type: object
16300
+ required: [presence, fileCountDelta, addedFrameworks]
16301
+ properties:
16302
+ presence:
16303
+ type: string
16304
+ enum: [unchanged, adopted, removed]
16305
+ fileCountDelta:
16306
+ type: integer
16307
+ addedFrameworks:
16308
+ type: array
16309
+ items:
16310
+ type: string
16311
+
16312
+ TestPyramidLayerDeltasDto:
16313
+ type: object
16314
+ required: [unit, integration, acceptance_bdd, contract, e2e]
16315
+ properties:
16316
+ unit:
16317
+ $ref: "#/components/schemas/TestPyramidLayerDeltaDto"
16318
+ integration:
16319
+ $ref: "#/components/schemas/TestPyramidLayerDeltaDto"
16320
+ acceptance_bdd:
16321
+ $ref: "#/components/schemas/TestPyramidLayerDeltaDto"
16322
+ contract:
16323
+ $ref: "#/components/schemas/TestPyramidLayerDeltaDto"
16324
+ e2e:
16325
+ $ref: "#/components/schemas/TestPyramidLayerDeltaDto"
16326
+
16327
+ TestPyramidCriterionDeltaDto:
16328
+ type: object
16329
+ required: [from, to]
16330
+ properties:
16331
+ from:
16332
+ type: string
16333
+ nullable: true
16334
+ to:
16335
+ type: string
16336
+
16337
+ TestPyramidCriterionDeltasDto:
16338
+ type: object
16339
+ properties:
16340
+ D1:
16341
+ $ref: "#/components/schemas/TestPyramidCriterionDeltaDto"
16342
+ D2:
16343
+ $ref: "#/components/schemas/TestPyramidCriterionDeltaDto"
16344
+ D3:
16345
+ $ref: "#/components/schemas/TestPyramidCriterionDeltaDto"
16346
+ D4:
16347
+ $ref: "#/components/schemas/TestPyramidCriterionDeltaDto"
16348
+
16349
+ TestPyramidRepoProgressDto:
16350
+ type: object
16351
+ required:
16352
+ - repoId
16353
+ - repoName
16354
+ - baselineAt
16355
+ - previousAt
16356
+ - currentAt
16357
+ - currentRunStatus
16358
+ - maturity
16359
+ - testsQaPercent
16360
+ - testsQaPercentDelta
16361
+ - layerDeltas
16362
+ - baselineLayerDeltas
16363
+ - criterionDeltas
16364
+ - testPyramid
16365
+ - testPyramidCriteria
16366
+ properties:
16367
+ repoId:
16368
+ type: string
16369
+ format: uuid
16370
+ repoName:
16371
+ type: string
16372
+ baselineAt:
16373
+ type: string
16374
+ format: date-time
16375
+ previousAt:
16376
+ type: string
16377
+ format: date-time
16378
+ nullable: true
16379
+ currentAt:
16380
+ type: string
16381
+ format: date-time
16382
+ currentRunStatus:
16383
+ $ref: "#/components/schemas/TestPyramidRunStatusDto"
16384
+ maturity:
16385
+ type: string
16386
+ enum: [missing, emerging, established, mature]
16387
+ testsQaPercent:
16388
+ type: integer
16389
+ minimum: 0
16390
+ maximum: 100
16391
+ nullable: true
16392
+ testsQaPercentDelta:
16393
+ type: integer
16394
+ nullable: true
16395
+ layerDeltas:
16396
+ $ref: "#/components/schemas/TestPyramidLayerDeltasDto"
16397
+ baselineLayerDeltas:
16398
+ $ref: "#/components/schemas/TestPyramidLayerDeltasDto"
16399
+ criterionDeltas:
16400
+ $ref: "#/components/schemas/TestPyramidCriterionDeltasDto"
16401
+ testPyramid:
16402
+ $ref: "#/components/schemas/TestPyramidSnapshotDto"
16403
+ testPyramidCriteria:
16404
+ $ref: "#/components/schemas/TestPyramidCriteriaDto"
16405
+ lineCoverage:
16406
+ $ref: "#/components/schemas/TestPyramidLineCoverageDto"
16407
+
16408
+ TestPyramidLayerCoverageDto:
16409
+ type: object
16410
+ required: [presentRepos, applicableRepos, percent, missingRepoIds]
16411
+ properties:
16412
+ presentRepos:
16413
+ type: integer
16414
+ minimum: 0
16415
+ applicableRepos:
16416
+ type: integer
16417
+ minimum: 0
16418
+ percent:
16419
+ type: integer
16420
+ minimum: 0
16421
+ maximum: 100
16422
+ nullable: true
16423
+ missingRepoIds:
16424
+ type: array
16425
+ items:
16426
+ type: string
16427
+ format: uuid
16428
+
16429
+ TestPyramidLayerCoverageMapDto:
16430
+ type: object
16431
+ required: [unit, integration, acceptance_bdd, contract, e2e]
16432
+ properties:
16433
+ unit:
16434
+ $ref: "#/components/schemas/TestPyramidLayerCoverageDto"
16435
+ integration:
16436
+ $ref: "#/components/schemas/TestPyramidLayerCoverageDto"
16437
+ acceptance_bdd:
16438
+ $ref: "#/components/schemas/TestPyramidLayerCoverageDto"
16439
+ contract:
16440
+ $ref: "#/components/schemas/TestPyramidLayerCoverageDto"
16441
+ e2e:
16442
+ $ref: "#/components/schemas/TestPyramidLayerCoverageDto"
16443
+
16444
+ TestPyramidMaturityCountsDto:
16445
+ type: object
16446
+ required: [missing, emerging, established, mature]
16447
+ properties:
16448
+ missing:
16449
+ type: integer
16450
+ minimum: 0
16451
+ emerging:
16452
+ type: integer
16453
+ minimum: 0
16454
+ established:
16455
+ type: integer
16456
+ minimum: 0
16457
+ mature:
16458
+ type: integer
16459
+ minimum: 0
16460
+
16461
+ TestPyramidCrossRepoMatchDto:
16462
+ type: object
16463
+ required: [sourceRepoId, targetRepoIds, referencedTargets]
16464
+ properties:
16465
+ sourceRepoId:
16466
+ type: string
16467
+ format: uuid
16468
+ targetRepoIds:
16469
+ type: array
16470
+ items:
16471
+ type: string
16472
+ format: uuid
16473
+ referencedTargets:
16474
+ type: array
16475
+ items:
16476
+ type: string
16477
+
16478
+ WorkspaceTestPyramidSummaryDto:
16479
+ type: object
16480
+ required:
16481
+ - reposWithPyramid
16482
+ - reposFromDegradedRuns
16483
+ - layerCoverage
16484
+ - maturityCounts
16485
+ - e2eCrossRepoCandidateRepoIds
16486
+ - e2eCrossRepoMatches
16487
+ - crossRepoE2ePresent
16488
+ properties:
16489
+ reposWithPyramid:
16490
+ type: integer
16491
+ minimum: 0
16492
+ reposFromDegradedRuns:
16493
+ type: array
16494
+ description: >-
16495
+ Repositories whose newest snapshot came from a run whose rubric grading did not
16496
+ complete. Their pyramid is valid but Tests & QA scores are unavailable.
16497
+ items:
16498
+ type: string
16499
+ format: uuid
16500
+ layerCoverage:
16501
+ $ref: "#/components/schemas/TestPyramidLayerCoverageMapDto"
16502
+ maturityCounts:
16503
+ $ref: "#/components/schemas/TestPyramidMaturityCountsDto"
16504
+ e2eCrossRepoCandidateRepoIds:
16505
+ type: array
16506
+ items:
16507
+ type: string
16508
+ format: uuid
16509
+ e2eCrossRepoMatches:
16510
+ type: array
16511
+ items:
16512
+ $ref: "#/components/schemas/TestPyramidCrossRepoMatchDto"
16513
+ crossRepoE2ePresent:
16514
+ type: boolean
16515
+ description: True only when an E2E target is matched to another repository in the workspace.
16516
+
16517
+ WorkspaceTestPyramidProgressDto:
16518
+ type: object
16519
+ required: [workspaceId, generatedAt, repos, workspace]
16520
+ properties:
16521
+ workspaceId:
16522
+ type: string
16523
+ format: uuid
16524
+ generatedAt:
16525
+ type: string
16526
+ format: date-time
16527
+ repos:
16528
+ type: array
16529
+ items:
16530
+ $ref: "#/components/schemas/TestPyramidRepoProgressDto"
16531
+ workspace:
16532
+ $ref: "#/components/schemas/WorkspaceTestPyramidSummaryDto"
16533
+
15905
16534
  ReadinessScoreHistoryPointDto:
15906
16535
  type: object
15907
16536
  required: [finishedAt, overallScore]
@@ -15918,6 +16547,10 @@ components:
15918
16547
  items:
15919
16548
  $ref: "#/components/schemas/ReadinessScoreHistoryDimensionScoreDto"
15920
16549
  description: Per-dimension percentages captured on this scan run.
16550
+ testPyramid:
16551
+ $ref: "#/components/schemas/TestPyramidSnapshotDto"
16552
+ testPyramidCriteria:
16553
+ $ref: "#/components/schemas/TestPyramidCriteriaDto"
15921
16554
 
15922
16555
  ReadinessRepoScoreHistoryDto:
15923
16556
  type: object
@@ -20976,3 +21609,206 @@ components:
20976
21609
  description: Org top-10 complexity hotspots by `ccMax` (current per-repo snapshots).
20977
21610
  sonar:
20978
21611
  $ref: "#/components/schemas/CodeInsightsSonarDto"
21612
+
21613
+ InsightsTestPyramidMaturityDto:
21614
+ type: string
21615
+ enum: [missing, emerging, established, mature]
21616
+ description: >
21617
+ Presence maturity (model A) using count-based layer presence
21618
+ (`fileCount > 0`), not AF signal-inclusive `present`.
21619
+
21620
+ InsightsTestPyramidShapeLabelDto:
21621
+ type: string
21622
+ enum: [insufficient_data, base_heavy, balanced, top_heavy, middle_heavy]
21623
+ description: >
21624
+ Advisory shape label vs fixed 70/20/10. `insufficient_data` when total
21625
+ classified test files < 10 (band percents are null).
21626
+
21627
+ InsightsTestPyramidShapeDto:
21628
+ type: object
21629
+ required: [label, totalClassifiedFiles, basePercent, middlePercent, topPercent, targets]
21630
+ properties:
21631
+ label:
21632
+ $ref: "#/components/schemas/InsightsTestPyramidShapeLabelDto"
21633
+ totalClassifiedFiles:
21634
+ type: integer
21635
+ minimum: 0
21636
+ description: Sum of classified test **files** across the five layers (not test cases).
21637
+ basePercent:
21638
+ type: number
21639
+ nullable: true
21640
+ description: Share of classified files in unit (base). Null when insufficient_data.
21641
+ middlePercent:
21642
+ type: number
21643
+ nullable: true
21644
+ description: >
21645
+ Share in integration + contract + acceptance_bdd (middle). Null when
21646
+ insufficient_data.
21647
+ topPercent:
21648
+ type: number
21649
+ nullable: true
21650
+ description: Share in e2e (top). Null when insufficient_data.
21651
+ targets:
21652
+ type: object
21653
+ required: [basePercent, middlePercent, topPercent]
21654
+ properties:
21655
+ basePercent: { type: number, enum: [70] }
21656
+ middlePercent: { type: number, enum: [20] }
21657
+ topPercent: { type: number, enum: [10] }
21658
+
21659
+ InsightsTestPyramidLayerCountsDto:
21660
+ type: object
21661
+ required: [unit, integration, acceptance_bdd, contract, e2e]
21662
+ properties:
21663
+ unit: { type: integer, minimum: 0 }
21664
+ integration: { type: integer, minimum: 0 }
21665
+ acceptance_bdd: { type: integer, minimum: 0 }
21666
+ contract: { type: integer, minimum: 0 }
21667
+ e2e: { type: integer, minimum: 0 }
21668
+
21669
+ InsightsTestPyramidLayerPresentDto:
21670
+ type: object
21671
+ required: [unit, integration, acceptance_bdd, contract, e2e]
21672
+ properties:
21673
+ unit: { type: boolean }
21674
+ integration: { type: boolean }
21675
+ acceptance_bdd: { type: boolean }
21676
+ contract: { type: boolean }
21677
+ e2e: { type: boolean }
21678
+
21679
+ InsightsTestPyramidLayerPresenceDto:
21680
+ type: object
21681
+ required: [presentRepos, applicableRepos, percent, missingRepoIds, missingRepoNames]
21682
+ properties:
21683
+ presentRepos: { type: integer, minimum: 0 }
21684
+ applicableRepos: { type: integer, minimum: 0 }
21685
+ percent:
21686
+ type: integer
21687
+ nullable: true
21688
+ minimum: 0
21689
+ maximum: 100
21690
+ missingRepoIds:
21691
+ type: array
21692
+ items: { type: string, format: uuid }
21693
+ missingRepoNames:
21694
+ type: array
21695
+ items: { type: string }
21696
+
21697
+ InsightsTestPyramidGapRepoDto:
21698
+ type: object
21699
+ required: [repoId, repoName]
21700
+ properties:
21701
+ repoId: { type: string, format: uuid }
21702
+ repoName: { type: string }
21703
+
21704
+ InsightsTestPyramidGapsByLayerDto:
21705
+ type: object
21706
+ required: [unit, integration, acceptance_bdd, contract, e2e]
21707
+ properties:
21708
+ unit:
21709
+ type: array
21710
+ items: { $ref: "#/components/schemas/InsightsTestPyramidGapRepoDto" }
21711
+ integration:
21712
+ type: array
21713
+ items: { $ref: "#/components/schemas/InsightsTestPyramidGapRepoDto" }
21714
+ acceptance_bdd:
21715
+ type: array
21716
+ items: { $ref: "#/components/schemas/InsightsTestPyramidGapRepoDto" }
21717
+ contract:
21718
+ type: array
21719
+ items: { $ref: "#/components/schemas/InsightsTestPyramidGapRepoDto" }
21720
+ e2e:
21721
+ type: array
21722
+ items: { $ref: "#/components/schemas/InsightsTestPyramidGapRepoDto" }
21723
+
21724
+ InsightsTestPyramidMaturityCountsDto:
21725
+ type: object
21726
+ required: [missing, emerging, established, mature]
21727
+ properties:
21728
+ missing: { type: integer, minimum: 0 }
21729
+ emerging: { type: integer, minimum: 0 }
21730
+ established: { type: integer, minimum: 0 }
21731
+ mature: { type: integer, minimum: 0 }
21732
+
21733
+ InsightsTestPyramidLayerPresenceMapDto:
21734
+ type: object
21735
+ required: [unit, integration, acceptance_bdd, contract, e2e]
21736
+ properties:
21737
+ unit: { $ref: "#/components/schemas/InsightsTestPyramidLayerPresenceDto" }
21738
+ integration: { $ref: "#/components/schemas/InsightsTestPyramidLayerPresenceDto" }
21739
+ acceptance_bdd: { $ref: "#/components/schemas/InsightsTestPyramidLayerPresenceDto" }
21740
+ contract: { $ref: "#/components/schemas/InsightsTestPyramidLayerPresenceDto" }
21741
+ e2e: { $ref: "#/components/schemas/InsightsTestPyramidLayerPresenceDto" }
21742
+
21743
+ InsightsTestPyramidSummaryDto:
21744
+ type: object
21745
+ required:
21746
+ - workspaceId
21747
+ - generatedAt
21748
+ - reposWithPyramid
21749
+ - reposFromDegradedRuns
21750
+ - totalClassifiedFiles
21751
+ - shape
21752
+ - layerPresence
21753
+ - maturityCounts
21754
+ - gapsByLayer
21755
+ properties:
21756
+ workspaceId: { type: string, format: uuid }
21757
+ generatedAt: { type: string, format: date-time }
21758
+ reposWithPyramid: { type: integer, minimum: 0 }
21759
+ reposFromDegradedRuns:
21760
+ type: array
21761
+ items: { type: string, format: uuid }
21762
+ description: Repos whose newest pyramid came from a non-succeeded readiness run.
21763
+ totalClassifiedFiles:
21764
+ type: integer
21765
+ minimum: 0
21766
+ description: Workspace sum of classified test files (not cases).
21767
+ shape:
21768
+ $ref: "#/components/schemas/InsightsTestPyramidShapeDto"
21769
+ layerPresence:
21770
+ $ref: "#/components/schemas/InsightsTestPyramidLayerPresenceMapDto"
21771
+ maturityCounts:
21772
+ $ref: "#/components/schemas/InsightsTestPyramidMaturityCountsDto"
21773
+ gapsByLayer:
21774
+ $ref: "#/components/schemas/InsightsTestPyramidGapsByLayerDto"
21775
+
21776
+ InsightsTestPyramidRepoItemDto:
21777
+ type: object
21778
+ required:
21779
+ - repoId
21780
+ - repoName
21781
+ - scannedAt
21782
+ - currentRunStatus
21783
+ - maturity
21784
+ - layerFileCounts
21785
+ - layerPresent
21786
+ - totalClassifiedFiles
21787
+ - shape
21788
+ properties:
21789
+ repoId: { type: string, format: uuid }
21790
+ repoName: { type: string }
21791
+ scannedAt: { type: string, format: date-time }
21792
+ currentRunStatus:
21793
+ $ref: "#/components/schemas/TestPyramidRunStatusDto"
21794
+ maturity:
21795
+ $ref: "#/components/schemas/InsightsTestPyramidMaturityDto"
21796
+ layerFileCounts:
21797
+ $ref: "#/components/schemas/InsightsTestPyramidLayerCountsDto"
21798
+ layerPresent:
21799
+ $ref: "#/components/schemas/InsightsTestPyramidLayerPresentDto"
21800
+ totalClassifiedFiles: { type: integer, minimum: 0 }
21801
+ shape:
21802
+ $ref: "#/components/schemas/InsightsTestPyramidShapeDto"
21803
+
21804
+ InsightsTestPyramidRepoListDto:
21805
+ type: object
21806
+ required: [items, total, limit, offset]
21807
+ properties:
21808
+ items:
21809
+ type: array
21810
+ items:
21811
+ $ref: "#/components/schemas/InsightsTestPyramidRepoItemDto"
21812
+ total: { type: integer, minimum: 0 }
21813
+ limit: { type: integer, minimum: 1 }
21814
+ offset: { type: integer, minimum: 0 }