delivery-friction-analyzer 0.1.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.
@@ -0,0 +1,73 @@
1
+ {
2
+ "schemaVersion": "repository-profile.v1",
3
+ "repository": {
4
+ "owner": "hannasdev",
5
+ "name": "mcp-writing"
6
+ },
7
+ "prClasses": [
8
+ {
9
+ "id": "release-title",
10
+ "class": "release",
11
+ "match": { "titleRegex": "^Release\\b" }
12
+ }
13
+ ],
14
+ "rules": [
15
+ {
16
+ "id": "generated-tool-docs",
17
+ "match": { "prefix": "docs/agents/" },
18
+ "category": "generated",
19
+ "role": "generated_docs",
20
+ "functionalSurface": "agent_tool_reference",
21
+ "generated": true
22
+ },
23
+ {
24
+ "id": "tests",
25
+ "match": { "prefix": "src/test/" },
26
+ "category": "tests",
27
+ "role": "tests",
28
+ "functionalSurface": "test_suite"
29
+ },
30
+ {
31
+ "id": "core-src",
32
+ "match": { "prefix": "src/" },
33
+ "category": "code",
34
+ "role": "core_product_code",
35
+ "functionalSurface": "runtime"
36
+ },
37
+ {
38
+ "id": "release-log",
39
+ "match": { "exact": "release-log.md" },
40
+ "category": "docs",
41
+ "role": "release_notes",
42
+ "functionalSurface": "release_notes"
43
+ },
44
+ {
45
+ "id": "planning-docs",
46
+ "match": { "prefix": "docs/initiatives/" },
47
+ "category": "docs",
48
+ "role": "planning_docs",
49
+ "functionalSurface": "planning"
50
+ },
51
+ {
52
+ "id": "guides",
53
+ "match": { "prefix": "docs/guides/" },
54
+ "category": "docs",
55
+ "role": "unknown",
56
+ "functionalSurface": "user_docs"
57
+ },
58
+ {
59
+ "id": "top-level-docs",
60
+ "match": { "regex": "^(README|PRODUCT|FEATURES)\\.md$" },
61
+ "category": "docs",
62
+ "role": "unknown",
63
+ "functionalSurface": "product_docs"
64
+ },
65
+ {
66
+ "id": "docker",
67
+ "match": { "suffix": "Dockerfile" },
68
+ "category": "infrastructure",
69
+ "role": "infrastructure",
70
+ "functionalSurface": "runtime_infra"
71
+ }
72
+ ]
73
+ }
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "delivery-friction-analyzer",
3
+ "version": "0.1.0",
4
+ "description": "Local GitHub pull request analytics for delivery friction reports.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": {
8
+ "delivery-friction-analyzer": "src/cli/analyze-github.js"
9
+ },
10
+ "files": [
11
+ "src",
12
+ "schemas",
13
+ "docs/contracts",
14
+ "docs/reference",
15
+ "fixtures/github/mcp-writing/profile.json",
16
+ "LICENSE",
17
+ "README.md",
18
+ "release-log.md"
19
+ ],
20
+ "scripts": {
21
+ "analyze:github": "node src/cli/analyze-github.js",
22
+ "report:fixture": "node src/report/generate-report.js --metrics-summary fixtures/github/mcp-writing/metrics-summary.golden.json --json-out fixtures/github/mcp-writing/reports/friction-report.golden.json --markdown-out fixtures/github/mcp-writing/reports/friction-report.golden.md",
23
+ "test": "node --test"
24
+ },
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "git+https://github.com/hannasdev/delivery-friction-analyzer.git"
28
+ },
29
+ "bugs": {
30
+ "url": "https://github.com/hannasdev/delivery-friction-analyzer/issues"
31
+ },
32
+ "homepage": "https://github.com/hannasdev/delivery-friction-analyzer#readme",
33
+ "keywords": [
34
+ "github",
35
+ "pull-request",
36
+ "developer-productivity",
37
+ "delivery-friction",
38
+ "ci",
39
+ "code-review",
40
+ "analytics"
41
+ ],
42
+ "publishConfig": {
43
+ "access": "public"
44
+ },
45
+ "engines": {
46
+ "node": ">=20"
47
+ }
48
+ }
package/release-log.md ADDED
@@ -0,0 +1,106 @@
1
+ # Release Log
2
+
3
+ ## Unreleased
4
+
5
+ ### 2026-06-14 — NPM Release Automation
6
+
7
+ - What changed: The package is prepared for public npm distribution with CLI metadata, a tight npm package allowlist, CI package dry-runs, automated conventional-commit versioning, GitHub release creation, and tag-triggered npm publishing.
8
+ - Why it matters: Maintainers can validate the release artifact on every PR and publish versioned CLI releases without manually editing package metadata or uploading ad hoc tarballs.
9
+ - Who is affected: Maintainers preparing releases and users installing the analyzer from npm.
10
+ - Action needed: Configure `RELEASE_DEPLOY_KEY` and npm trusted publishing before the first tag-triggered release.
11
+ - PR: https://github.com/hannasdev/delivery-friction-analyzer/pull/28
12
+
13
+ ### 2026-06-14 — Explicit PR Class Filtering
14
+
15
+ - What changed: GitHub analysis now accepts `--exclude-pr-class` to recompute normalized data, metrics, reports, methodology, and CSV exports for an explicitly filtered PR class sample while preserving the full collected `source-bundle.json`.
16
+ - Why it matters: Maintainers can inspect development-oriented reports separately from release, dependency, or repository-specific PR populations without losing auditability of the collected sample.
17
+ - Who is affected: Maintainers and contributors running `npm run analyze:github`.
18
+ - Action needed: Use `--exclude-pr-class <class>` when a class should be excluded from downstream analysis artifacts.
19
+ - PR: https://github.com/hannasdev/delivery-friction-analyzer/pull/27
20
+
21
+ ### 2026-06-14 — PR Class Report Context
22
+
23
+ - What changed: Markdown and JSON friction reports now include PR class distribution, PR class evidence in representative bottleneck examples, and caveats when displayed bottleneck examples are concentrated in one PR class.
24
+ - Why it matters: Maintainers can see when release, dependency, development, or repository-specific PR populations are shaping report interpretation without filtering the default analysis.
25
+ - Who is affected: Maintainers and contributors reviewing generated friction reports.
26
+ - Action needed: None.
27
+ - PR: https://github.com/hannasdev/delivery-friction-analyzer/pull/26
28
+
29
+ ### 2026-06-14 — PR Class Evidence
30
+
31
+ - What changed: Repository profiles can now classify pull requests by title rules, and normalized data, metrics summaries, and `pr-metrics.csv` carry PR class evidence.
32
+ - Why it matters: Maintainers can segment release, dependency, or repository-specific PR populations downstream without manually parsing PR titles.
33
+ - Who is affected: Maintainers and contributors running or inspecting delivery-friction analysis artifacts.
34
+ - Action needed: Add optional `prClasses` rules to repository profiles when PR populations should be labeled.
35
+ - PR: https://github.com/hannasdev/delivery-friction-analyzer/pull/25
36
+
37
+ ### 2026-06-14 — PR Sample Contract Alignment
38
+
39
+ - What changed: Target repository metadata now records the latest-N pull request sample size, and Markdown reports label the analyzed pull request count instead of a day window.
40
+ - Why it matters: Maintainers can trust that report headers, fixtures, and schemas describe the actual analysis selection model.
41
+ - Who is affected: Maintainers and contributors reviewing generated reports, fixtures, or target repository metadata.
42
+ - Action needed: Update consumers that read `analysisWindowDays` to use `analysisPullRequestLimit`.
43
+ - PR: https://github.com/hannasdev/delivery-friction-analyzer/pull/23
44
+
45
+ ### 2026-06-13 — Shared Signal Interpretation
46
+
47
+ - What changed: Markdown and JSON friction reports now call out when displayed bottlenecks share the same ranking signal or representative PR evidence while keeping their recommendation categories distinct.
48
+ - Why it matters: Maintainers can tell when several ranked findings are related interpretations of one underlying pattern instead of treating them as independent repository problems.
49
+ - Who is affected: Maintainers and contributors reviewing generated friction reports.
50
+ - Action needed: None.
51
+ - PR: https://github.com/hannasdev/delivery-friction-analyzer/pull/20
52
+
53
+ ### 2026-06-12 — Review Decision Evidence
54
+
55
+ - What changed: Friction metrics, Markdown reports, and `pr-metrics.csv` now include review decision evidence derived from review events, including human approval, changes-requested, reviewer count, and unavailable review-event coverage.
56
+ - Why it matters: Maintainers can distinguish zero inline review threads from missing review evidence or clean human approval, so `review_threads = 0` is less likely to be misread as "unreviewed."
57
+ - Who is affected: Maintainers and contributors reviewing delivery-friction reports or CSV evidence exports.
58
+ - Action needed: Treat `review_threads` as review churn and use the adjacent review-decision fields for review coverage context.
59
+ - PR: https://github.com/hannasdev/delivery-friction-analyzer/pull/18
60
+
61
+ ### 2026-06-10 — Report Evidence Readability
62
+
63
+ - What changed: Markdown friction reports now show final/current PR additions, deletions, changed files, and changed lines in representative evidence tables, with validation and review details rendered as plain Markdown lists.
64
+ - Why it matters: Maintainers can compare PR size against review, validation, and planning friction without reading dense semicolon-packed table cells.
65
+ - Who is affected: Maintainers and contributors reviewing delivery-friction reports.
66
+ - Action needed: None.
67
+ - PR: https://github.com/hannasdev/delivery-friction-analyzer/pull/12
68
+
69
+ ### 2026-06-10 — CLI Report Delivery Experience
70
+
71
+ - What changed: Successful GitHub analysis runs now print a concise human-readable completion message by default, with the Markdown report path first; pass `--json` to print the full machine-readable completion receipt on stdout. Live collection also retries transient `gh pr view` GraphQL authentication failures.
72
+ - Why it matters: Maintainers can jump straight to the main report, automation can keep parsing the existing receipt by opting into `--json`, and larger live samples are less likely to fail on brief GitHub CLI throttling/auth hiccups.
73
+ - Who is affected: Maintainers and scripts running `npm run analyze:github`.
74
+ - Action needed: Update scripts that parse default stdout JSON to pass `--json`.
75
+
76
+ ### 2026-06-10 — Methodology And Evidence Exports
77
+
78
+ - What changed: Full GitHub analysis now writes a detailed `methodology.md` artifact and curated CSV evidence exports by default, with `--no-csv` available to suppress CSV files.
79
+ - Why it matters: Maintainers can understand the report methodology, inspect spreadsheet-friendly evidence, and see outlier sensitivity without reading nested JSON first.
80
+ - Who is affected: Maintainers and contributors running local GitHub analysis.
81
+ - Action needed: Use `--no-csv` for runs where spreadsheet-friendly artifacts should not be produced.
82
+ - PR: https://github.com/hannasdev/delivery-friction-analyzer/pull/10
83
+
84
+ ### 2026-06-10 — Report Readability And Evidence Transparency
85
+
86
+ - What changed: Markdown friction reports now use a clearer reader path with executive summary, evidence-quality coverage, key findings, labeled bottleneck sections, scannable PR evidence tables, methodology summary, guardrails, and artifact-sensitivity guidance.
87
+ - Why it matters: Maintainers can distinguish observed data, analyzer interpretation, recommendations, and caveats more quickly before acting on report findings.
88
+ - Who is affected: Maintainers and contributors reviewing delivery-friction reports from fixture or live GitHub analysis.
89
+ - Action needed: None.
90
+ - PR: #9
91
+
92
+ ### 2026-06-09 — Live Report Calibration
93
+
94
+ - What changed: Report bottleneck examples now show validation sources, workflow conclusions, review-thread sources, comment-source evidence, and outlier dominance notes, with a redacted 30-PR calibration sample protecting the output shape.
95
+ - Why it matters: Maintainers can trust and inspect live report recommendations more easily before turning them into process changes.
96
+ - Who is affected: Maintainers and contributors reviewing delivery-friction reports from live GitHub analysis.
97
+ - Action needed: None.
98
+ - PR: #7
99
+
100
+ ### 2026-06-09 - Local GitHub Analysis Command
101
+
102
+ - What changed: Added a documented local command that runs live GitHub collection, normalization, metrics, and Markdown/JSON report generation in one workflow.
103
+ - Why it matters: Maintainers can now point the analyzer at a GitHub repository and generate the MVP report artifacts without preparing a metrics summary by hand.
104
+ - Who is affected: Maintainers and contributors running repository delivery-friction analysis locally.
105
+ - Action needed: Authenticate with `gh`, provide a repository profile, and choose a local output directory for generated artifacts.
106
+ - PR: #6
@@ -0,0 +1,342 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://delivery-friction-analyzer.local/schemas/normalized-entities.schema.json",
4
+ "title": "NormalizedFixtureBundle",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["schemaVersion", "targetRepository", "languageDistribution", "pullRequests"],
8
+ "properties": {
9
+ "schemaVersion": { "const": "normalized-fixture.v1" },
10
+ "targetRepository": { "$ref": "target-repository.schema.json" },
11
+ "analysisFilter": {
12
+ "type": "object",
13
+ "additionalProperties": false,
14
+ "required": ["excludedPrClasses", "originalPullRequests", "filteredPullRequests"],
15
+ "properties": {
16
+ "excludedPrClasses": {
17
+ "type": "array",
18
+ "items": {
19
+ "type": "string",
20
+ "pattern": "^[a-z0-9]+(?:[-_][a-z0-9]+)*$"
21
+ }
22
+ },
23
+ "originalPullRequests": { "type": "integer", "minimum": 1 },
24
+ "filteredPullRequests": { "type": "integer", "minimum": 1 }
25
+ }
26
+ },
27
+ "languageDistribution": {
28
+ "type": "object",
29
+ "additionalProperties": false,
30
+ "required": ["source", "bytesByLanguage"],
31
+ "properties": {
32
+ "source": { "const": "rest:/repos/{owner}/{repo}/languages" },
33
+ "bytesByLanguage": {
34
+ "type": "object",
35
+ "additionalProperties": { "type": "integer", "minimum": 0 }
36
+ }
37
+ }
38
+ },
39
+ "pullRequests": {
40
+ "type": "array",
41
+ "items": {
42
+ "type": "object",
43
+ "additionalProperties": false,
44
+ "required": [
45
+ "number",
46
+ "title",
47
+ "authorLogin",
48
+ "prClass",
49
+ "url",
50
+ "state",
51
+ "lifecycle",
52
+ "commits",
53
+ "diffAtMerge",
54
+ "prOpenDiff",
55
+ "files",
56
+ "reviews",
57
+ "reviewDecision",
58
+ "reviewThreads",
59
+ "reviewComments",
60
+ "checkRuns",
61
+ "workflowRuns"
62
+ ],
63
+ "properties": {
64
+ "number": { "type": "integer" },
65
+ "title": { "type": "string" },
66
+ "authorLogin": { "type": ["string", "null"] },
67
+ "prClass": {
68
+ "type": "object",
69
+ "additionalProperties": false,
70
+ "required": ["class", "classificationSource", "ruleId"],
71
+ "properties": {
72
+ "class": {
73
+ "type": "string",
74
+ "pattern": "^[a-z0-9]+(?:[-_][a-z0-9]+)*$"
75
+ },
76
+ "classificationSource": { "enum": ["repository_profile", "fallback_rule"] },
77
+ "ruleId": { "type": ["string", "null"] }
78
+ }
79
+ },
80
+ "url": { "type": "string" },
81
+ "state": { "enum": ["OPEN", "CLOSED", "MERGED"] },
82
+ "lifecycle": {
83
+ "type": "object",
84
+ "additionalProperties": false,
85
+ "required": ["createdAt", "mergedAt", "firstCommitAt", "firstReviewAt", "lastReviewAt"],
86
+ "properties": {
87
+ "createdAt": { "type": ["string", "null"] },
88
+ "mergedAt": { "type": ["string", "null"] },
89
+ "firstCommitAt": { "type": ["string", "null"] },
90
+ "firstReviewAt": { "type": ["string", "null"] },
91
+ "lastReviewAt": { "type": ["string", "null"] }
92
+ }
93
+ },
94
+ "commits": {
95
+ "type": "array",
96
+ "items": {
97
+ "type": "object",
98
+ "additionalProperties": false,
99
+ "required": ["oid", "authoredDate", "committedDate", "messageHeadline"],
100
+ "properties": {
101
+ "oid": { "type": "string" },
102
+ "authoredDate": { "type": ["string", "null"] },
103
+ "committedDate": { "type": ["string", "null"] },
104
+ "messageHeadline": { "type": ["string", "null"] }
105
+ }
106
+ }
107
+ },
108
+ "diffAtMerge": {
109
+ "type": "object",
110
+ "additionalProperties": false,
111
+ "required": ["additions", "deletions", "changedFiles"],
112
+ "properties": {
113
+ "additions": { "type": "integer", "minimum": 0 },
114
+ "deletions": { "type": "integer", "minimum": 0 },
115
+ "changedFiles": { "type": "integer", "minimum": 0 }
116
+ }
117
+ },
118
+ "prOpenDiff": {
119
+ "type": "object",
120
+ "additionalProperties": false,
121
+ "required": ["source", "confidence"],
122
+ "allOf": [
123
+ {
124
+ "if": {
125
+ "type": "object",
126
+ "anyOf": [
127
+ { "required": ["additions"] },
128
+ { "required": ["deletions"] },
129
+ { "required": ["changedFiles"] }
130
+ ]
131
+ },
132
+ "then": {
133
+ "required": ["additions", "deletions", "changedFiles"]
134
+ }
135
+ },
136
+ {
137
+ "if": {
138
+ "type": "object",
139
+ "required": ["source"],
140
+ "properties": {
141
+ "source": { "enum": ["snapshot_only", "unavailable"] }
142
+ }
143
+ },
144
+ "then": {
145
+ "not": {
146
+ "anyOf": [
147
+ { "required": ["additions"] },
148
+ { "required": ["deletions"] },
149
+ { "required": ["changedFiles"] }
150
+ ]
151
+ }
152
+ }
153
+ }
154
+ ],
155
+ "properties": {
156
+ "source": { "enum": ["direct", "reconstructed", "snapshot_only", "unavailable"] },
157
+ "confidence": { "type": "string" },
158
+ "additions": { "type": "integer", "minimum": 0 },
159
+ "deletions": { "type": "integer", "minimum": 0 },
160
+ "changedFiles": { "type": "integer", "minimum": 0 }
161
+ }
162
+ },
163
+ "files": {
164
+ "type": "array",
165
+ "items": {
166
+ "type": "object",
167
+ "additionalProperties": false,
168
+ "required": [
169
+ "path",
170
+ "category",
171
+ "role",
172
+ "functionalSurface",
173
+ "generated",
174
+ "classificationSource",
175
+ "ruleId",
176
+ "additions",
177
+ "deletions",
178
+ "changeType"
179
+ ],
180
+ "properties": {
181
+ "path": { "type": "string" },
182
+ "category": { "enum": ["code", "tests", "docs", "config", "generated", "infrastructure", "unknown"] },
183
+ "role": {
184
+ "enum": [
185
+ "core_product_code",
186
+ "product_ui",
187
+ "tests",
188
+ "generated_docs",
189
+ "release_notes",
190
+ "planning_docs",
191
+ "marketing_site",
192
+ "config",
193
+ "infrastructure",
194
+ "fixtures",
195
+ "generated_or_vendored",
196
+ "unknown"
197
+ ]
198
+ },
199
+ "functionalSurface": { "type": "string" },
200
+ "generated": { "type": "boolean" },
201
+ "classificationSource": { "enum": ["repository_profile", "fallback_rule"] },
202
+ "ruleId": { "type": ["string", "null"] },
203
+ "additions": { "type": "integer", "minimum": 0 },
204
+ "deletions": { "type": "integer", "minimum": 0 },
205
+ "changeType": { "type": "string" }
206
+ }
207
+ }
208
+ },
209
+ "reviews": {
210
+ "type": "array",
211
+ "items": {
212
+ "type": "object",
213
+ "additionalProperties": false,
214
+ "required": [
215
+ "id",
216
+ "submittedAt",
217
+ "state",
218
+ "commitOid",
219
+ "source",
220
+ "generatedCommentCount",
221
+ "failedAttempt"
222
+ ],
223
+ "properties": {
224
+ "id": { "type": "string" },
225
+ "submittedAt": { "type": ["string", "null"] },
226
+ "state": { "type": ["string", "null"] },
227
+ "commitOid": { "type": ["string", "null"] },
228
+ "source": {
229
+ "enum": [
230
+ "copilot",
231
+ "human_reviewer",
232
+ "author_reply",
233
+ "github_actions_bot",
234
+ "dependency_bot",
235
+ "code_scanning",
236
+ "unknown_bot",
237
+ "unknown"
238
+ ]
239
+ },
240
+ "generatedCommentCount": { "type": ["integer", "null"], "minimum": 0 },
241
+ "failedAttempt": { "type": "boolean" }
242
+ }
243
+ }
244
+ },
245
+ "reviewDecision": {
246
+ "type": "object",
247
+ "additionalProperties": false,
248
+ "required": [
249
+ "state",
250
+ "humanApproved",
251
+ "humanChangesRequested",
252
+ "humanReviewerCount",
253
+ "source"
254
+ ],
255
+ "properties": {
256
+ "state": {
257
+ "enum": ["approved", "changes_requested", "commented", "review_required", "none", "unavailable"]
258
+ },
259
+ "humanApproved": { "type": "boolean" },
260
+ "humanChangesRequested": { "type": "boolean" },
261
+ "humanReviewerCount": { "type": "integer", "minimum": 0 },
262
+ "source": { "enum": ["reviews", "unavailable"] }
263
+ }
264
+ },
265
+ "reviewThreads": {
266
+ "type": "object",
267
+ "additionalProperties": false,
268
+ "required": ["source", "totalCount", "resolvedCount", "outdatedCount"],
269
+ "properties": {
270
+ "source": { "type": "string" },
271
+ "totalCount": { "type": "integer", "minimum": 0 },
272
+ "resolvedCount": { "type": "integer", "minimum": 0 },
273
+ "outdatedCount": { "type": "integer", "minimum": 0 }
274
+ }
275
+ },
276
+ "reviewComments": {
277
+ "type": "object",
278
+ "additionalProperties": false,
279
+ "required": ["totalCount", "bySource"],
280
+ "properties": {
281
+ "totalCount": { "type": "integer", "minimum": 0 },
282
+ "bySource": {
283
+ "type": "object",
284
+ "additionalProperties": false,
285
+ "required": [
286
+ "copilot",
287
+ "human_reviewer",
288
+ "author_reply",
289
+ "github_actions_bot",
290
+ "dependency_bot",
291
+ "code_scanning",
292
+ "unknown_bot",
293
+ "unknown"
294
+ ],
295
+ "properties": {
296
+ "copilot": { "type": "integer", "minimum": 0 },
297
+ "human_reviewer": { "type": "integer", "minimum": 0 },
298
+ "author_reply": { "type": "integer", "minimum": 0 },
299
+ "github_actions_bot": { "type": "integer", "minimum": 0 },
300
+ "dependency_bot": { "type": "integer", "minimum": 0 },
301
+ "code_scanning": { "type": "integer", "minimum": 0 },
302
+ "unknown_bot": { "type": "integer", "minimum": 0 },
303
+ "unknown": { "type": "integer", "minimum": 0 }
304
+ }
305
+ }
306
+ }
307
+ },
308
+ "checkRuns": {
309
+ "type": "array",
310
+ "items": {
311
+ "type": "object",
312
+ "additionalProperties": false,
313
+ "required": ["source", "name", "workflowName", "status", "conclusion", "startedAt", "completedAt"],
314
+ "properties": {
315
+ "source": { "enum": ["check_run", "status_context"] },
316
+ "name": { "type": ["string", "null"] },
317
+ "workflowName": { "type": ["string", "null"] },
318
+ "status": { "type": ["string", "null"] },
319
+ "conclusion": { "type": ["string", "null"] },
320
+ "startedAt": { "type": ["string", "null"] },
321
+ "completedAt": { "type": ["string", "null"] }
322
+ }
323
+ }
324
+ },
325
+ "workflowRuns": {
326
+ "type": "object",
327
+ "additionalProperties": false,
328
+ "required": ["source", "totalCount", "conclusions"],
329
+ "properties": {
330
+ "source": { "type": "string" },
331
+ "totalCount": { "type": ["integer", "null"], "minimum": 0 },
332
+ "conclusions": {
333
+ "type": "object",
334
+ "additionalProperties": { "type": "integer", "minimum": 0 }
335
+ }
336
+ }
337
+ }
338
+ }
339
+ }
340
+ }
341
+ }
342
+ }
@@ -0,0 +1,92 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://delivery-friction-analyzer.local/schemas/repository-profile.schema.json",
4
+ "title": "RepositoryProfile",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["schemaVersion", "repository", "rules"],
8
+ "properties": {
9
+ "schemaVersion": {
10
+ "const": "repository-profile.v1"
11
+ },
12
+ "repository": {
13
+ "type": "object",
14
+ "additionalProperties": false,
15
+ "required": ["owner", "name"],
16
+ "properties": {
17
+ "owner": { "type": "string" },
18
+ "name": { "type": "string" }
19
+ }
20
+ },
21
+ "rules": {
22
+ "type": "array",
23
+ "items": {
24
+ "type": "object",
25
+ "additionalProperties": false,
26
+ "required": ["id", "match", "category", "role"],
27
+ "properties": {
28
+ "id": { "type": "string" },
29
+ "match": {
30
+ "type": "object",
31
+ "additionalProperties": false,
32
+ "properties": {
33
+ "exact": { "type": "string" },
34
+ "prefix": { "type": "string" },
35
+ "suffix": { "type": "string" },
36
+ "includes": { "type": "string" },
37
+ "regex": { "type": "string" }
38
+ },
39
+ "minProperties": 1
40
+ },
41
+ "category": {
42
+ "enum": ["code", "tests", "docs", "config", "generated", "infrastructure", "unknown"]
43
+ },
44
+ "role": {
45
+ "enum": [
46
+ "core_product_code",
47
+ "product_ui",
48
+ "tests",
49
+ "generated_docs",
50
+ "release_notes",
51
+ "planning_docs",
52
+ "marketing_site",
53
+ "config",
54
+ "infrastructure",
55
+ "fixtures",
56
+ "generated_or_vendored",
57
+ "unknown"
58
+ ]
59
+ },
60
+ "functionalSurface": { "type": "string" },
61
+ "generated": { "type": "boolean" },
62
+ "notes": { "type": "string" }
63
+ }
64
+ }
65
+ },
66
+ "prClasses": {
67
+ "type": "array",
68
+ "items": {
69
+ "type": "object",
70
+ "additionalProperties": false,
71
+ "required": ["id", "class", "match"],
72
+ "properties": {
73
+ "id": { "type": "string", "minLength": 1 },
74
+ "class": {
75
+ "type": "string",
76
+ "pattern": "^[a-z0-9]+(?:[-_][a-z0-9]+)*$"
77
+ },
78
+ "match": {
79
+ "type": "object",
80
+ "additionalProperties": false,
81
+ "properties": {
82
+ "titleIncludes": { "type": "string", "minLength": 1 },
83
+ "titleRegex": { "type": "string", "minLength": 1 }
84
+ },
85
+ "minProperties": 1
86
+ },
87
+ "notes": { "type": "string" }
88
+ }
89
+ }
90
+ }
91
+ }
92
+ }