@thinkai/tai-api-contract 2.62.0 → 2.64.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.62.0
4
+ version: 2.64.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}/...`.
@@ -54,6 +54,14 @@ tags:
54
54
  description: Agentic Foundation pillars (epic #278); reads stored repository readiness snapshots
55
55
  - name: YourAiJourney
56
56
  description: Your AI Journey dashboard aggregators (epic #267); composes readiness, metrics, and AI-spend data for the /dashboard page
57
+ - name: SdlcInsights
58
+ description: SDLC Engineering Health insights — DORA, CI, collaboration, security, governance, and operational metrics for `/insights/sdlc/overview`.
59
+ - name: InsightsRecommendations
60
+ description: >
61
+ Cross-analysis Insights & Recommendations page (`/insights-recommendations`).
62
+ Seven workspace-scoped GET resources under `/insights/recommendations-page/*`
63
+ with shared date/org/provider filters. Numbers are computed from dashboard metrics,
64
+ AI-tool usage/spend, org chart, and readiness — never mock payloads.
57
65
  - name: WorkspaceActivity
58
66
  description: Workspace-wide lifecycle activity log — repo add/remove/re-add and integration lifecycle events (issue #515).
59
67
  - name: PlatformAdmin
@@ -2610,6 +2618,412 @@ paths:
2610
2618
  "404":
2611
2619
  description: Workspace does not exist or malformed workspaceId
2612
2620
 
2621
+ /workspaces/{workspaceId}/insights/sdlc/overview:
2622
+ get:
2623
+ tags: [SdlcInsights]
2624
+ summary: SDLC insights — Engineering Health overview
2625
+ description: >
2626
+ Engineering Health dashboard for `/insights/sdlc/overview`. Returns precomputed
2627
+ DORA, CI, collaboration, security, governance, and operational metrics aggregated
2628
+ at calendar-day granularity for the selected window. Filter params mirror other
2629
+ Measure insights routes plus optional `repoIds` scope.
2630
+ operationId: getSdlcInsightsOverview
2631
+ parameters:
2632
+ - $ref: "#/components/parameters/WorkspaceId"
2633
+ - $ref: "#/components/parameters/InsightsSdlcRangeId"
2634
+ - $ref: "#/components/parameters/InsightsDepartmentFilter"
2635
+ - name: team
2636
+ in: query
2637
+ description: Team name filter; send `All teams` to include every team.
2638
+ schema:
2639
+ type: string
2640
+ default: All teams
2641
+ - name: repoIds
2642
+ in: query
2643
+ description: Comma-separated internal repo ids; omit or empty for all repos.
2644
+ schema:
2645
+ type: string
2646
+ responses:
2647
+ "200":
2648
+ description: Engineering Health overview payload
2649
+ content:
2650
+ application/json:
2651
+ schema:
2652
+ $ref: "#/components/schemas/SdlcOverviewDto"
2653
+ "400":
2654
+ description: Invalid query parameters
2655
+ content:
2656
+ application/json:
2657
+ schema:
2658
+ type: object
2659
+ required: [error]
2660
+ properties:
2661
+ error: { type: string, example: invalid_query }
2662
+ "401":
2663
+ $ref: "#/components/responses/Unauthorized"
2664
+ "403":
2665
+ $ref: "#/components/responses/Forbidden"
2666
+ "404":
2667
+ description: Workspace does not exist or malformed workspaceId
2668
+
2669
+ /workspaces/{workspaceId}/insights/sdlc/drilldown/{metricId}:
2670
+ get:
2671
+ tags: [SdlcInsights]
2672
+ summary: SDLC insights — metric drill-down entities
2673
+ description: >
2674
+ Paginated entity list for a single Engineering Health metric (failed workflow runs,
2675
+ PRs, alerts, etc.). Available only when the overview marks `drilldownAvailable: true`.
2676
+ operationId: getSdlcInsightsDrilldown
2677
+ parameters:
2678
+ - $ref: "#/components/parameters/WorkspaceId"
2679
+ - name: metricId
2680
+ in: path
2681
+ required: true
2682
+ schema:
2683
+ $ref: "#/components/schemas/SdlcMetricId"
2684
+ - $ref: "#/components/parameters/InsightsSdlcRangeId"
2685
+ - $ref: "#/components/parameters/InsightsDepartmentFilter"
2686
+ - name: team
2687
+ in: query
2688
+ schema:
2689
+ type: string
2690
+ default: All teams
2691
+ - name: repoIds
2692
+ in: query
2693
+ schema:
2694
+ type: string
2695
+ - name: cursor
2696
+ in: query
2697
+ description: Opaque pagination cursor from a prior response.
2698
+ schema:
2699
+ type: string
2700
+ - name: limit
2701
+ in: query
2702
+ schema:
2703
+ type: integer
2704
+ minimum: 1
2705
+ maximum: 100
2706
+ default: 25
2707
+ responses:
2708
+ "200":
2709
+ description: Drill-down page
2710
+ content:
2711
+ application/json:
2712
+ schema:
2713
+ $ref: "#/components/schemas/SdlcDrilldownDto"
2714
+ "400":
2715
+ description: Invalid query parameters
2716
+ content:
2717
+ application/json:
2718
+ schema:
2719
+ type: object
2720
+ required: [error]
2721
+ properties:
2722
+ error: { type: string, example: invalid_query }
2723
+ "401":
2724
+ $ref: "#/components/responses/Unauthorized"
2725
+ "403":
2726
+ $ref: "#/components/responses/Forbidden"
2727
+ "404":
2728
+ description: Workspace or metric not found
2729
+
2730
+ /workspaces/{workspaceId}/insights/recommendations-page/verdict-summary:
2731
+ get:
2732
+ tags: [InsightsRecommendations]
2733
+ summary: Insights recommendations — verdict summary cards
2734
+ description: >
2735
+ Top status cards for `/insights-recommendations`. `productivityMultiplier` is the
2736
+ merged-PR volume ratio versus the previous equal-length window (not AI-active vs
2737
+ non-users). `ciFailRatePct` is portfolio CI fail rate percent. Cost statuses compare
2738
+ AI spend per merged PR to the prior window. Status thresholds match the product UI:
2739
+ productivity ≥1.5 healthy / ≥1.0 watch / else at-risk; CI fail <15 healthy / ≤30 watch /
2740
+ else at-risk; cost change ≤0 healthy / <20% watch / else at-risk (prev≤0 → watch).
2741
+ operationId: getInsightsRecommendationsVerdictSummary
2742
+ parameters:
2743
+ - $ref: "#/components/parameters/WorkspaceId"
2744
+ - $ref: "#/components/parameters/InsightsRecommendationsDepartments"
2745
+ - $ref: "#/components/parameters/InsightsRecommendationsTeams"
2746
+ - $ref: "#/components/parameters/InsightsRecommendationsDateFrom"
2747
+ - $ref: "#/components/parameters/InsightsRecommendationsDateTo"
2748
+ - $ref: "#/components/parameters/InsightsRecommendationsProvider"
2749
+ - $ref: "#/components/parameters/InsightsRecommendationsIncludeUnmapped"
2750
+ - $ref: "#/components/parameters/InsightsRecommendationsIncludeBots"
2751
+ responses:
2752
+ "200":
2753
+ description: Verdict summary with `_meta.isMock=false`
2754
+ content:
2755
+ application/json:
2756
+ schema:
2757
+ $ref: "#/components/schemas/InsightsRecommendationsVerdictSummaryResponse"
2758
+ "400":
2759
+ description: Invalid filter or date range
2760
+ content:
2761
+ application/json:
2762
+ schema:
2763
+ type: object
2764
+ required: [error]
2765
+ properties:
2766
+ error: { type: string, example: invalid_query }
2767
+ "401":
2768
+ $ref: "#/components/responses/Unauthorized"
2769
+ "403":
2770
+ $ref: "#/components/responses/Forbidden"
2771
+ "404":
2772
+ description: Workspace does not exist or malformed workspaceId
2773
+
2774
+ /workspaces/{workspaceId}/insights/recommendations-page/roi-quadrant:
2775
+ get:
2776
+ tags: [InsightsRecommendations]
2777
+ summary: Insights recommendations — AI spend vs delivery output
2778
+ description: >
2779
+ Per-engineer AI spend (USD) and merged PR counts for the scatter / ROI quadrant.
2780
+ Includes engineers with spend>0 or mergedPrs>0. Medians are over the returned set
2781
+ (n<2 uses the single point or zeros when empty). `id` is the stable org person id.
2782
+ operationId: getInsightsRecommendationsRoiQuadrant
2783
+ parameters:
2784
+ - $ref: "#/components/parameters/WorkspaceId"
2785
+ - $ref: "#/components/parameters/InsightsRecommendationsDepartments"
2786
+ - $ref: "#/components/parameters/InsightsRecommendationsTeams"
2787
+ - $ref: "#/components/parameters/InsightsRecommendationsDateFrom"
2788
+ - $ref: "#/components/parameters/InsightsRecommendationsDateTo"
2789
+ - $ref: "#/components/parameters/InsightsRecommendationsProvider"
2790
+ - $ref: "#/components/parameters/InsightsRecommendationsIncludeUnmapped"
2791
+ - $ref: "#/components/parameters/InsightsRecommendationsIncludeBots"
2792
+ responses:
2793
+ "200":
2794
+ description: ROI quadrant payload
2795
+ content:
2796
+ application/json:
2797
+ schema:
2798
+ $ref: "#/components/schemas/InsightsRecommendationsRoiQuadrantResponse"
2799
+ "400":
2800
+ description: Invalid filter or date range
2801
+ content:
2802
+ application/json:
2803
+ schema:
2804
+ type: object
2805
+ required: [error]
2806
+ properties:
2807
+ error: { type: string, example: invalid_query }
2808
+ "401":
2809
+ $ref: "#/components/responses/Unauthorized"
2810
+ "403":
2811
+ $ref: "#/components/responses/Forbidden"
2812
+ "404":
2813
+ description: Workspace does not exist or malformed workspaceId
2814
+
2815
+ /workspaces/{workspaceId}/insights/recommendations-page/velocity-quality:
2816
+ get:
2817
+ tags: [InsightsRecommendations]
2818
+ summary: Insights recommendations — velocity vs quality weekly series
2819
+ description: >
2820
+ Weekly merged PR volume and CI fail rate for the filter window. Weeks follow the
2821
+ Measure calendar-week bucket convention. `targetFailRatePct` is the org target (15).
2822
+ `volumeGrowthPct` is percent change vs the prior equal-length period.
2823
+ operationId: getInsightsRecommendationsVelocityQuality
2824
+ parameters:
2825
+ - $ref: "#/components/parameters/WorkspaceId"
2826
+ - $ref: "#/components/parameters/InsightsRecommendationsDepartments"
2827
+ - $ref: "#/components/parameters/InsightsRecommendationsTeams"
2828
+ - $ref: "#/components/parameters/InsightsRecommendationsDateFrom"
2829
+ - $ref: "#/components/parameters/InsightsRecommendationsDateTo"
2830
+ - $ref: "#/components/parameters/InsightsRecommendationsProvider"
2831
+ - $ref: "#/components/parameters/InsightsRecommendationsIncludeUnmapped"
2832
+ - $ref: "#/components/parameters/InsightsRecommendationsIncludeBots"
2833
+ responses:
2834
+ "200":
2835
+ description: Velocity vs quality payload
2836
+ content:
2837
+ application/json:
2838
+ schema:
2839
+ $ref: "#/components/schemas/InsightsRecommendationsVelocityQualityResponse"
2840
+ "400":
2841
+ description: Invalid filter or date range
2842
+ content:
2843
+ application/json:
2844
+ schema:
2845
+ type: object
2846
+ required: [error]
2847
+ properties:
2848
+ error: { type: string, example: invalid_query }
2849
+ "401":
2850
+ $ref: "#/components/responses/Unauthorized"
2851
+ "403":
2852
+ $ref: "#/components/responses/Forbidden"
2853
+ "404":
2854
+ description: Workspace does not exist or malformed workspaceId
2855
+
2856
+ /workspaces/{workspaceId}/insights/recommendations-page/review-pipeline:
2857
+ get:
2858
+ tags: [InsightsRecommendations]
2859
+ summary: Insights recommendations — review bottleneck funnel
2860
+ description: >
2861
+ Review funnel stages `open-review`, `review-approval`, `approval-merge`, and `merged`.
2862
+ Wait stages use delivery-health hours (`avgReviewWaitHours`, `avgApprovalHours`, and
2863
+ approval→merge as max(0, avgTimeToMergeHours − wait − approval)). The `merged` stage
2864
+ uses `medianHours=0` (volume is not hours). `bottleneckStageId` is the wait stage with
2865
+ the highest median hours. `reviewerLoad` comes from persisted `deliveryHealth.topReviewers`
2866
+ when available; otherwise an empty array (never invented reviewers).
2867
+ operationId: getInsightsRecommendationsReviewPipeline
2868
+ parameters:
2869
+ - $ref: "#/components/parameters/WorkspaceId"
2870
+ - $ref: "#/components/parameters/InsightsRecommendationsDepartments"
2871
+ - $ref: "#/components/parameters/InsightsRecommendationsTeams"
2872
+ - $ref: "#/components/parameters/InsightsRecommendationsDateFrom"
2873
+ - $ref: "#/components/parameters/InsightsRecommendationsDateTo"
2874
+ - $ref: "#/components/parameters/InsightsRecommendationsProvider"
2875
+ - $ref: "#/components/parameters/InsightsRecommendationsIncludeUnmapped"
2876
+ - $ref: "#/components/parameters/InsightsRecommendationsIncludeBots"
2877
+ responses:
2878
+ "200":
2879
+ description: Review pipeline payload
2880
+ content:
2881
+ application/json:
2882
+ schema:
2883
+ $ref: "#/components/schemas/InsightsRecommendationsReviewPipelineResponse"
2884
+ "400":
2885
+ description: Invalid filter or date range
2886
+ content:
2887
+ application/json:
2888
+ schema:
2889
+ type: object
2890
+ required: [error]
2891
+ properties:
2892
+ error: { type: string, example: invalid_query }
2893
+ "401":
2894
+ $ref: "#/components/responses/Unauthorized"
2895
+ "403":
2896
+ $ref: "#/components/responses/Forbidden"
2897
+ "404":
2898
+ description: Workspace does not exist or malformed workspaceId
2899
+
2900
+ /workspaces/{workspaceId}/insights/recommendations-page/cost-per-pr:
2901
+ get:
2902
+ tags: [InsightsRecommendations]
2903
+ summary: Insights recommendations — cost per merged PR by team
2904
+ description: >
2905
+ Org and per-team AI spend / merged PRs. Teams with zero merged PRs in the window are
2906
+ omitted. `costPerPrUsd = spendUsd / mergedPrs`. `activeAi` is distinct AI-active members
2907
+ on the team in the window (provider filter applied).
2908
+ operationId: getInsightsRecommendationsCostPerPr
2909
+ parameters:
2910
+ - $ref: "#/components/parameters/WorkspaceId"
2911
+ - $ref: "#/components/parameters/InsightsRecommendationsDepartments"
2912
+ - $ref: "#/components/parameters/InsightsRecommendationsTeams"
2913
+ - $ref: "#/components/parameters/InsightsRecommendationsDateFrom"
2914
+ - $ref: "#/components/parameters/InsightsRecommendationsDateTo"
2915
+ - $ref: "#/components/parameters/InsightsRecommendationsProvider"
2916
+ - $ref: "#/components/parameters/InsightsRecommendationsIncludeUnmapped"
2917
+ - $ref: "#/components/parameters/InsightsRecommendationsIncludeBots"
2918
+ responses:
2919
+ "200":
2920
+ description: Cost per PR payload
2921
+ content:
2922
+ application/json:
2923
+ schema:
2924
+ $ref: "#/components/schemas/InsightsRecommendationsCostPerPrResponse"
2925
+ "400":
2926
+ description: Invalid filter or date range
2927
+ content:
2928
+ application/json:
2929
+ schema:
2930
+ type: object
2931
+ required: [error]
2932
+ properties:
2933
+ error: { type: string, example: invalid_query }
2934
+ "401":
2935
+ $ref: "#/components/responses/Unauthorized"
2936
+ "403":
2937
+ $ref: "#/components/responses/Forbidden"
2938
+ "404":
2939
+ description: Workspace does not exist or malformed workspaceId
2940
+
2941
+ /workspaces/{workspaceId}/insights/recommendations-page/adoption-gap:
2942
+ get:
2943
+ tags: [InsightsRecommendations]
2944
+ summary: Insights recommendations — AI adoption gap by team
2945
+ description: >
2946
+ Headcount vs AI-active contributors and per-team readiness/output. `readinessPct` is the
2947
+ mean latest overallScore of repos with matching `teamId` (workspace mean fallback).
2948
+ `outputPerEngPerWeek` is team merged PRs / headcount / weeks in window. `upliftPct`
2949
+ estimates additional PR volume if non-adopters matched leader-team output
2950
+ (teams with >50% adoption).
2951
+ operationId: getInsightsRecommendationsAdoptionGap
2952
+ parameters:
2953
+ - $ref: "#/components/parameters/WorkspaceId"
2954
+ - $ref: "#/components/parameters/InsightsRecommendationsDepartments"
2955
+ - $ref: "#/components/parameters/InsightsRecommendationsTeams"
2956
+ - $ref: "#/components/parameters/InsightsRecommendationsDateFrom"
2957
+ - $ref: "#/components/parameters/InsightsRecommendationsDateTo"
2958
+ - $ref: "#/components/parameters/InsightsRecommendationsProvider"
2959
+ - $ref: "#/components/parameters/InsightsRecommendationsIncludeUnmapped"
2960
+ - $ref: "#/components/parameters/InsightsRecommendationsIncludeBots"
2961
+ responses:
2962
+ "200":
2963
+ description: Adoption gap payload
2964
+ content:
2965
+ application/json:
2966
+ schema:
2967
+ $ref: "#/components/schemas/InsightsRecommendationsAdoptionGapResponse"
2968
+ "400":
2969
+ description: Invalid filter or date range
2970
+ content:
2971
+ application/json:
2972
+ schema:
2973
+ type: object
2974
+ required: [error]
2975
+ properties:
2976
+ error: { type: string, example: invalid_query }
2977
+ "401":
2978
+ $ref: "#/components/responses/Unauthorized"
2979
+ "403":
2980
+ $ref: "#/components/responses/Forbidden"
2981
+ "404":
2982
+ description: Workspace does not exist or malformed workspaceId
2983
+
2984
+ /workspaces/{workspaceId}/insights/recommendations-page/recommendations:
2985
+ get:
2986
+ tags: [InsightsRecommendations]
2987
+ summary: Insights recommendations — deterministic action items
2988
+ description: >
2989
+ Deterministic rules engine (no LLM). Emits module-anchored recommendations with
2990
+ `moduleId` in {mod-spend-vs-output, mod-velocity-vs-quality, mod-review-bottleneck,
2991
+ mod-cost-per-pr, mod-adoption-gap}. Action items must cite one AI metric and one
2992
+ delivery metric in `observed`. Evidence chips use kinds user-spend|team|contributor|repo|module
2993
+ with real target ids when available.
2994
+ operationId: getInsightsRecommendationsRecommendations
2995
+ parameters:
2996
+ - $ref: "#/components/parameters/WorkspaceId"
2997
+ - $ref: "#/components/parameters/InsightsRecommendationsDepartments"
2998
+ - $ref: "#/components/parameters/InsightsRecommendationsTeams"
2999
+ - $ref: "#/components/parameters/InsightsRecommendationsDateFrom"
3000
+ - $ref: "#/components/parameters/InsightsRecommendationsDateTo"
3001
+ - $ref: "#/components/parameters/InsightsRecommendationsProvider"
3002
+ - $ref: "#/components/parameters/InsightsRecommendationsIncludeUnmapped"
3003
+ - $ref: "#/components/parameters/InsightsRecommendationsIncludeBots"
3004
+ responses:
3005
+ "200":
3006
+ description: Recommendation items
3007
+ content:
3008
+ application/json:
3009
+ schema:
3010
+ $ref: "#/components/schemas/InsightsRecommendationsListResponse"
3011
+ "400":
3012
+ description: Invalid filter or date range
3013
+ content:
3014
+ application/json:
3015
+ schema:
3016
+ type: object
3017
+ required: [error]
3018
+ properties:
3019
+ error: { type: string, example: invalid_query }
3020
+ "401":
3021
+ $ref: "#/components/responses/Unauthorized"
3022
+ "403":
3023
+ $ref: "#/components/responses/Forbidden"
3024
+ "404":
3025
+ description: Workspace does not exist or malformed workspaceId
3026
+
2613
3027
  /workspaces/{workspaceId}/integrations/ai-tool/{provider}/members:
2614
3028
  get:
2615
3029
  tags: [Workspace]
@@ -7071,32 +7485,107 @@ components:
7071
7485
  name: from
7072
7486
  in: query
7073
7487
  description: >
7074
- Inclusive start of a daily window (`YYYY-MM-DD`). When set with `to`, overrides `rangeId`
7075
- for day-mode responses (max 180 days).
7488
+ Inclusive start of a daily window (`YYYY-MM-DD`). When set with `to`, overrides `rangeId`
7489
+ for day-mode responses (max 180 days).
7490
+ schema:
7491
+ type: string
7492
+ format: date
7493
+ InsightsProductivityTo:
7494
+ name: to
7495
+ in: query
7496
+ description: >
7497
+ Inclusive end of a daily window (`YYYY-MM-DD`). When set with `from`, overrides `rangeId`
7498
+ for day-mode responses (max 180 days).
7499
+ schema:
7500
+ type: string
7501
+ format: date
7502
+ InsightsSdlcRangeId:
7503
+ name: rangeId
7504
+ in: query
7505
+ description: >
7506
+ Day-level Measure window. Presets: `7d`, `30d`, `90d`, `180d`. Custom inclusive
7507
+ calendar range: `cr:YYYY-MM-DD:YYYY-MM-DD` (max span 180 days).
7508
+ schema:
7509
+ type: string
7510
+ default: 30d
7511
+ example: 30d
7512
+ InsightsDepartmentFilter:
7513
+ name: department
7514
+ in: query
7515
+ description: >
7516
+ Department filter; send `All departments` to include every department. Scoped using
7517
+ imported `thinkai_org_structure` members when present, otherwise SPA org chart
7518
+ `department` nodes and their descendant teams. When neither source defines the
7519
+ requested department, insights return no scoped teams or contributors (not org-wide
7520
+ data).
7521
+ schema:
7522
+ type: string
7523
+ default: All departments
7524
+ InsightsRecommendationsDepartments:
7525
+ name: departments
7526
+ in: query
7527
+ description: >
7528
+ Org-chart department ids (repeat param or comma-separated). Empty/omitted = all departments.
7529
+ schema:
7530
+ type: array
7531
+ items:
7532
+ type: string
7533
+ style: form
7534
+ explode: true
7535
+ InsightsRecommendationsTeams:
7536
+ name: teams
7537
+ in: query
7538
+ description: >
7539
+ Org-chart team ids (repeat param or comma-separated). Empty/omitted = all teams in department scope.
7540
+ schema:
7541
+ type: array
7542
+ items:
7543
+ type: string
7544
+ style: form
7545
+ explode: true
7546
+ InsightsRecommendationsDateFrom:
7547
+ name: dateFrom
7548
+ in: query
7549
+ description: >
7550
+ Inclusive window start (`YYYY-MM-DD`). Required with `dateTo`. Maps to Measure day-mode
7551
+ custom range (`from`/`to`). Max span 180 days.
7552
+ required: true
7076
7553
  schema:
7077
7554
  type: string
7078
7555
  format: date
7079
- InsightsProductivityTo:
7080
- name: to
7556
+ InsightsRecommendationsDateTo:
7557
+ name: dateTo
7081
7558
  in: query
7082
- description: >
7083
- Inclusive end of a daily window (`YYYY-MM-DD`). When set with `from`, overrides `rangeId`
7084
- for day-mode responses (max 180 days).
7559
+ description: Inclusive window end (`YYYY-MM-DD`). Required with `dateFrom`.
7560
+ required: true
7085
7561
  schema:
7086
7562
  type: string
7087
7563
  format: date
7088
- InsightsDepartmentFilter:
7089
- name: department
7564
+ InsightsRecommendationsProvider:
7565
+ name: provider
7090
7566
  in: query
7091
7567
  description: >
7092
- Department filter; send `All departments` to include every department. Scoped using
7093
- imported `thinkai_org_structure` members when present, otherwise SPA org chart
7094
- `department` nodes and their descendant teams. When neither source defines the
7095
- requested department, insights return no scoped teams or contributors (not org-wide
7096
- data).
7568
+ AI provider ids (e.g. `cursor`, `copilot`). Empty/omitted = all configured providers.
7097
7569
  schema:
7098
- type: string
7099
- default: All departments
7570
+ type: array
7571
+ items:
7572
+ type: string
7573
+ style: form
7574
+ explode: true
7575
+ InsightsRecommendationsIncludeUnmapped:
7576
+ name: includeUnmapped
7577
+ in: query
7578
+ description: Include contributors / AI rows not mapped to a team.
7579
+ schema:
7580
+ type: boolean
7581
+ default: true
7582
+ InsightsRecommendationsIncludeBots:
7583
+ name: includeBots
7584
+ in: query
7585
+ description: Include bot accounts in PR/CI stats.
7586
+ schema:
7587
+ type: boolean
7588
+ default: false
7100
7589
  PaginationLimit:
7101
7590
  name: limit
7102
7591
  in: query
@@ -14185,3 +14674,514 @@ components:
14185
14674
  type: string
14186
14675
  format: date-time
14187
14676
  description: Timestamp of the most recent contributing run (UTC).
14677
+
14678
+ SdlcModuleId:
14679
+ type: string
14680
+ enum:
14681
+ - dora
14682
+ - ci-pipeline
14683
+ - collaboration-pr
14684
+ - security-risk
14685
+ - governance-architecture
14686
+ - financial-operational
14687
+
14688
+ SdlcMetricId:
14689
+ type: string
14690
+ enum:
14691
+ - dora-deployment-frequency
14692
+ - dora-lead-time
14693
+ - dora-cfr
14694
+ - dora-mttr
14695
+ - ci-success-rate
14696
+ - ci-duration-p50-p95
14697
+ - ci-flakiness
14698
+ - ci-queue-wait
14699
+ - ci-cache-hit
14700
+ - pr-review-time
14701
+ - pr-bus-factor
14702
+ - pr-size
14703
+ - pr-abandonment
14704
+ - pr-review-depth
14705
+ - pr-draft-duration
14706
+ - pr-merge-conflicts
14707
+ - pr-commit-density
14708
+ - sec-dependabot-backlog
14709
+ - sec-vuln-mttr
14710
+ - sec-secret-scanning
14711
+ - sec-self-approvals
14712
+ - sec-unreviewed-merge
14713
+ - gov-branch-protection
14714
+ - gov-stale-branches
14715
+ - gov-orphaned-repos
14716
+ - gov-readme-health
14717
+ - gov-codeowners
14718
+ - gov-issue-pr-linkage
14719
+ - fin-gha-minutes
14720
+ - fin-copilot-utilization
14721
+ - fin-org-inactivity
14722
+ - fin-env-drift
14723
+ - fin-release-cadence
14724
+ - fin-api-rate-limit
14725
+
14726
+ SdlcMetricDataStatus:
14727
+ type: string
14728
+ enum: [live, preview, unavailable]
14729
+
14730
+ SdlcMetricHealthStatus:
14731
+ type: string
14732
+ enum: [healthy, warning, critical, unknown]
14733
+
14734
+ SdlcBenchmarkBand:
14735
+ type: string
14736
+ enum: [elite, high, medium, low]
14737
+
14738
+ SdlcMetricTrendDto:
14739
+ type: object
14740
+ required: [direction]
14741
+ properties:
14742
+ direction:
14743
+ type: string
14744
+ enum: [up, down, flat]
14745
+ deltaPercent:
14746
+ type: number
14747
+
14748
+ SdlcDailySeriesPointDto:
14749
+ type: object
14750
+ required: [date, value]
14751
+ properties:
14752
+ date:
14753
+ type: string
14754
+ format: date
14755
+ description: Inclusive ISO calendar day (UTC).
14756
+ value:
14757
+ type: number
14758
+
14759
+ SdlcMetricDto:
14760
+ type: object
14761
+ required: [id, name, dataStatus, healthStatus, value, drilldownAvailable]
14762
+ properties:
14763
+ id:
14764
+ $ref: "#/components/schemas/SdlcMetricId"
14765
+ name:
14766
+ type: string
14767
+ dataStatus:
14768
+ $ref: "#/components/schemas/SdlcMetricDataStatus"
14769
+ healthStatus:
14770
+ $ref: "#/components/schemas/SdlcMetricHealthStatus"
14771
+ value:
14772
+ oneOf:
14773
+ - type: number
14774
+ - type: string
14775
+ nullable: true
14776
+ unit:
14777
+ type: string
14778
+ secondaryValue:
14779
+ oneOf:
14780
+ - type: number
14781
+ - type: string
14782
+ nullable: true
14783
+ secondaryLabel:
14784
+ type: string
14785
+ trend:
14786
+ $ref: "#/components/schemas/SdlcMetricTrendDto"
14787
+ benchmarkBand:
14788
+ $ref: "#/components/schemas/SdlcBenchmarkBand"
14789
+ drilldownAvailable:
14790
+ type: boolean
14791
+ dailySeries:
14792
+ type: array
14793
+ items:
14794
+ $ref: "#/components/schemas/SdlcDailySeriesPointDto"
14795
+ unavailableReason:
14796
+ type: string
14797
+
14798
+ SdlcModuleDto:
14799
+ type: object
14800
+ required: [id, name, metrics]
14801
+ properties:
14802
+ id:
14803
+ $ref: "#/components/schemas/SdlcModuleId"
14804
+ name:
14805
+ type: string
14806
+ metrics:
14807
+ type: array
14808
+ items:
14809
+ $ref: "#/components/schemas/SdlcMetricDto"
14810
+
14811
+ SdlcOverviewDto:
14812
+ type: object
14813
+ required: [rangeId, from, to, department, team, repoIds, asOf, modules]
14814
+ properties:
14815
+ rangeId:
14816
+ type: string
14817
+ from:
14818
+ type: string
14819
+ format: date
14820
+ to:
14821
+ type: string
14822
+ format: date
14823
+ department:
14824
+ type: string
14825
+ team:
14826
+ type: string
14827
+ repoIds:
14828
+ type: array
14829
+ items:
14830
+ type: string
14831
+ asOf:
14832
+ type: string
14833
+ format: date-time
14834
+ modules:
14835
+ type: array
14836
+ items:
14837
+ $ref: "#/components/schemas/SdlcModuleDto"
14838
+
14839
+ SdlcDrilldownItemDto:
14840
+ type: object
14841
+ required: [id, title]
14842
+ properties:
14843
+ id:
14844
+ type: string
14845
+ title:
14846
+ type: string
14847
+ subtitle:
14848
+ type: string
14849
+ url:
14850
+ type: string
14851
+ format: uri
14852
+ occurredAt:
14853
+ type: string
14854
+ format: date-time
14855
+ metadata:
14856
+ type: object
14857
+ additionalProperties:
14858
+ oneOf:
14859
+ - type: string
14860
+ - type: number
14861
+
14862
+ SdlcDrilldownDto:
14863
+ type: object
14864
+ required: [metricId, items]
14865
+ properties:
14866
+ metricId:
14867
+ $ref: "#/components/schemas/SdlcMetricId"
14868
+ items:
14869
+ type: array
14870
+ items:
14871
+ $ref: "#/components/schemas/SdlcDrilldownItemDto"
14872
+ nextCursor:
14873
+ type: string
14874
+
14875
+ InsightsResponseMeta:
14876
+ type: object
14877
+ required: [syncedAt, isMock]
14878
+ properties:
14879
+ syncedAt:
14880
+ type: string
14881
+ format: date-time
14882
+ description: ISO timestamp when numbers were computed server-side
14883
+ isMock:
14884
+ type: boolean
14885
+ description: Must be false for production handlers
14886
+ enum: [false]
14887
+
14888
+ InsightsVerdictStatus:
14889
+ type: string
14890
+ enum: [healthy, watch, at-risk]
14891
+
14892
+ InsightsRecommendationsVerdictSummary:
14893
+ type: object
14894
+ required:
14895
+ - productivityMultiplier
14896
+ - productivityStatus
14897
+ - ciFailRatePct
14898
+ - qualityStatus
14899
+ - spendPerMergedPrUsd
14900
+ - spendPerMergedPrPrevUsd
14901
+ - costStatus
14902
+ properties:
14903
+ productivityMultiplier:
14904
+ type: number
14905
+ description: >
14906
+ Merged-PR volume ratio vs prior equal-length window (current/prior).
14907
+ When priorMergedPrs is 0, value is 1.0 and productivityStatus is watch.
14908
+ productivityStatus:
14909
+ $ref: "#/components/schemas/InsightsVerdictStatus"
14910
+ ciFailRatePct:
14911
+ type: number
14912
+ qualityStatus:
14913
+ $ref: "#/components/schemas/InsightsVerdictStatus"
14914
+ spendPerMergedPrUsd:
14915
+ type: number
14916
+ spendPerMergedPrPrevUsd:
14917
+ type: number
14918
+ costStatus:
14919
+ $ref: "#/components/schemas/InsightsVerdictStatus"
14920
+
14921
+ InsightsRecommendationsVerdictSummaryResponse:
14922
+ allOf:
14923
+ - $ref: "#/components/schemas/InsightsRecommendationsVerdictSummary"
14924
+ - type: object
14925
+ required: [_meta]
14926
+ properties:
14927
+ _meta:
14928
+ $ref: "#/components/schemas/InsightsResponseMeta"
14929
+
14930
+ InsightsRoiEngineerPoint:
14931
+ type: object
14932
+ required: [id, name, team, spendUsd, mergedPrs]
14933
+ properties:
14934
+ id: { type: string }
14935
+ name: { type: string }
14936
+ team: { type: string }
14937
+ spendUsd: { type: number }
14938
+ mergedPrs: { type: number }
14939
+
14940
+ InsightsRecommendationsRoiQuadrant:
14941
+ type: object
14942
+ required: [medianSpendUsd, medianMergedPrs, engineers, correlationHint]
14943
+ properties:
14944
+ medianSpendUsd: { type: number }
14945
+ medianMergedPrs: { type: number }
14946
+ engineers:
14947
+ type: array
14948
+ items:
14949
+ $ref: "#/components/schemas/InsightsRoiEngineerPoint"
14950
+ correlationHint: { type: string }
14951
+
14952
+ InsightsRecommendationsRoiQuadrantResponse:
14953
+ allOf:
14954
+ - $ref: "#/components/schemas/InsightsRecommendationsRoiQuadrant"
14955
+ - type: object
14956
+ required: [_meta]
14957
+ properties:
14958
+ _meta:
14959
+ $ref: "#/components/schemas/InsightsResponseMeta"
14960
+
14961
+ InsightsVelocityQualityWeek:
14962
+ type: object
14963
+ required: [weekStartIso, mergedPrs, ciFailRatePct]
14964
+ properties:
14965
+ weekStartIso: { type: string, format: date }
14966
+ mergedPrs: { type: number }
14967
+ ciFailRatePct: { type: number }
14968
+
14969
+ InsightsRecommendationsVelocityQuality:
14970
+ type: object
14971
+ required: [weeks, targetFailRatePct, volumeGrowthPct]
14972
+ properties:
14973
+ weeks:
14974
+ type: array
14975
+ items:
14976
+ $ref: "#/components/schemas/InsightsVelocityQualityWeek"
14977
+ targetFailRatePct: { type: number }
14978
+ volumeGrowthPct: { type: number }
14979
+
14980
+ InsightsRecommendationsVelocityQualityResponse:
14981
+ allOf:
14982
+ - $ref: "#/components/schemas/InsightsRecommendationsVelocityQuality"
14983
+ - type: object
14984
+ required: [_meta]
14985
+ properties:
14986
+ _meta:
14987
+ $ref: "#/components/schemas/InsightsResponseMeta"
14988
+
14989
+ InsightsReviewStageId:
14990
+ type: string
14991
+ enum: [open-review, review-approval, approval-merge, merged]
14992
+
14993
+ InsightsReviewStage:
14994
+ type: object
14995
+ required: [id, name, medianHours, trendPct]
14996
+ properties:
14997
+ id:
14998
+ $ref: "#/components/schemas/InsightsReviewStageId"
14999
+ name: { type: string }
15000
+ medianHours:
15001
+ type: number
15002
+ description: Wait hours for funnel stages; 0 for the merged volume stage
15003
+ trendPct: { type: number }
15004
+
15005
+ InsightsReviewerLoadItem:
15006
+ type: object
15007
+ required: [id, name, reviewsCount, sharePct]
15008
+ properties:
15009
+ id: { type: string }
15010
+ name: { type: string }
15011
+ reviewsCount: { type: number }
15012
+ sharePct: { type: number }
15013
+
15014
+ InsightsRecommendationsReviewPipeline:
15015
+ type: object
15016
+ required: [stages, bottleneckStageId, reviewerLoad]
15017
+ properties:
15018
+ stages:
15019
+ type: array
15020
+ items:
15021
+ $ref: "#/components/schemas/InsightsReviewStage"
15022
+ bottleneckStageId:
15023
+ $ref: "#/components/schemas/InsightsReviewStageId"
15024
+ reviewerLoad:
15025
+ type: array
15026
+ items:
15027
+ $ref: "#/components/schemas/InsightsReviewerLoadItem"
15028
+
15029
+ InsightsRecommendationsReviewPipelineResponse:
15030
+ allOf:
15031
+ - $ref: "#/components/schemas/InsightsRecommendationsReviewPipeline"
15032
+ - type: object
15033
+ required: [_meta]
15034
+ properties:
15035
+ _meta:
15036
+ $ref: "#/components/schemas/InsightsResponseMeta"
15037
+
15038
+ InsightsCostPerPrTeam:
15039
+ type: object
15040
+ required: [id, name, activeAi, spendUsd, mergedPrs, costPerPrUsd, changePct]
15041
+ properties:
15042
+ id: { type: string }
15043
+ name: { type: string }
15044
+ activeAi: { type: number }
15045
+ spendUsd: { type: number }
15046
+ mergedPrs: { type: number }
15047
+ costPerPrUsd: { type: number }
15048
+ changePct: { type: number }
15049
+
15050
+ InsightsRecommendationsCostPerPr:
15051
+ type: object
15052
+ required: [orgAvgCostUsd, orgAvgPrevUsd, teams]
15053
+ properties:
15054
+ orgAvgCostUsd: { type: number }
15055
+ orgAvgPrevUsd: { type: number }
15056
+ teams:
15057
+ type: array
15058
+ items:
15059
+ $ref: "#/components/schemas/InsightsCostPerPrTeam"
15060
+
15061
+ InsightsRecommendationsCostPerPrResponse:
15062
+ allOf:
15063
+ - $ref: "#/components/schemas/InsightsRecommendationsCostPerPr"
15064
+ - type: object
15065
+ required: [_meta]
15066
+ properties:
15067
+ _meta:
15068
+ $ref: "#/components/schemas/InsightsResponseMeta"
15069
+
15070
+ InsightsAdoptionTeam:
15071
+ type: object
15072
+ required: [id, name, activeAi, totalMembers, readinessPct, outputPerEngPerWeek]
15073
+ properties:
15074
+ id: { type: string }
15075
+ name: { type: string }
15076
+ activeAi: { type: number }
15077
+ totalMembers: { type: number }
15078
+ readinessPct: { type: number }
15079
+ outputPerEngPerWeek: { type: number }
15080
+
15081
+ InsightsRecommendationsAdoptionGap:
15082
+ type: object
15083
+ required: [totalContributors, activeContributors, upliftPct, teams]
15084
+ properties:
15085
+ totalContributors: { type: number }
15086
+ activeContributors: { type: number }
15087
+ upliftPct: { type: number }
15088
+ teams:
15089
+ type: array
15090
+ items:
15091
+ $ref: "#/components/schemas/InsightsAdoptionTeam"
15092
+
15093
+ InsightsRecommendationsAdoptionGapResponse:
15094
+ allOf:
15095
+ - $ref: "#/components/schemas/InsightsRecommendationsAdoptionGap"
15096
+ - type: object
15097
+ required: [_meta]
15098
+ properties:
15099
+ _meta:
15100
+ $ref: "#/components/schemas/InsightsResponseMeta"
15101
+
15102
+ InsightsRecommendationModuleId:
15103
+ type: string
15104
+ enum:
15105
+ - mod-spend-vs-output
15106
+ - mod-velocity-vs-quality
15107
+ - mod-review-bottleneck
15108
+ - mod-cost-per-pr
15109
+ - mod-adoption-gap
15110
+
15111
+ InsightsRecommendationImpact:
15112
+ type: string
15113
+ enum: [high, medium]
15114
+
15115
+ InsightsRecommendationTone:
15116
+ type: string
15117
+ enum: [action, no-action]
15118
+
15119
+ InsightsEvidenceLinkKind:
15120
+ type: string
15121
+ enum: [user-spend, team, contributor, repo, module]
15122
+
15123
+ InsightsEvidenceChip:
15124
+ type: object
15125
+ required: [label, kind, targetId]
15126
+ properties:
15127
+ label: { type: string }
15128
+ kind:
15129
+ $ref: "#/components/schemas/InsightsEvidenceLinkKind"
15130
+ targetId: { type: string }
15131
+
15132
+ InsightsRecommendationEvidenceGroup:
15133
+ type: object
15134
+ required: [title, chips]
15135
+ properties:
15136
+ title: { type: string }
15137
+ chips:
15138
+ type: array
15139
+ items:
15140
+ $ref: "#/components/schemas/InsightsEvidenceChip"
15141
+
15142
+ InsightsRecommendationDto:
15143
+ type: object
15144
+ required:
15145
+ - moduleId
15146
+ - moduleName
15147
+ - tone
15148
+ - impact
15149
+ - headline
15150
+ - observed
15151
+ - action
15152
+ - benefit
15153
+ - confidencePct
15154
+ - evidence
15155
+ properties:
15156
+ moduleId:
15157
+ $ref: "#/components/schemas/InsightsRecommendationModuleId"
15158
+ moduleName: { type: string }
15159
+ tone:
15160
+ $ref: "#/components/schemas/InsightsRecommendationTone"
15161
+ impact:
15162
+ $ref: "#/components/schemas/InsightsRecommendationImpact"
15163
+ headline: { type: string }
15164
+ observed:
15165
+ type: string
15166
+ description: For tone=action must cite one AI metric and one delivery metric
15167
+ action: { type: string }
15168
+ benefit: { type: string }
15169
+ confidencePct:
15170
+ type: number
15171
+ minimum: 0
15172
+ maximum: 100
15173
+ evidence:
15174
+ type: array
15175
+ items:
15176
+ $ref: "#/components/schemas/InsightsRecommendationEvidenceGroup"
15177
+
15178
+ InsightsRecommendationsListResponse:
15179
+ type: object
15180
+ required: [items, _meta]
15181
+ properties:
15182
+ items:
15183
+ type: array
15184
+ items:
15185
+ $ref: "#/components/schemas/InsightsRecommendationDto"
15186
+ _meta:
15187
+ $ref: "#/components/schemas/InsightsResponseMeta"