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