1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# multi-source-config.yaml
#
# Fully annotated tga config showing multi-source classification (issues #260,
# #272, #273, #274, #275) and the corrected custom-rules priority defaults
# (issue #259).
#
# Run all sources:
# JIRA_API_TOKEN=<token> GITHUB_TOKEN=<pat> \
# LINEAR_API_KEY=<key> SHORTCUT_API_TOKEN=<token> \
# CONFLUENCE_API_TOKEN=<token> CONFLUENCE_EMAIL=<email> \
# DD_API_KEY=<key> DD_APP_KEY=<key> \
# tga classify --config multi-source-config.yaml
#
# To disable external sources for a single run (e.g. in CI without credentials):
# tga classify --config multi-source-config.yaml --no-external
repositories:
- path: ~/code/my-project
name: my-project
output:
directory: ./reports
formats:
classification:
# Optional: path to custom rules. Custom rules default to priority 110,
# which places them above the built-in rules (priority 100). The file is
# standalone by default (extend_defaults: false); only the rules listed
# here apply unless you set extend_defaults: true.
rules_file: ./my-rules.yaml
# WAL checkpoint frequency (new in 1.4.0 — issue #298).
# When non-zero, a PASSIVE checkpoint is issued every N classified commits
# to cap the data-loss window during long runs. 0 = disabled (default).
checkpoint_every: 1000
# External classification sources (issue #260 + 1.4.0 additions).
# Sources are consulted in order; the first non-None signal wins.
# Each unique ticket is fetched at most once per run (in-memory cache).
# On HTTP failure or missing token the source is skipped with a warning.
sources:
# -----------------------------------------------------------------
# JIRA Cloud / Server
# -----------------------------------------------------------------
- type: jira
# Base URL of your JIRA instance.
base_url: "https://yourco.atlassian.net"
# Name of the environment variable carrying the API token.
# For JIRA Cloud: create a token at
# https://id.atlassian.com/manage-profile/security/api-tokens
# Set it as: export JIRA_API_TOKEN="your-token"
token_env: JIRA_API_TOKEN
# JIRA Cloud requires Basic auth: email + token base64-encoded.
#
# Recommended: use `email_env:` so the email address is read from the
# environment at request time and never stored in the config file.
# export JIRA_EMAIL="you@yourco.com"
email_env: JIRA_EMAIL
#
# Alternative (backward compat): set the literal email here.
# Only one of `email_env` or `username` is needed; `username` wins if
# both are present.
# username: "you@yourco.com"
# Limit JIRA lookups to these project keys.
# An empty list (or omitting the key) means "query any project key
# found in commit messages".
project_keys:
- PROJ
- ENG
- INFRA
# Map JIRA issue fields to TGA category strings.
# Priority: issue_type > labels > components (first match wins).
field_mappings:
issue_type:
# Standard JIRA issue types -> TGA categories
Bug: bug_fix
Story: new_feature
Task: tech_debt_refactoring
Epic: new_feature
Improvement: new_feature
Sub-task: tech_debt_refactoring
Technical Debt: tech_debt_refactoring
Spike: wip
labels:
# Label-to-category fallback (fires when issue_type is unmapped)
ktlo: tech_debt_refactoring
security: security
performance: performance
documentation: documentation
testing: test
components:
# Component-to-category fallback (fires when neither issue_type
# nor labels match)
Platform: platform_infrastructure
CI/CD: ci
Security: security
# -----------------------------------------------------------------
# GitHub Issues
# -----------------------------------------------------------------
- type: github_issues
# Default repository for bare "#NNN" references.
# Qualified "owner/repo#NNN" references override this for that ref.
repo: "acme/widgets"
# Name of the environment variable carrying the GitHub PAT.
# Required scopes: repo (private) or public_repo (public).
# Set it as: export GITHUB_TOKEN="ghp_..."
token_env: GITHUB_TOKEN
# Map GitHub issue label names to TGA category strings.
# First matching label in the issue's label list wins.
label_mappings:
bug: bug_fix
enhancement: new_feature
feature: new_feature
refactor: tech_debt_refactoring
performance: performance
documentation: documentation
test: test
ci: ci
security: security
dependencies: tech_debt_refactoring
good first issue: new_feature
help wanted: new_feature
# -----------------------------------------------------------------
# Linear (new in 1.4.0 — issue #272)
# -----------------------------------------------------------------
- type: linear
# Personal API Key from https://linear.app/settings/api
# Set it as: export LINEAR_API_KEY="lin_api_..."
api_key_env: LINEAR_API_KEY # pragma: allowlist secret
# Restrict processing to these Linear team key prefixes.
# Linear keys and JIRA keys share the same PROJ-NNN shape. Listing your
# Linear team keys here prevents Linear from processing keys that belong
# to your JIRA instance (and vice-versa when both sources are active).
# Leave empty (or omit) to process all PROJ-NNN references via Linear.
team_keys:
- ENG
- MOBILE
# Map Linear fields to TGA category strings.
# Priority: issue_type > labels > cycle (first match wins).
field_mappings:
issue_type:
Bug: bug_fix
Feature: new_feature
Improvement: tech_debt_refactoring
Chore: tech_debt_refactoring
labels:
security: security
ktlo: tech_debt_refactoring
performance: performance
cycle:
# Active cycle/sprint name → category (fires last).
# Useful when cycle names encode work type (e.g. "Security Sprint").
"Security Sprint": security
# -----------------------------------------------------------------
# Shortcut (new in 1.4.0 — issue #273)
# -----------------------------------------------------------------
- type: shortcut
# API token from https://app.shortcut.com/settings/api-tokens
# Set it as: export SHORTCUT_API_TOKEN="..."
api_token_env: SHORTCUT_API_TOKEN
# Two reference forms are recognized in commit messages:
# [ch1234] — bracket form (most common)
# sc-1234 — sc-prefix form (common in branch names)
field_mappings:
story_type:
bug: bug_fix
feature: new_feature
chore: tech_debt_refactoring
labels:
security: security
performance: performance
documentation: documentation
workflow_state:
# Workflow state name → category. Fires last.
"In Development": new_feature
"In Review": new_feature
# -----------------------------------------------------------------
# Confluence (new in 1.4.0 — issue #274)
# Note: Confluence confidence is fixed at 0.80 (lower than the standard
# 0.92 for JIRA/GitHub/Linear/Shortcut) because page labels are a weaker
# signal than issue type or story category.
# -----------------------------------------------------------------
- type: confluence
# Atlassian base URL (same as your JIRA instance if using Atlassian Cloud).
base_url: "https://yourco.atlassian.net"
# Confluence Cloud requires Basic auth: email + API token.
# Set them as:
# export CONFLUENCE_API_TOKEN="your-token"
# export CONFLUENCE_EMAIL="you@yourco.com"
token_env: CONFLUENCE_API_TOKEN
email_env: CONFLUENCE_EMAIL
# Two reference forms are recognized in commit messages:
# /wiki/spaces/SPACE/pages/12345 — URL form (page ID extracted)
# [CONF-12345] — Smart Commit form
label_mappings:
runbook: devops
architecture: tech_debt_refactoring
security: security
on-call: devops
# -----------------------------------------------------------------
# Datadog (new in 1.4.0 — issue #275)
# Matches commit SHAs found in commit messages against the Datadog
# Events API. A deployment event that references the SHA causes this
# commit to be classified as `devops` (or the `default_category` below).
# Confidence is fixed at 0.95.
# -----------------------------------------------------------------
- type: datadog
# API key from https://app.datadoghq.com/organization-settings/api-keys
# Application key from https://app.datadoghq.com/organization-settings/application-keys
# Set them as:
# export DD_API_KEY="..."
# export DD_APP_KEY="..."
api_key_env: DD_API_KEY # pragma: allowlist secret
app_key_env: DD_APP_KEY # pragma: allowlist secret
# Datadog site (default: "datadoghq.com").
# Use "datadoghq.eu" for the EU region.
site: datadoghq.com
# Category written when a deployment event is found for this commit's SHA.
default_category: devops # default: "devops"
# How many days back to search for deployment events.
lookback_days: 30 # default: 30
# Optional LLM fallback for commits with low-confidence verdicts.
# use_llm: false
# llm_model: gpt-4o-mini
# llm_fallback_threshold: 0.35