TenantAtlas/specs/208-heavy-suite-segmentation/contracts/heavy-suite-segmentation.logical.openapi.yaml
2026-04-17 11:44:04 +02:00

667 lines
18 KiB
YAML

openapi: 3.1.0
info:
title: Heavy Suite Segmentation Logical Contract
version: 1.0.0
summary: Logical contract for classifying heavy UI test families, validating lane placement, and reading heavy-attribution reports.
description: |
This is a logical contract for repository tooling, tests, and planning artifacts.
It does not imply a new runtime HTTP service. It documents the expected
semantics of heavy-family classification, lane-placement validation, and
heavy-lane report attribution so the existing lane-governance seams remain
consistent as Spec 208 is implemented.
x-logical-contract: true
servers:
- url: https://tenantatlas.local/logical
paths:
/heavy-test-classifications:
get:
summary: Read the checked-in heavy classification catalog.
operationId: listHeavyTestClassifications
responses:
'200':
description: Current heavy classification catalog.
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- classifications
properties:
classifications:
type: array
minItems: 5
items:
$ref: '#/components/schemas/HeavyTestClassification'
/heavy-test-placement-rules:
get:
summary: Read the checked-in lane placement rules.
operationId: listHeavyTestPlacementRules
responses:
'200':
description: Current lane placement rules.
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- rules
properties:
rules:
type: array
minItems: 5
items:
$ref: '#/components/schemas/LanePlacementRule'
/heavy-test-families:
get:
summary: Read the seeded heavy test family inventory.
operationId: listHeavyTestFamilies
responses:
'200':
description: Current heavy family inventory.
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- families
properties:
families:
type: array
minItems: 1
items:
$ref: '#/components/schemas/HeavyTestFamily'
/heavy-test-families/mixed-file-resolutions:
get:
summary: Read the checked-in mixed-file resolution inventory.
operationId: listMixedFileResolutions
responses:
'200':
description: Current mixed-file resolution records.
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- resolutions
properties:
resolutions:
type: array
items:
$ref: '#/components/schemas/MixedFileResolution'
/heavy-test-families/placement-validations:
post:
summary: Validate that a heavy class or family is assigned to a compatible lane.
operationId: validateHeavyFamilyPlacement
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/LanePlacementValidationRequest'
responses:
'200':
description: Placement validation result.
content:
application/json:
schema:
$ref: '#/components/schemas/LanePlacementValidationResult'
/test-lanes/{laneId}/reports/heavy-attribution/latest:
get:
summary: Read the latest heavy-attribution report for a lane.
operationId: getLatestHeavyAttributionReport
parameters:
- name: laneId
in: path
required: true
schema:
$ref: '#/components/schemas/LaneId'
responses:
'200':
description: Latest heavy-attribution report for the requested lane.
content:
application/json:
schema:
$ref: '#/components/schemas/HeavyAttributionReport'
components:
schemas:
ClassificationId:
type: string
enum:
- ui-light
- ui-workflow
- surface-guard
- discovery-heavy
- browser
LaneId:
type: string
enum:
- fast-feedback
- confidence
- heavy-governance
- browser
- profiling
- junit
PlacementAllowance:
type: string
enum:
- required
- allowed
- discouraged
- forbidden
ValidationStatus:
type: string
enum:
- seeded
- reviewed
- migrated
- guarded
BudgetStatus:
type: string
enum:
- within-budget
- warning
- over-budget
BudgetBaselineSource:
type: string
enum:
- measured-current-suite
- measured-lane
- measured-post-spec-207
BudgetEnforcement:
type: string
enum:
- report-only
- warn
- hard-fail
BudgetLifecycleState:
type: string
enum:
- draft
- measured
- documented
- enforced
HeavyFamilySelector:
type: object
additionalProperties: false
required:
- selectorType
- selectorValue
- selectorRole
- sourceOfTruth
properties:
selectorType:
type: string
enum:
- suite
- path
- group
- file
selectorValue:
type: string
minLength: 1
selectorRole:
type: string
enum:
- include
- exclude
- inventory-only
sourceOfTruth:
type: string
enum:
- manifest
- pest-group
- guard-test
- report-attribution
rationale:
type: string
HeavyTestClassification:
type: object
additionalProperties: false
required:
- classificationId
- purpose
- dominantCostDrivers
- defaultLaneId
- allowedLaneIds
- forbiddenLaneIds
- reviewerSignals
- escalationTriggers
properties:
classificationId:
$ref: '#/components/schemas/ClassificationId'
purpose:
type: string
dominantCostDrivers:
type: array
minItems: 1
items:
type: string
defaultLaneId:
$ref: '#/components/schemas/LaneId'
allowedLaneIds:
type: array
minItems: 1
items:
$ref: '#/components/schemas/LaneId'
forbiddenLaneIds:
type: array
items:
$ref: '#/components/schemas/LaneId'
reviewerSignals:
type: array
minItems: 1
items:
type: string
escalationTriggers:
type: array
minItems: 1
items:
type: string
allOf:
- if:
properties:
classificationId:
const: browser
then:
properties:
defaultLaneId:
const: browser
allowedLaneIds:
type: array
minItems: 1
maxItems: 1
items:
const: browser
- if:
properties:
classificationId:
const: surface-guard
then:
properties:
defaultLaneId:
const: heavy-governance
forbiddenLaneIds:
allOf:
- contains:
const: fast-feedback
- contains:
const: confidence
- if:
properties:
classificationId:
const: ui-workflow
then:
properties:
defaultLaneId:
const: confidence
- if:
properties:
classificationId:
const: discovery-heavy
then:
properties:
defaultLaneId:
const: heavy-governance
forbiddenLaneIds:
allOf:
- contains:
const: fast-feedback
- contains:
const: confidence
HeavyTestFamily:
type: object
additionalProperties: false
required:
- familyId
- classificationId
- purpose
- currentLaneId
- targetLaneId
- selectors
- hotspotFiles
- costSignals
- validationStatus
properties:
familyId:
type: string
classificationId:
$ref: '#/components/schemas/ClassificationId'
purpose:
type: string
currentLaneId:
$ref: '#/components/schemas/LaneId'
targetLaneId:
$ref: '#/components/schemas/LaneId'
selectors:
type: array
minItems: 1
items:
$ref: '#/components/schemas/HeavyFamilySelector'
hotspotFiles:
type: array
minItems: 1
items:
type: string
costSignals:
type: array
minItems: 1
items:
type: string
confidenceRationale:
type: string
validationStatus:
$ref: '#/components/schemas/ValidationStatus'
allOf:
- if:
properties:
targetLaneId:
const: confidence
then:
required:
- confidenceRationale
properties:
confidenceRationale:
type: string
minLength: 1
- if:
properties:
classificationId:
const: ui-light
then:
properties:
targetLaneId:
enum:
- fast-feedback
- confidence
- if:
properties:
classificationId:
const: ui-workflow
then:
properties:
targetLaneId:
enum:
- confidence
- heavy-governance
- if:
properties:
classificationId:
const: surface-guard
then:
properties:
targetLaneId:
const: heavy-governance
- if:
properties:
classificationId:
const: discovery-heavy
then:
properties:
targetLaneId:
const: heavy-governance
- if:
properties:
classificationId:
const: browser
then:
properties:
targetLaneId:
const: browser
MixedFileResolution:
type: object
additionalProperties: false
required:
- filePath
- primaryClassificationId
- resolutionStrategy
- rationale
- followUpRequired
properties:
filePath:
type: string
minLength: 1
primaryClassificationId:
$ref: '#/components/schemas/ClassificationId'
secondaryClassificationIds:
type: array
items:
$ref: '#/components/schemas/ClassificationId'
resolutionStrategy:
type: string
enum:
- split-file
- broadest-cost-wins
rationale:
type: string
minLength: 1
followUpRequired:
type: boolean
LanePlacementRule:
type: object
additionalProperties: false
required:
- ruleId
- classificationId
- laneId
- allowance
- reason
properties:
ruleId:
type: string
classificationId:
$ref: '#/components/schemas/ClassificationId'
laneId:
$ref: '#/components/schemas/LaneId'
allowance:
$ref: '#/components/schemas/PlacementAllowance'
reason:
type: string
exceptionPolicy:
type: string
LanePlacementValidationRequest:
type: object
additionalProperties: false
required:
- laneId
properties:
laneId:
$ref: '#/components/schemas/LaneId'
classificationId:
$ref: '#/components/schemas/ClassificationId'
familyId:
type: string
filePath:
type: string
observedCostSignals:
type: array
items:
type: string
anyOf:
- required:
- classificationId
- required:
- familyId
- required:
- filePath
LanePlacementValidationResult:
type: object
additionalProperties: false
required:
- laneId
- resolvedClassificationId
- allowance
- valid
- reasons
properties:
laneId:
$ref: '#/components/schemas/LaneId'
resolvedClassificationId:
$ref: '#/components/schemas/ClassificationId'
familyId:
type: string
allowance:
$ref: '#/components/schemas/PlacementAllowance'
valid:
type: boolean
reasons:
type: array
minItems: 1
items:
type: string
remediationOptions:
type: array
items:
type: string
mixedFileResolution:
$ref: '#/components/schemas/MixedFileResolution'
HeavyBudgetEvaluation:
type: object
additionalProperties: false
required:
- targetType
- targetId
- thresholdSeconds
- measuredSeconds
- baselineSource
- enforcement
- lifecycleState
- status
properties:
targetType:
type: string
enum:
- lane
- classification
- family
targetId:
type: string
thresholdSeconds:
type: integer
minimum: 1
measuredSeconds:
type: number
minimum: 0
baselineSource:
$ref: '#/components/schemas/BudgetBaselineSource'
enforcement:
$ref: '#/components/schemas/BudgetEnforcement'
lifecycleState:
$ref: '#/components/schemas/BudgetLifecycleState'
status:
$ref: '#/components/schemas/BudgetStatus'
HeavyAttributionReport:
type: object
additionalProperties: false
required:
- laneId
- finishedAt
- wallClockSeconds
- slowestEntries
- classificationAttribution
- familyAttribution
- budgetEvaluations
- artifactDirectory
properties:
laneId:
$ref: '#/components/schemas/LaneId'
finishedAt:
type: string
format: date-time
wallClockSeconds:
type: number
minimum: 0
slowestEntries:
type: array
description: Canonical top 10 runtime hotspot entries ordered by slowest wall-clock time.
minItems: 10
items:
type: object
additionalProperties: false
required:
- label
- wallClockSeconds
properties:
label:
type: string
wallClockSeconds:
type: number
minimum: 0
classificationAttribution:
type: array
minItems: 1
items:
type: object
additionalProperties: false
required:
- classificationId
- totalWallClockSeconds
properties:
classificationId:
$ref: '#/components/schemas/ClassificationId'
totalWallClockSeconds:
type: number
minimum: 0
hotspotFiles:
type: array
items:
type: string
familyAttribution:
type: array
minItems: 1
items:
type: object
additionalProperties: false
required:
- familyId
- classificationId
- totalWallClockSeconds
properties:
familyId:
type: string
classificationId:
$ref: '#/components/schemas/ClassificationId'
totalWallClockSeconds:
type: number
minimum: 0
hotspotFiles:
type: array
items:
type: string
budgetEvaluations:
type: array
minItems: 1
allOf:
- contains:
type: object
required:
- targetType
- targetId
properties:
targetType:
const: lane
targetId:
const: heavy-governance
- contains:
type: object
required:
- targetType
properties:
targetType:
const: classification
- contains:
type: object
required:
- targetType
properties:
targetType:
const: family
items:
$ref: '#/components/schemas/HeavyBudgetEvaluation'
artifactDirectory:
type: string
const: storage/logs/test-lanes