specfact-cli 0.4.2__py3-none-any.whl → 0.6.8__py3-none-any.whl

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.
Files changed (66) hide show
  1. specfact_cli/__init__.py +1 -1
  2. specfact_cli/agents/analyze_agent.py +2 -3
  3. specfact_cli/analyzers/__init__.py +2 -1
  4. specfact_cli/analyzers/ambiguity_scanner.py +601 -0
  5. specfact_cli/analyzers/code_analyzer.py +462 -30
  6. specfact_cli/analyzers/constitution_evidence_extractor.py +491 -0
  7. specfact_cli/analyzers/contract_extractor.py +419 -0
  8. specfact_cli/analyzers/control_flow_analyzer.py +281 -0
  9. specfact_cli/analyzers/requirement_extractor.py +337 -0
  10. specfact_cli/analyzers/test_pattern_extractor.py +330 -0
  11. specfact_cli/cli.py +151 -206
  12. specfact_cli/commands/constitution.py +281 -0
  13. specfact_cli/commands/enforce.py +42 -34
  14. specfact_cli/commands/import_cmd.py +481 -152
  15. specfact_cli/commands/init.py +224 -55
  16. specfact_cli/commands/plan.py +2133 -547
  17. specfact_cli/commands/repro.py +100 -78
  18. specfact_cli/commands/sync.py +701 -186
  19. specfact_cli/enrichers/constitution_enricher.py +765 -0
  20. specfact_cli/enrichers/plan_enricher.py +294 -0
  21. specfact_cli/importers/speckit_converter.py +364 -48
  22. specfact_cli/importers/speckit_scanner.py +65 -0
  23. specfact_cli/models/plan.py +42 -0
  24. specfact_cli/resources/mappings/node-async.yaml +49 -0
  25. specfact_cli/resources/mappings/python-async.yaml +47 -0
  26. specfact_cli/resources/mappings/speckit-default.yaml +82 -0
  27. specfact_cli/resources/prompts/specfact-enforce.md +185 -0
  28. specfact_cli/resources/prompts/specfact-import-from-code.md +626 -0
  29. specfact_cli/resources/prompts/specfact-plan-add-feature.md +188 -0
  30. specfact_cli/resources/prompts/specfact-plan-add-story.md +212 -0
  31. specfact_cli/resources/prompts/specfact-plan-compare.md +571 -0
  32. specfact_cli/resources/prompts/specfact-plan-init.md +531 -0
  33. specfact_cli/resources/prompts/specfact-plan-promote.md +352 -0
  34. specfact_cli/resources/prompts/specfact-plan-review.md +1276 -0
  35. specfact_cli/resources/prompts/specfact-plan-select.md +401 -0
  36. specfact_cli/resources/prompts/specfact-plan-update-feature.md +242 -0
  37. specfact_cli/resources/prompts/specfact-plan-update-idea.md +211 -0
  38. specfact_cli/resources/prompts/specfact-repro.md +268 -0
  39. specfact_cli/resources/prompts/specfact-sync.md +497 -0
  40. specfact_cli/resources/schemas/deviation.schema.json +61 -0
  41. specfact_cli/resources/schemas/plan.schema.json +204 -0
  42. specfact_cli/resources/schemas/protocol.schema.json +53 -0
  43. specfact_cli/resources/templates/github-action.yml.j2 +140 -0
  44. specfact_cli/resources/templates/plan.bundle.yaml.j2 +141 -0
  45. specfact_cli/resources/templates/pr-template.md.j2 +58 -0
  46. specfact_cli/resources/templates/protocol.yaml.j2 +24 -0
  47. specfact_cli/resources/templates/telemetry.yaml.example +35 -0
  48. specfact_cli/sync/__init__.py +10 -1
  49. specfact_cli/sync/watcher.py +268 -0
  50. specfact_cli/telemetry.py +440 -0
  51. specfact_cli/utils/acceptance_criteria.py +127 -0
  52. specfact_cli/utils/enrichment_parser.py +445 -0
  53. specfact_cli/utils/feature_keys.py +12 -3
  54. specfact_cli/utils/ide_setup.py +170 -0
  55. specfact_cli/utils/structure.py +179 -2
  56. specfact_cli/utils/yaml_utils.py +33 -0
  57. specfact_cli/validators/repro_checker.py +22 -1
  58. specfact_cli/validators/schema.py +15 -4
  59. specfact_cli-0.6.8.dist-info/METADATA +456 -0
  60. specfact_cli-0.6.8.dist-info/RECORD +99 -0
  61. {specfact_cli-0.4.2.dist-info → specfact_cli-0.6.8.dist-info}/entry_points.txt +1 -0
  62. specfact_cli-0.6.8.dist-info/licenses/LICENSE.md +202 -0
  63. specfact_cli-0.4.2.dist-info/METADATA +0 -370
  64. specfact_cli-0.4.2.dist-info/RECORD +0 -62
  65. specfact_cli-0.4.2.dist-info/licenses/LICENSE.md +0 -61
  66. {specfact_cli-0.4.2.dist-info → specfact_cli-0.6.8.dist-info}/WHEEL +0 -0
@@ -0,0 +1,204 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "Plan Bundle Schema",
4
+ "description": "Schema for SpecFact CLI plan bundle validation",
5
+ "type": "object",
6
+ "required": ["version", "product"],
7
+ "properties": {
8
+ "version": {
9
+ "type": "string",
10
+ "pattern": "^\\d+\\.\\d+$",
11
+ "description": "Plan bundle version"
12
+ },
13
+ "idea": {
14
+ "type": "object",
15
+ "required": ["title", "narrative"],
16
+ "properties": {
17
+ "title": {
18
+ "type": "string",
19
+ "minLength": 1
20
+ },
21
+ "narrative": {
22
+ "type": "string",
23
+ "minLength": 1
24
+ },
25
+ "target_users": {
26
+ "type": "array",
27
+ "items": {
28
+ "type": "string"
29
+ }
30
+ },
31
+ "value_hypothesis": {
32
+ "type": "string"
33
+ },
34
+ "constraints": {
35
+ "type": "array",
36
+ "items": {
37
+ "type": "string"
38
+ }
39
+ },
40
+ "metrics": {
41
+ "type": "object"
42
+ }
43
+ }
44
+ },
45
+ "business": {
46
+ "type": "object",
47
+ "properties": {
48
+ "segments": {
49
+ "type": "array",
50
+ "items": {
51
+ "type": "string"
52
+ }
53
+ },
54
+ "problems": {
55
+ "type": "array",
56
+ "items": {
57
+ "type": "string"
58
+ }
59
+ },
60
+ "solutions": {
61
+ "type": "array",
62
+ "items": {
63
+ "type": "string"
64
+ }
65
+ },
66
+ "differentiation": {
67
+ "type": "array",
68
+ "items": {
69
+ "type": "string"
70
+ }
71
+ },
72
+ "risks": {
73
+ "type": "array",
74
+ "items": {
75
+ "type": "string"
76
+ }
77
+ }
78
+ }
79
+ },
80
+ "product": {
81
+ "type": "object",
82
+ "required": ["themes"],
83
+ "properties": {
84
+ "themes": {
85
+ "type": "array",
86
+ "items": {
87
+ "type": "string"
88
+ }
89
+ },
90
+ "releases": {
91
+ "type": "array",
92
+ "items": {
93
+ "type": "object",
94
+ "required": ["name"],
95
+ "properties": {
96
+ "name": {
97
+ "type": "string"
98
+ },
99
+ "objectives": {
100
+ "type": "array",
101
+ "items": {
102
+ "type": "string"
103
+ }
104
+ },
105
+ "scope": {
106
+ "type": "array",
107
+ "items": {
108
+ "type": "string"
109
+ }
110
+ },
111
+ "risks": {
112
+ "type": "array",
113
+ "items": {
114
+ "type": "string"
115
+ }
116
+ }
117
+ }
118
+ }
119
+ }
120
+ }
121
+ },
122
+ "features": {
123
+ "type": "array",
124
+ "items": {
125
+ "type": "object",
126
+ "required": ["key", "title"],
127
+ "properties": {
128
+ "key": {
129
+ "type": "string",
130
+ "pattern": "^FEATURE-\\d+$"
131
+ },
132
+ "title": {
133
+ "type": "string",
134
+ "minLength": 1
135
+ },
136
+ "outcomes": {
137
+ "type": "array",
138
+ "items": {
139
+ "type": "string"
140
+ }
141
+ },
142
+ "acceptance": {
143
+ "type": "array",
144
+ "items": {
145
+ "type": "string"
146
+ }
147
+ },
148
+ "constraints": {
149
+ "type": "array",
150
+ "items": {
151
+ "type": "string"
152
+ }
153
+ },
154
+ "stories": {
155
+ "type": "array",
156
+ "items": {
157
+ "type": "object",
158
+ "required": ["key", "title"],
159
+ "properties": {
160
+ "key": {
161
+ "type": "string",
162
+ "pattern": "^STORY-\\d+$"
163
+ },
164
+ "title": {
165
+ "type": "string",
166
+ "minLength": 1
167
+ },
168
+ "acceptance": {
169
+ "type": "array",
170
+ "items": {
171
+ "type": "string"
172
+ }
173
+ },
174
+ "tags": {
175
+ "type": "array",
176
+ "items": {
177
+ "type": "string"
178
+ }
179
+ },
180
+ "confidence": {
181
+ "type": "number",
182
+ "minimum": 0.0,
183
+ "maximum": 1.0
184
+ },
185
+ "draft": {
186
+ "type": "boolean"
187
+ }
188
+ }
189
+ }
190
+ },
191
+ "confidence": {
192
+ "type": "number",
193
+ "minimum": 0.0,
194
+ "maximum": 1.0
195
+ },
196
+ "draft": {
197
+ "type": "boolean"
198
+ }
199
+ }
200
+ }
201
+ }
202
+ }
203
+ }
204
+
@@ -0,0 +1,53 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "Protocol Schema",
4
+ "description": "Schema for SpecFact CLI FSM protocol validation",
5
+ "type": "object",
6
+ "required": ["states", "start", "transitions"],
7
+ "properties": {
8
+ "states": {
9
+ "type": "array",
10
+ "items": {
11
+ "type": "string"
12
+ },
13
+ "minItems": 1,
14
+ "uniqueItems": true,
15
+ "description": "List of state names"
16
+ },
17
+ "start": {
18
+ "type": "string",
19
+ "description": "Initial state name"
20
+ },
21
+ "transitions": {
22
+ "type": "array",
23
+ "items": {
24
+ "type": "object",
25
+ "required": ["from_state", "on_event", "to_state"],
26
+ "properties": {
27
+ "from_state": {
28
+ "type": "string"
29
+ },
30
+ "on_event": {
31
+ "type": "string"
32
+ },
33
+ "to_state": {
34
+ "type": "string"
35
+ },
36
+ "guard": {
37
+ "type": "string",
38
+ "description": "Guard function name"
39
+ }
40
+ }
41
+ },
42
+ "description": "List of state transitions"
43
+ },
44
+ "guards": {
45
+ "type": "object",
46
+ "additionalProperties": {
47
+ "type": "string"
48
+ },
49
+ "description": "Guard definitions"
50
+ }
51
+ }
52
+ }
53
+
@@ -0,0 +1,140 @@
1
+ # yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
2
+ # yamllint disable rule:line-length rule:truthy
3
+ name: SpecFact CLI Validation
4
+
5
+ on:
6
+ pull_request:
7
+ branches: [main, dev]
8
+ paths-ignore:
9
+ - "docs/**"
10
+ - "**.md"
11
+ - "**.mdc"
12
+ push:
13
+ branches: [main, dev]
14
+ paths-ignore:
15
+ - "docs/**"
16
+ - "**.md"
17
+ - "**.mdc"
18
+ workflow_dispatch:
19
+ inputs:
20
+ budget:
21
+ description: "Time budget in seconds"
22
+ required: false
23
+ default: "{{ budget }}"
24
+ type: string
25
+ mode:
26
+ description: "Enforcement mode (block, warn, log)"
27
+ required: false
28
+ default: "block"
29
+ type: choice
30
+ options:
31
+ - block
32
+ - warn
33
+ - log
34
+
35
+ jobs:
36
+ specfact-validation:
37
+ name: Contract Validation
38
+ runs-on: ubuntu-latest
39
+ permissions:
40
+ contents: read
41
+ pull-requests: write
42
+ checks: write
43
+ steps:
44
+ - name: Checkout
45
+ uses: actions/checkout@v4
46
+
47
+ - name: Set up Python
48
+ uses: actions/setup-python@v5
49
+ with:
50
+ python-version: "{{ python_version }}"
51
+ cache: "pip"
52
+
53
+ - name: Install dependencies
54
+ run: |
55
+ python -m pip install --upgrade pip
56
+ pip install hatch
57
+
58
+ - name: Install SpecFact CLI
59
+ run: |
60
+ echo "📦 Installing SpecFact CLI..."
61
+ pip install specfact-cli
62
+
63
+ - name: Set validation parameters
64
+ id: validation
65
+ run: |
66
+ BUDGET="${INPUT_BUDGET:-{{ budget }}}"
67
+ MODE="${INPUT_MODE:-block}"
68
+ echo "budget=$BUDGET" >> $GITHUB_OUTPUT
69
+ echo "mode=$MODE" >> $GITHUB_OUTPUT
70
+ echo "SPECFACT_BUDGET=$BUDGET" >> $GITHUB_ENV
71
+ echo "SPECFACT_MODE=$MODE" >> $GITHUB_ENV
72
+
73
+ - name: Run Contract Validation
74
+ id: repro
75
+ continue-on-error: true
76
+ run: |
77
+ specfact repro --verbose --budget {% raw %}${{ steps.validation.outputs.budget }}{% endraw %} || true
78
+ echo "exit_code=$?" >> $GITHUB_OUTPUT
79
+
80
+ - name: Find latest repro report
81
+ id: report
82
+ if: always()
83
+ run: |
84
+ REPORT_DIR=".specfact/reports/enforcement"
85
+ if [ -d "$REPORT_DIR" ]; then
86
+ LATEST_REPORT=$(find "$REPORT_DIR" -name "report-*.yaml" -type f -printf "%T@ %p\n" | sort -n | tail -1 | cut -d' ' -f2-)
87
+ if [ -n "$LATEST_REPORT" ]; then
88
+ echo "path=$LATEST_REPORT" >> $GITHUB_OUTPUT
89
+ echo "SPECFACT_REPORT_PATH=$LATEST_REPORT" >> $GITHUB_ENV
90
+ fi
91
+ fi
92
+
93
+ - name: Create GitHub annotations
94
+ id: annotations
95
+ if: always() && {% raw %}steps.report.outputs.path != ''{% endraw %}
96
+ run: |
97
+ python -m specfact_cli.utils.github_annotations || true
98
+
99
+ - name: Generate PR comment
100
+ id: pr-comment
101
+ if: always() && {% raw %}github.event_name == 'pull_request' && steps.report.outputs.path != ''{% endraw %}
102
+ run: |
103
+ python -m specfact_cli.utils.github_annotations
104
+ if [ -f ".specfact/pr-comment.md" ]; then
105
+ echo "comment_path=.specfact/pr-comment.md" >> $GITHUB_OUTPUT
106
+ fi
107
+
108
+ - name: Post PR comment
109
+ if: always() && {% raw %}github.event_name == 'pull_request' && steps.pr-comment.outputs.comment_path != ''{% endraw %}
110
+ uses: actions/github-script@v7
111
+ with:
112
+ script: |
113
+ const fs = require('fs');
114
+ const commentPath = '{% raw %}${{ steps.pr-comment.outputs.comment_path }}{% endraw %}';
115
+ if (fs.existsSync(commentPath)) {
116
+ const comment = fs.readFileSync(commentPath, 'utf8');
117
+ github.rest.issues.createComment({
118
+ issue_number: context.issue.number,
119
+ owner: context.repo.owner,
120
+ repo: context.repo.repo,
121
+ body: comment
122
+ });
123
+ }
124
+
125
+ - name: Upload validation report
126
+ if: always()
127
+ uses: actions/upload-artifact@v4
128
+ with:
129
+ name: specfact-report
130
+ path: |
131
+ .specfact/reports/enforcement/*.yaml
132
+ .specfact/pr-comment.md
133
+ if-no-files-found: ignore
134
+
135
+ - name: Fail workflow if validation failed
136
+ if: {% raw %}steps.repro.outputs.exit_code != '0' && steps.validation.outputs.mode == 'block'{% endraw %}
137
+ run: |
138
+ echo "❌ Validation failed. Exiting with error code."
139
+ exit 1
140
+
@@ -0,0 +1,141 @@
1
+ version: "1.0"
2
+
3
+ {% if idea %}
4
+ idea:
5
+ title: {{ idea.title }}
6
+ narrative: {{ idea.narrative }}
7
+ {% if idea.target_users %}
8
+ target_users:
9
+ {% for user in idea.target_users %}
10
+ - {{ user }}
11
+ {% endfor %}
12
+ {% endif %}
13
+ {% if idea.value_hypothesis %}
14
+ value_hypothesis: {{ idea.value_hypothesis }}
15
+ {% endif %}
16
+ {% if idea.constraints %}
17
+ constraints:
18
+ {% for constraint in idea.constraints %}
19
+ - {{ constraint }}
20
+ {% endfor %}
21
+ {% endif %}
22
+ {% if idea.metrics %}
23
+ metrics: {{ idea.metrics | tojson }}
24
+ {% endif %}
25
+ {% endif %}
26
+
27
+ {% if business %}
28
+ business:
29
+ {% if business.segments %}
30
+ segments:
31
+ {% for segment in business.segments %}
32
+ - {{ segment }}
33
+ {% endfor %}
34
+ {% endif %}
35
+ {% if business.problems %}
36
+ problems:
37
+ {% for problem in business.problems %}
38
+ - {{ problem }}
39
+ {% endfor %}
40
+ {% endif %}
41
+ {% if business.solutions %}
42
+ solutions:
43
+ {% for solution in business.solutions %}
44
+ - {{ solution }}
45
+ {% endfor %}
46
+ {% endif %}
47
+ {% if business.differentiation %}
48
+ differentiation:
49
+ {% for diff in business.differentiation %}
50
+ - {{ diff }}
51
+ {% endfor %}
52
+ {% endif %}
53
+ {% if business.risks %}
54
+ risks:
55
+ {% for risk in business.risks %}
56
+ - {{ risk }}
57
+ {% endfor %}
58
+ {% endif %}
59
+ {% endif %}
60
+
61
+ product:
62
+ {% if product.themes %}
63
+ themes:
64
+ {% for theme in product.themes %}
65
+ - {{ theme }}
66
+ {% endfor %}
67
+ {% endif %}
68
+ {% if product.releases %}
69
+ releases:
70
+ {% for release in product.releases %}
71
+ - name: {{ release.name }}
72
+ {% if release.objectives %}
73
+ objectives:
74
+ {% for objective in release.objectives %}
75
+ - {{ objective }}
76
+ {% endfor %}
77
+ {% endif %}
78
+ {% if release.scope %}
79
+ scope:
80
+ {% for item in release.scope %}
81
+ - {{ item }}
82
+ {% endfor %}
83
+ {% endif %}
84
+ {% if release.risks %}
85
+ risks:
86
+ {% for risk in release.risks %}
87
+ - {{ risk }}
88
+ {% endfor %}
89
+ {% endif %}
90
+ {% endfor %}
91
+ {% endif %}
92
+
93
+ {% if features %}
94
+ features:
95
+ {% for feature in features %}
96
+ - key: {{ feature.key }}
97
+ title: {{ feature.title }}
98
+ {% if feature.outcomes %}
99
+ outcomes:
100
+ {% for outcome in feature.outcomes %}
101
+ - {{ outcome }}
102
+ {% endfor %}
103
+ {% endif %}
104
+ {% if feature.acceptance %}
105
+ acceptance:
106
+ {% for criterion in feature.acceptance %}
107
+ - {{ criterion }}
108
+ {% endfor %}
109
+ {% endif %}
110
+ {% if feature.constraints %}
111
+ constraints:
112
+ {% for constraint in feature.constraints %}
113
+ - {{ constraint }}
114
+ {% endfor %}
115
+ {% endif %}
116
+ {% if feature.stories %}
117
+ stories:
118
+ {% for story in feature.stories %}
119
+ - key: {{ story.key }}
120
+ title: {{ story.title }}
121
+ {% if story.acceptance %}
122
+ acceptance:
123
+ {% for criterion in story.acceptance %}
124
+ - {{ criterion }}
125
+ {% endfor %}
126
+ {% endif %}
127
+ {% if story.tags %}
128
+ tags:
129
+ {% for tag in story.tags %}
130
+ - {{ tag }}
131
+ {% endfor %}
132
+ {% endif %}
133
+ confidence: {{ story.confidence }}
134
+ draft: {{ story.draft | lower }}
135
+ {% endfor %}
136
+ {% endif %}
137
+ confidence: {{ feature.confidence }}
138
+ draft: {{ feature.draft | lower }}
139
+ {% endfor %}
140
+ {% endif %}
141
+
@@ -0,0 +1,58 @@
1
+ ## 🎯 Purpose
2
+
3
+ {{ purpose | default("Describe the purpose of this PR") }}
4
+
5
+ ## 📋 Changes
6
+
7
+ {% if changes %}
8
+ {% for change in changes %}
9
+ - {{ change }}
10
+ {% endfor %}
11
+ {% else %}
12
+ - [ ] List your changes here
13
+ {% endif %}
14
+
15
+ ## ✅ Validation
16
+
17
+ **SpecFact CLI Validation Results:**
18
+
19
+ {% if validation_passed %}
20
+ - ✅ All contracts validated successfully
21
+ - ✅ No plan deviations detected
22
+ - ✅ FSM protocol compliant
23
+ {% else %}
24
+ - ⚠️ Validation findings:
25
+ {% if high_count > 0 %}
26
+ - {{ high_count }} HIGH severity issue(s)
27
+ {% endif %}
28
+ {% if medium_count > 0 %}
29
+ - {{ medium_count }} MEDIUM severity issue(s)
30
+ {% endif %}
31
+ {% if low_count > 0 %}
32
+ - {{ low_count }} LOW severity issue(s)
33
+ {% endif %}
34
+ {% endif %}
35
+
36
+ ## 📊 Coverage
37
+
38
+ {% if coverage %}
39
+ - **Line Coverage**: {{ coverage.line }}%
40
+ - **Branch Coverage**: {{ coverage.branch }}%
41
+ {% else %}
42
+ - [ ] Add coverage information
43
+ {% endif %}
44
+
45
+ ## 🔗 Related
46
+
47
+ {% if related_issues %}
48
+ {% for issue in related_issues %}
49
+ - Closes #{{ issue }}
50
+ {% endfor %}
51
+ {% else %}
52
+ - [ ] Link related issues/PRs
53
+ {% endif %}
54
+
55
+ ## 📝 Notes
56
+
57
+ {{ notes | default("Add any additional notes here") }}
58
+
@@ -0,0 +1,24 @@
1
+ states:
2
+ {% for state in states %}
3
+ - {{ state }}
4
+ {% endfor %}
5
+
6
+ start: {{ start }}
7
+
8
+ transitions:
9
+ {% for transition in transitions %}
10
+ - from_state: {{ transition.from_state }}
11
+ on_event: {{ transition.on_event }}
12
+ to_state: {{ transition.to_state }}
13
+ {% if transition.guard %}
14
+ guard: {{ transition.guard }}
15
+ {% endif %}
16
+ {% endfor %}
17
+
18
+ {% if guards %}
19
+ guards:
20
+ {% for guard_name, guard_expr in guards.items() %}
21
+ {{ guard_name }}: "{{ guard_expr }}"
22
+ {% endfor %}
23
+ {% endif %}
24
+
@@ -0,0 +1,35 @@
1
+ # SpecFact CLI Telemetry Configuration
2
+ #
3
+ # This is an example configuration file for SpecFact CLI telemetry.
4
+ #
5
+ # To use this template:
6
+ # 1. Copy this file to ~/.specfact/telemetry.yaml
7
+ # 2. Customize the settings below
8
+ # 3. Replace YOUR_BASE64_ENCODED_CREDENTIALS_HERE with your actual credentials
9
+ #
10
+ # For more information, see: docs/reference/telemetry.md
11
+
12
+ # Enable telemetry (required)
13
+ enabled: true
14
+
15
+ # OTLP endpoint (HTTPS recommended for corporate environments)
16
+ # Example for Grafana Cloud EU:
17
+ # Get the exact endpoint from: Grafana Cloud Dashboard > Connections > OpenTelemetry > Send traces
18
+ endpoint: "https://otlp-gateway-prod-eu-west-2.grafana.net/otlp/v1/traces"
19
+
20
+ # Authentication headers
21
+ # For Grafana Cloud, get credentials from: Dashboard > Connections > OpenTelemetry > Send traces
22
+ # Format: "Basic <base64(instance-id:api-key)>"
23
+ # The token from Grafana Cloud setup wizard can be used directly
24
+ headers:
25
+ Authorization: "Basic YOUR_BASE64_ENCODED_CREDENTIALS_HERE"
26
+
27
+ # Optional: Advanced configuration
28
+ service_name: "specfact-cli" # Custom service name (default: "specfact-cli")
29
+ service_namespace: "cli" # Service namespace (default: "cli") - used by Grafana Cloud
30
+ deployment_environment: "production" # Deployment environment (default: "production") - used by Grafana Cloud
31
+ batch_size: 512 # Batch size (default: 512)
32
+ batch_timeout: 5 # Batch timeout in seconds (default: 5)
33
+ export_timeout: 10 # Export timeout in seconds (default: 10)
34
+ debug: false # Enable console output for debugging (default: false)
35
+ local_path: "~/.specfact/telemetry.log" # Local log file path (default: ~/.specfact/telemetry.log)
@@ -7,6 +7,15 @@ repository changes, and SpecFact plans.
7
7
 
8
8
  from specfact_cli.sync.repository_sync import RepositorySync, RepositorySyncResult
9
9
  from specfact_cli.sync.speckit_sync import SpecKitSync, SyncResult
10
+ from specfact_cli.sync.watcher import FileChange, SyncEventHandler, SyncWatcher
10
11
 
11
12
 
12
- __all__ = ["RepositorySync", "RepositorySyncResult", "SpecKitSync", "SyncResult"]
13
+ __all__ = [
14
+ "FileChange",
15
+ "RepositorySync",
16
+ "RepositorySyncResult",
17
+ "SpecKitSync",
18
+ "SyncEventHandler",
19
+ "SyncResult",
20
+ "SyncWatcher",
21
+ ]