specfact-cli 0.4.0__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.

Potentially problematic release.


This version of specfact-cli might be problematic. Click here for more details.

Files changed (60) hide show
  1. specfact_cli/__init__.py +14 -0
  2. specfact_cli/agents/__init__.py +23 -0
  3. specfact_cli/agents/analyze_agent.py +392 -0
  4. specfact_cli/agents/base.py +95 -0
  5. specfact_cli/agents/plan_agent.py +202 -0
  6. specfact_cli/agents/registry.py +176 -0
  7. specfact_cli/agents/sync_agent.py +133 -0
  8. specfact_cli/analyzers/__init__.py +10 -0
  9. specfact_cli/analyzers/code_analyzer.py +775 -0
  10. specfact_cli/cli.py +397 -0
  11. specfact_cli/commands/__init__.py +7 -0
  12. specfact_cli/commands/enforce.py +87 -0
  13. specfact_cli/commands/import_cmd.py +355 -0
  14. specfact_cli/commands/init.py +119 -0
  15. specfact_cli/commands/plan.py +1090 -0
  16. specfact_cli/commands/repro.py +172 -0
  17. specfact_cli/commands/sync.py +408 -0
  18. specfact_cli/common/__init__.py +24 -0
  19. specfact_cli/common/logger_setup.py +673 -0
  20. specfact_cli/common/logging_utils.py +41 -0
  21. specfact_cli/common/text_utils.py +52 -0
  22. specfact_cli/common/utils.py +48 -0
  23. specfact_cli/comparators/__init__.py +10 -0
  24. specfact_cli/comparators/plan_comparator.py +391 -0
  25. specfact_cli/generators/__init__.py +13 -0
  26. specfact_cli/generators/plan_generator.py +105 -0
  27. specfact_cli/generators/protocol_generator.py +115 -0
  28. specfact_cli/generators/report_generator.py +200 -0
  29. specfact_cli/generators/workflow_generator.py +111 -0
  30. specfact_cli/importers/__init__.py +6 -0
  31. specfact_cli/importers/speckit_converter.py +773 -0
  32. specfact_cli/importers/speckit_scanner.py +704 -0
  33. specfact_cli/models/__init__.py +32 -0
  34. specfact_cli/models/deviation.py +105 -0
  35. specfact_cli/models/enforcement.py +150 -0
  36. specfact_cli/models/plan.py +97 -0
  37. specfact_cli/models/protocol.py +28 -0
  38. specfact_cli/modes/__init__.py +18 -0
  39. specfact_cli/modes/detector.py +126 -0
  40. specfact_cli/modes/router.py +153 -0
  41. specfact_cli/sync/__init__.py +11 -0
  42. specfact_cli/sync/repository_sync.py +279 -0
  43. specfact_cli/sync/speckit_sync.py +388 -0
  44. specfact_cli/utils/__init__.py +57 -0
  45. specfact_cli/utils/console.py +69 -0
  46. specfact_cli/utils/feature_keys.py +213 -0
  47. specfact_cli/utils/git.py +241 -0
  48. specfact_cli/utils/ide_setup.py +381 -0
  49. specfact_cli/utils/prompts.py +179 -0
  50. specfact_cli/utils/structure.py +496 -0
  51. specfact_cli/utils/yaml_utils.py +200 -0
  52. specfact_cli/validators/__init__.py +19 -0
  53. specfact_cli/validators/fsm.py +260 -0
  54. specfact_cli/validators/repro_checker.py +320 -0
  55. specfact_cli/validators/schema.py +200 -0
  56. specfact_cli-0.4.0.dist-info/METADATA +332 -0
  57. specfact_cli-0.4.0.dist-info/RECORD +60 -0
  58. specfact_cli-0.4.0.dist-info/WHEEL +4 -0
  59. specfact_cli-0.4.0.dist-info/entry_points.txt +2 -0
  60. specfact_cli-0.4.0.dist-info/licenses/LICENSE.md +55 -0
@@ -0,0 +1,200 @@
1
+ """
2
+ Schema validation module.
3
+
4
+ This module provides schema validation for plan bundles and protocols.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import json
10
+ from pathlib import Path
11
+
12
+ import jsonschema
13
+ import yaml
14
+ from beartype import beartype
15
+ from icontract import ensure, require
16
+ from pydantic import ValidationError
17
+
18
+ from specfact_cli.models.deviation import Deviation, DeviationSeverity, DeviationType, ValidationReport
19
+ from specfact_cli.models.plan import PlanBundle
20
+ from specfact_cli.models.protocol import Protocol
21
+
22
+
23
+ class SchemaValidator:
24
+ """Schema validator for plan bundles and protocols."""
25
+
26
+ def __init__(self, schemas_dir: Path | None = None):
27
+ """
28
+ Initialize schema validator.
29
+
30
+ Args:
31
+ schemas_dir: Directory containing JSON schemas (default: resources/schemas)
32
+ """
33
+ if schemas_dir is None:
34
+ # Default to resources/schemas relative to project root
35
+ schemas_dir = Path(__file__).parent.parent.parent.parent / "resources" / "schemas"
36
+
37
+ self.schemas_dir = Path(schemas_dir)
38
+ self._schemas: dict[str, dict] = {}
39
+
40
+ def _load_schema(self, schema_name: str) -> dict:
41
+ """
42
+ Load JSON schema from file.
43
+
44
+ Args:
45
+ schema_name: Name of the schema file (with or without .schema.json extension)
46
+
47
+ Returns:
48
+ Loaded schema dict
49
+
50
+ Raises:
51
+ FileNotFoundError: If schema file doesn't exist
52
+ """
53
+ if schema_name not in self._schemas:
54
+ # Handle both "plan" and "plan.schema.json" as input
55
+ if schema_name.endswith(".schema.json"):
56
+ schema_path = self.schemas_dir / schema_name
57
+ elif schema_name.endswith(".json"):
58
+ # Just add .schema if only .json is present
59
+ schema_path = self.schemas_dir / schema_name.replace(".json", ".schema.json")
60
+ else:
61
+ # Add full suffix
62
+ schema_path = self.schemas_dir / f"{schema_name}.schema.json"
63
+
64
+ if not schema_path.exists():
65
+ raise FileNotFoundError(f"Schema file not found: {schema_path}")
66
+
67
+ with open(schema_path, encoding="utf-8") as f:
68
+ self._schemas[schema_name] = json.load(f)
69
+
70
+ return self._schemas[schema_name]
71
+
72
+ @beartype
73
+ @require(lambda data: isinstance(data, dict), "Data must be dictionary")
74
+ @require(
75
+ lambda schema_name: isinstance(schema_name, str) and len(schema_name) > 0,
76
+ "Schema name must be non-empty string",
77
+ )
78
+ @ensure(lambda result: isinstance(result, ValidationReport), "Must return ValidationReport")
79
+ def validate_json_schema(self, data: dict, schema_name: str) -> ValidationReport:
80
+ """
81
+ Validate data against JSON schema.
82
+
83
+ Args:
84
+ data: Data to validate
85
+ schema_name: Name of the schema (e.g., 'plan', 'protocol', 'deviation')
86
+
87
+ Returns:
88
+ Validation report
89
+ """
90
+ report = ValidationReport()
91
+
92
+ try:
93
+ schema = self._load_schema(schema_name)
94
+ jsonschema.validate(instance=data, schema=schema)
95
+
96
+ except jsonschema.ValidationError as e:
97
+ deviation = Deviation(
98
+ type=DeviationType.FSM_MISMATCH, # Generic type for schema violations
99
+ severity=DeviationSeverity.HIGH,
100
+ description=f"Schema validation failed: {e.message}",
101
+ location=f"${'.'.join(str(p) for p in e.path)}" if e.path else "root",
102
+ fix_hint=f"Expected {e.validator}: {e.validator_value}",
103
+ )
104
+ report.add_deviation(deviation)
105
+
106
+ except FileNotFoundError as e:
107
+ deviation = Deviation(
108
+ type=DeviationType.FSM_MISMATCH,
109
+ severity=DeviationSeverity.HIGH,
110
+ description=str(e),
111
+ location="schema",
112
+ fix_hint="Ensure the schema file exists in the schemas directory",
113
+ )
114
+ report.add_deviation(deviation)
115
+
116
+ return report
117
+
118
+
119
+ @beartype
120
+ @ensure(
121
+ lambda result: isinstance(result, ValidationReport)
122
+ or (isinstance(result, tuple) and len(result) == 3 and isinstance(result[0], bool)),
123
+ "Must return ValidationReport or tuple[bool, str | None, PlanBundle | None]",
124
+ )
125
+ def validate_plan_bundle(
126
+ plan_or_path: PlanBundle | Path,
127
+ ) -> ValidationReport | tuple[bool, str | None, PlanBundle | None]:
128
+ """
129
+ Validate a plan bundle model or YAML file.
130
+
131
+ Args:
132
+ plan_or_path: PlanBundle model or Path to plan bundle YAML file
133
+
134
+ Returns:
135
+ ValidationReport if model provided, tuple of (is_valid, error_message, parsed_bundle) if path provided
136
+ """
137
+ # If it's already a model, just return success report
138
+ if isinstance(plan_or_path, PlanBundle):
139
+ report = ValidationReport()
140
+ # Could add additional validation logic here if needed
141
+ return report
142
+
143
+ # Otherwise treat as path
144
+ path = plan_or_path
145
+ try:
146
+ with path.open("r") as f:
147
+ data = yaml.safe_load(f)
148
+
149
+ bundle = PlanBundle(**data)
150
+ return True, None, bundle
151
+
152
+ except FileNotFoundError:
153
+ return False, f"File not found: {path}", None
154
+ except yaml.YAMLError as e:
155
+ return False, f"YAML parsing error: {e}", None
156
+ except ValidationError as e:
157
+ return False, f"Validation error: {e}", None
158
+ except Exception as e:
159
+ return False, f"Unexpected error: {e}", None
160
+
161
+
162
+ @beartype
163
+ @ensure(
164
+ lambda result: isinstance(result, ValidationReport)
165
+ or (isinstance(result, tuple) and len(result) == 3 and isinstance(result[0], bool)),
166
+ "Must return ValidationReport or tuple[bool, str | None, Protocol | None]",
167
+ )
168
+ def validate_protocol(protocol_or_path: Protocol | Path) -> ValidationReport | tuple[bool, str | None, Protocol | None]:
169
+ """
170
+ Validate a protocol model or YAML file.
171
+
172
+ Args:
173
+ protocol_or_path: Protocol model or Path to protocol YAML file
174
+
175
+ Returns:
176
+ ValidationReport if model provided, tuple of (is_valid, error_message, parsed_protocol) if path provided
177
+ """
178
+ # If it's already a model, just return success report
179
+ if isinstance(protocol_or_path, Protocol):
180
+ report = ValidationReport()
181
+ # Could add additional validation logic here if needed
182
+ return report
183
+
184
+ # Otherwise treat as path
185
+ path = protocol_or_path
186
+ try:
187
+ with path.open("r") as f:
188
+ data = yaml.safe_load(f)
189
+
190
+ protocol = Protocol(**data)
191
+ return True, None, protocol
192
+
193
+ except FileNotFoundError:
194
+ return False, f"File not found: {path}", None
195
+ except yaml.YAMLError as e:
196
+ return False, f"YAML parsing error: {e}", None
197
+ except ValidationError as e:
198
+ return False, f"Validation error: {e}", None
199
+ except Exception as e:
200
+ return False, f"Unexpected error: {e}", None
@@ -0,0 +1,332 @@
1
+ Metadata-Version: 2.4
2
+ Name: specfact-cli
3
+ Version: 0.4.0
4
+ Summary: SpecFact CLI - Spec→Contract→Sentinel tool for contract-driven development with automated quality gates
5
+ Project-URL: Homepage, https://github.com/nold-ai/specfact-cli
6
+ Project-URL: Repository, https://github.com/nold-ai/specfact-cli.git
7
+ Project-URL: Documentation, https://github.com/nold-ai/specfact-cli#readme
8
+ Project-URL: Issues, https://github.com/nold-ai/specfact-cli/issues
9
+ Author-email: "NOLD AI (Owner: Dominikus Nold)" <hello@noldai.com>
10
+ License: # Sustainable Use License
11
+
12
+ Version 1.0
13
+
14
+ ## Acceptance
15
+
16
+ By using the software, you agree to all of the terms and conditions below.
17
+
18
+ ## Copyright License
19
+
20
+ The licensor grants you a non-exclusive, royalty-free, worldwide, non-sublicensable, non-transferable license to use, copy, distribute, make available, and prepare derivative works of the software, in each case subject to the limitations below.
21
+
22
+ ## Limitations
23
+
24
+ You may use or modify the software only for your own internal business purposes or for non-commercial or personal use. You may distribute the software or provide it to others only if you do so free of charge for non-commercial purposes. You may not alter, remove, or obscure any licensing, copyright, or other notices of the licensor in the software. Any use of the licensor's trademarks is subject to applicable law.
25
+
26
+ ## Patents
27
+
28
+ The licensor grants you a license, under any patent claims the licensor can license, or becomes able to license, to make, have made, use, sell, offer for sale, import and have imported the software, in each case subject to the limitations and conditions in this license. This license does not cover any patent claims that you cause to be infringed by modifications or additions to the software. If you or your company make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company.
29
+
30
+ ## Notices
31
+
32
+ You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these terms. If you modify the software, you must include in any modified copies of the software a prominent notice stating that you have modified the software.
33
+
34
+ ## No Other Rights
35
+
36
+ These terms do not imply any licenses other than those expressly granted in these terms.
37
+
38
+ ## Termination
39
+
40
+ If you use the software in violation of these terms, such use is not licensed, and your license will automatically terminate. If the licensor provides you with a notice of your violation, and you cease all violation of this license no later than 30 days after you receive that notice, your license will be reinstated retroactively. However, if you violate these terms after such reinstatement, any additional violation of these terms will cause your license to terminate automatically and permanently.
41
+
42
+ ## No Liability
43
+
44
+ As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.
45
+
46
+ ## Definitions
47
+
48
+ The "licensor" is Nold AI (Owner: Dominikus Nold).
49
+
50
+ The "software" is the SpecFact CLI software the licensor makes available under these terms, including any portion of it.
51
+
52
+ "You" refers to the individual or entity agreeing to these terms.
53
+
54
+ "Your company" is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all organizations that have control over, are under the control of, or are under common control with that organization. Control means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect.
55
+
56
+ "Your license" is the license granted to you for the software under these terms.
57
+
58
+ "Use" means anything you do with the software requiring your license.
59
+
60
+ "Trademark" means trademarks, service marks, and similar rights.
61
+
62
+ ---
63
+
64
+ Copyright (c) 2025 Nold AI (Owner: Dominikus Nold)
65
+ License-File: LICENSE.md
66
+ Keywords: async,beartype,cli,contract-driven-development,contracts,crosshair,icontract,property-based-testing,quality-gates,spec-first,specfact,state-machine,tdd
67
+ Classifier: Development Status :: 4 - Beta
68
+ Classifier: Intended Audience :: Developers
69
+ Classifier: License :: Other/Proprietary License
70
+ Classifier: Programming Language :: Python :: 3
71
+ Classifier: Programming Language :: Python :: 3.11
72
+ Classifier: Programming Language :: Python :: 3.12
73
+ Classifier: Programming Language :: Python :: 3.13
74
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
75
+ Classifier: Topic :: Software Development :: Quality Assurance
76
+ Classifier: Topic :: Software Development :: Testing
77
+ Requires-Python: >=3.11
78
+ Requires-Dist: beartype>=0.22.4
79
+ Requires-Dist: crosshair-tool>=0.0.97
80
+ Requires-Dist: gitpython>=3.1.45
81
+ Requires-Dist: hypothesis>=6.142.4
82
+ Requires-Dist: icontract>=2.7.1
83
+ Requires-Dist: jinja2>=3.1.6
84
+ Requires-Dist: jsonschema>=4.23.0
85
+ Requires-Dist: networkx>=3.4.2
86
+ Requires-Dist: pydantic>=2.12.3
87
+ Requires-Dist: python-dotenv>=1.2.1
88
+ Requires-Dist: pyyaml>=6.0.3
89
+ Requires-Dist: rich<14.0.0,>=13.0.0
90
+ Requires-Dist: ruamel-yaml>=0.18.16
91
+ Requires-Dist: ruff>=0.14.2
92
+ Requires-Dist: typer>=0.20.0
93
+ Requires-Dist: typing-extensions>=4.15.0
94
+ Provides-Extra: dev
95
+ Requires-Dist: basedpyright>=1.32.1; extra == 'dev'
96
+ Requires-Dist: beartype>=0.22.4; extra == 'dev'
97
+ Requires-Dist: black>=25.9.0; extra == 'dev'
98
+ Requires-Dist: crosshair-tool>=0.0.97; extra == 'dev'
99
+ Requires-Dist: hypothesis>=6.142.4; extra == 'dev'
100
+ Requires-Dist: icontract>=2.7.1; extra == 'dev'
101
+ Requires-Dist: isort>=7.0.0; extra == 'dev'
102
+ Requires-Dist: pip-tools>=7.5.1; extra == 'dev'
103
+ Requires-Dist: pylint>=4.0.2; extra == 'dev'
104
+ Requires-Dist: pytest-asyncio>=1.2.0; extra == 'dev'
105
+ Requires-Dist: pytest-cov>=7.0.0; extra == 'dev'
106
+ Requires-Dist: pytest-mock>=3.15.1; extra == 'dev'
107
+ Requires-Dist: pytest-xdist>=3.8.0; extra == 'dev'
108
+ Requires-Dist: pytest>=8.4.2; extra == 'dev'
109
+ Requires-Dist: ruff>=0.14.2; extra == 'dev'
110
+ Requires-Dist: semgrep>=1.141.1; extra == 'dev'
111
+ Requires-Dist: tomlkit>=0.13.3; extra == 'dev'
112
+ Requires-Dist: types-pyyaml>=6.0.12.20250516; extra == 'dev'
113
+ Provides-Extra: scanning
114
+ Requires-Dist: semgrep>=1.141.1; extra == 'scanning'
115
+ Description-Content-Type: text/markdown
116
+
117
+ # SpecFact CLI
118
+
119
+ > **Stop "vibe coding", start shipping quality code with contracts**
120
+
121
+ [![License](https://img.shields.io/badge/license-Sustainable%20Use-blue.svg)](LICENSE.md)
122
+ [![Python](https://img.shields.io/badge/python-3.11%2B-blue.svg)](https://www.python.org/)
123
+ [![Status](https://img.shields.io/badge/status-beta-orange.svg)](https://github.com/nold-ai/specfact-cli)
124
+
125
+ ---
126
+
127
+ ## What is SpecFact CLI?
128
+
129
+ A command-line tool that helps you write better code by enforcing **contracts** - rules that catch bugs before they reach production.
130
+
131
+ Think of it as a **quality gate** for your development workflow that:
132
+
133
+ - ✅ Catches async bugs automatically
134
+ - ✅ Validates your code matches your specs
135
+ - ✅ Blocks bad code from merging
136
+ - ✅ Works offline, no cloud required
137
+
138
+ **Perfect for:** Teams who want to ship faster without breaking things.
139
+
140
+ ---
141
+
142
+ ## Quick Start
143
+
144
+ ### Install in 10 seconds
145
+
146
+ ```bash
147
+ # Zero-install (just run it)
148
+ uvx specfact --help
149
+
150
+ # Or install with pip
151
+ pip install specfact-cli
152
+ ```
153
+
154
+ ### Your first command (< 60 seconds)
155
+
156
+ ```bash
157
+ # Starting a new project?
158
+ specfact plan init --interactive
159
+
160
+ # Have existing code?
161
+ specfact import from-code --repo . --name my-project
162
+
163
+ # Using GitHub Spec-Kit?
164
+ specfact import from-spec-kit --repo ./my-project --dry-run
165
+ ```
166
+
167
+ That's it! 🎉
168
+
169
+ ---
170
+
171
+ ## See It In Action
172
+
173
+ We ran SpecFact CLI **on itself** to prove it works:
174
+
175
+ - ⚡ Analyzed 32 Python files → Discovered **32 features** and **81 stories** in **3 seconds**
176
+ - 🚫 Set enforcement to "balanced" → **Blocked 2 HIGH violations** (as configured)
177
+ - 📊 Compared manual vs auto-derived plans → Found **24 deviations** in **5 seconds**
178
+
179
+ **Total time**: < 10 seconds | **Total value**: Found real naming inconsistencies and undocumented features
180
+
181
+ 👉 **[Read the complete example](docs/examples/dogfooding-specfact-cli.md)** with actual commands and outputs
182
+
183
+ ---
184
+
185
+ ## What Can You Do?
186
+
187
+ ### 1. 🔄 Import from GitHub Spec-Kit
188
+
189
+ Already using Spec-Kit? **Level up to automated enforcement** in one command:
190
+
191
+ ```bash
192
+ specfact import from-spec-kit --repo ./spec-kit-project --write
193
+ ```
194
+
195
+ **Result**: Your Spec-Kit artifacts become production-ready contracts with automated quality gates.
196
+
197
+ ### 2. 🔍 Analyze Your Existing Code
198
+
199
+ Turn brownfield code into a clean spec:
200
+
201
+ ```bash
202
+ specfact import from-code --repo . --name my-project
203
+ ```
204
+
205
+ **Result**: Auto-generated plan showing what your code actually does
206
+
207
+ ### 3. 📋 Plan New Features
208
+
209
+ Start with a spec, not with code:
210
+
211
+ ```bash
212
+ specfact plan init --interactive
213
+ specfact plan add-feature --key FEATURE-001 --title "User Login"
214
+ ```
215
+
216
+ **Result**: Clear acceptance criteria before writing any code
217
+
218
+ ### 4. 🛡️ Enforce Quality
219
+
220
+ Set rules that actually block bad code:
221
+
222
+ ```bash
223
+ specfact enforce stage --preset balanced
224
+ ```
225
+
226
+ **Modes:**
227
+
228
+ - `minimal` - Just observe, never block
229
+ - `balanced` - Block critical bugs, warn on others
230
+ - `strict` - Block everything suspicious
231
+
232
+ ### 5. ✅ Validate Everything
233
+
234
+ One command to check it all:
235
+
236
+ ```bash
237
+ specfact repro
238
+ ```
239
+
240
+ **Checks:** Contracts, types, async patterns, state machines
241
+
242
+ ---
243
+
244
+ ## Documentation
245
+
246
+ For complete documentation, see **[docs/README.md](docs/README.md)**.
247
+
248
+ **Quick Links:**
249
+
250
+ - 📖 **[Getting Started](docs/getting-started/README.md)** - Installation and first steps
251
+ - 🎯 **[The Journey: From Spec-Kit to SpecFact](docs/guides/speckit-journey.md)** - Level up from interactive authoring to automated enforcement
252
+ - 📋 **[Command Reference](docs/reference/commands.md)** - All commands with examples
253
+ - 🤖 **[IDE Integration](docs/guides/ide-integration.md)** - Set up slash commands in your IDE
254
+ - 💡 **[Use Cases](docs/guides/use-cases.md)** - Real-world scenarios
255
+
256
+ ---
257
+
258
+ ## Installation Options
259
+
260
+ ### 1. uvx (Easiest)
261
+
262
+ No installation needed:
263
+
264
+ ```bash
265
+ uvx specfact plan init
266
+ ```
267
+
268
+ ### 2. pip
269
+
270
+ Install globally:
271
+
272
+ ```bash
273
+ pip install specfact-cli
274
+ specfact --help
275
+ ```
276
+
277
+ ### 3. Docker
278
+
279
+ Run in a container:
280
+
281
+ ```bash
282
+ docker run ghcr.io/nold-ai/specfact-cli:latest --help
283
+ ```
284
+
285
+ ---
286
+
287
+ ## Contributing
288
+
289
+ We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
290
+
291
+ ```bash
292
+ git clone https://github.com/nold-ai/specfact-cli.git
293
+ cd specfact-cli
294
+ pip install -e ".[dev]"
295
+ hatch run contract-test-full
296
+ ```
297
+
298
+ ---
299
+
300
+ ## License
301
+
302
+ **Sustainable Use License** - Free for internal business use
303
+
304
+ ### ✅ You Can
305
+
306
+ - Use it for your business (internal tools, automation)
307
+ - Modify it for your own needs
308
+ - Provide consulting services using SpecFact CLI
309
+
310
+ ### ❌ You Cannot
311
+
312
+ - Sell it as a SaaS product
313
+ - White-label and resell
314
+ - Create competing products
315
+
316
+ For commercial licensing, contact [hello@noldai.com](mailto:hello@noldai.com)
317
+
318
+ **Full license**: [LICENSE.md](LICENSE.md) | **FAQ**: [USAGE-FAQ.md](USAGE-FAQ.md)
319
+
320
+ ---
321
+
322
+ ## Support
323
+
324
+ - 💬 **Questions?** [GitHub Discussions](https://github.com/nold-ai/specfact-cli/discussions)
325
+ - 🐛 **Found a bug?** [GitHub Issues](https://github.com/nold-ai/specfact-cli/issues)
326
+ - 📧 **Need help?** [hello@noldai.com](mailto:hello@noldai.com)
327
+
328
+ ---
329
+
330
+ > **Built with ❤️ by [NOLD AI](https://noldai.com)**
331
+
332
+ Copyright © 2025 Nold AI (Owner: Dominikus Nold)
@@ -0,0 +1,60 @@
1
+ specfact_cli/__init__.py,sha256=9wQNEw1pcLfCzBf1cKZsQQmT6uEnhL0xN-vp9u2OZS4,338
2
+ specfact_cli/cli.py,sha256=52Qr_YyTFCvaeo6tjowFrPIHB1FdZEVE9k3hW7c6Jv8,14624
3
+ specfact_cli/agents/__init__.py,sha256=Iu5QfKJhenQpTrUWizSy5MrSIU6MBMh3tVbuMmLSfw4,661
4
+ specfact_cli/agents/analyze_agent.py,sha256=Rywe5zWBO07efD0Ss5TlFYOhziQnarJqhPSZ3EBABTg,15617
5
+ specfact_cli/agents/base.py,sha256=fFS5R3_7U3hHvlTbXy1cren8Jx_p2ySEgjtY4tj5Jyc,3169
6
+ specfact_cli/agents/plan_agent.py,sha256=S1FdSAzLCTvZEVkASFKAONM6xskQc_HxNWJJQhqzfY8,6856
7
+ specfact_cli/agents/registry.py,sha256=kc7417QydGU9lhFEAKMSpoWwJsuYHFj1Q8cAYN4RItM,5161
8
+ specfact_cli/agents/sync_agent.py,sha256=AWp0k5AGaaKJvhpQ7rss3vCxG78hYRgskNU1LBfNABo,4351
9
+ specfact_cli/analyzers/__init__.py,sha256=qD11XL3t5jKPWasZZUdCxE4X7eQorG_7QutDGd2qr5E,266
10
+ specfact_cli/analyzers/code_analyzer.py,sha256=inKkLEoHFk-w6nQbKjhOHhkfc3QDwzC05DoRWHQxwbc,30723
11
+ specfact_cli/commands/__init__.py,sha256=Hm0ddN9c3UUvXEH1hCj7lYpZEY7NS-8vnKCC0XEngVc,109
12
+ specfact_cli/commands/enforce.py,sha256=A_tKZKaupr_hBdr8m4II-i9wfFnfuURUz3hhoRctOpo,2817
13
+ specfact_cli/commands/import_cmd.py,sha256=BMw6zhgu6OZ-V6qnfTjyBkEtUq0rcD0-lPfycQdIaPk,13867
14
+ specfact_cli/commands/init.py,sha256=OuRgZ9QFcB_mjMqXCeWuVlWYZo2dKNAcQ2smGwVnQUM,4565
15
+ specfact_cli/commands/plan.py,sha256=90xuVZmZ9TrG-icRxdd2eMZfgQEY8DFU3F-5SOs6jR0,41089
16
+ specfact_cli/commands/repro.py,sha256=U1v6gF-ks64lVboPYnbiTEaydXlQFpkuQc9f0cKeM2c,5807
17
+ specfact_cli/commands/sync.py,sha256=7IVabzsYZ06-_7AbvEbUc9BsawWggmpjQ8nP7OLAid0,17190
18
+ specfact_cli/common/__init__.py,sha256=OrOXNw5juhUiQ4XpAw_uw18xFX3ODq49JclQWqyWB7w,777
19
+ specfact_cli/common/logger_setup.py,sha256=rO0x43Gg4pIzdq6x1g4Dawz4CF-3Zl33o4zuSVN3I8Y,26825
20
+ specfact_cli/common/logging_utils.py,sha256=wSDCasch5b4F7B5hRYd3oeWYzmz738eTX-BRP7WD8ko,1549
21
+ specfact_cli/common/text_utils.py,sha256=g9uNKyNeZAI54oPraMJH3KJcAIICpq66dNt2xtYXLfQ,1968
22
+ specfact_cli/common/utils.py,sha256=dB-4_-nqo6sY2-HyeyARDcpoMODA5pVKdIONxbd6PxI,1622
23
+ specfact_cli/comparators/__init__.py,sha256=CIB1FT0OqGqIP-6WPcrpLANdaGb3bFZ6rPNEJdosaao,279
24
+ specfact_cli/comparators/plan_comparator.py,sha256=4Qtuxj6CVqyjegzv8WLvKfZmaQx_HY_C_ym73m70xhc,17496
25
+ specfact_cli/generators/__init__.py,sha256=bYNoCmyaQegcaNSwFT3DAT_e6epqNZHzglrSSICUTEo,460
26
+ specfact_cli/generators/plan_generator.py,sha256=gjbYEQY5UFc71tXwl56KJSq1p_CkgmArbagCIellokQ,3878
27
+ specfact_cli/generators/protocol_generator.py,sha256=yOSmogp-bUwJ45AhqfKzAbKiJ9VzQsBnXlS8FloTbYo,4343
28
+ specfact_cli/generators/report_generator.py,sha256=ziS2J7I14LDl8HgscoZc7d2I1DFd92zQ-Z71kzReTZs,8098
29
+ specfact_cli/generators/workflow_generator.py,sha256=LUaJzDW1-ND83K9dfE3yHxrH3_R1bwvUhL7f8wzycmw,4237
30
+ specfact_cli/importers/__init__.py,sha256=ZmKsoLYCZwIpQUgssnPc99S0tEKLQ8BSXZDoqPcqaAQ,255
31
+ specfact_cli/importers/speckit_converter.py,sha256=H4QVnOyAQ2hrgLv-a-jHy7KmzoNeH4S7mxxr_TsfR9k,32098
32
+ specfact_cli/importers/speckit_scanner.py,sha256=xSy8xmHtgvEKndCc5nNBRNfJwvnfDG3jOjBUFmjczGo,31205
33
+ specfact_cli/models/__init__.py,sha256=C3AITr0RWMBTCC8sEKFyG6hIE-8SCH3xA5PP4l_gXyA,891
34
+ specfact_cli/models/deviation.py,sha256=C3JRu1CZqv1UIeMWhT2Rpk5xM8MW4RUGsKcd0AsE34w,3826
35
+ specfact_cli/models/enforcement.py,sha256=MFsxoleu9n2U1I7ng6GCIxkyj0M0gJ1v3dFi94sljDo,5720
36
+ specfact_cli/models/plan.py,sha256=Fr_w49R6zM-E7rsEke1uMj3amwF_luJbm_Xk9MFi7V0,4413
37
+ specfact_cli/models/protocol.py,sha256=s9SpUIH9qf0W0Io_wWEYjERTdf1VOowq6rj20I3p9To,900
38
+ specfact_cli/modes/__init__.py,sha256=4SoF2nFBXQscZiQx7WtxN3d7J1W0yCSVGmkPZ8DZRNk,445
39
+ specfact_cli/modes/detector.py,sha256=qPs_KvlCXMQCnWP0vO6GGnmbgNFrrewYWlx5ffN9JJ4,3468
40
+ specfact_cli/modes/router.py,sha256=U9g4YhntRx7Wg6e59K1uMQt682YzzHdUeNHqEIfIUFU,5160
41
+ specfact_cli/sync/__init__.py,sha256=qd5KiaETOTzcHE9iUHkm11YfEUXTm4VeY1iwnnJEYzI,396
42
+ specfact_cli/sync/repository_sync.py,sha256=4jq0uUoWuHqFNd6g1OkVCUdTJuK9-WcsV8c8k2qFQkk,10007
43
+ specfact_cli/sync/speckit_sync.py,sha256=l_V7rYe7aLG6v3DPOJhPcc_1vx-jLqXAYsKZNLMbOzs,13612
44
+ specfact_cli/utils/__init__.py,sha256=7r71WkiTVVloVNhMi6SdBWkWJ5pytYir2-Hh_FH-M7s,1357
45
+ specfact_cli/utils/console.py,sha256=7ifgATHPGWEqzlvBkHIre9mbMjSaNX7KFPFs9_8W3J0,2254
46
+ specfact_cli/utils/feature_keys.py,sha256=Co2A6gFdhaYZhNOGYGKbHzLn6Rp5X-ywT5GuWqwHfxY,6651
47
+ specfact_cli/utils/git.py,sha256=qHmW50OaXccPCeCthMJZODHx5LibIJ1MuOOt95QS8Ao,7538
48
+ specfact_cli/utils/ide_setup.py,sha256=fjYiumkzpgy9ayc6OKhjgz4fbgg2p-qjyh7DDw9NQrM,12364
49
+ specfact_cli/utils/prompts.py,sha256=fbBrp8DhZFIGtX-puPbd05PeuyYwkMxh-dN_yMTVx1k,5761
50
+ specfact_cli/utils/structure.py,sha256=bbl-I2ozYYqRFuoGNMp-3gf6BIsquksF_Mlo11ky9Tw,18398
51
+ specfact_cli/utils/yaml_utils.py,sha256=xK2uvCVUssaHnB4BLYq9vJUarSuIIxANftlq8yrltkA,5719
52
+ specfact_cli/validators/__init__.py,sha256=L8AmArgcT0_vGUnFez40SWOtr0SN4qvGmzDZ5N8ZrW4,499
53
+ specfact_cli/validators/fsm.py,sha256=wwDAugwuBPaNRNB-g9-Y6Zwc2MwndpXdrPdgaRYVUx4,9995
54
+ specfact_cli/validators/repro_checker.py,sha256=YphkDju82um0JZRsGoO6gPVc0kKRzD3Py93K1YHjhuU,10713
55
+ specfact_cli/validators/schema.py,sha256=hLDcTE6lnNBbni1UBQdluvDLZNSxX7Ek7dhXvIvAXZc,6885
56
+ specfact_cli-0.4.0.dist-info/METADATA,sha256=CnibY3boIOHjR1v_UNsKELxt0hR2QyV5au54C3XF4Ws,12026
57
+ specfact_cli-0.4.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
58
+ specfact_cli-0.4.0.dist-info/entry_points.txt,sha256=NvpypgoclYhHooSFA3rOeoqoyo9hkM547yMbujJbjOk,55
59
+ specfact_cli-0.4.0.dist-info/licenses/LICENSE.md,sha256=MTjC0xPZjRB_MQt-_FD826DwppdV8uW4qFTm9t6BgnM,3669
60
+ specfact_cli-0.4.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ specfact = specfact_cli.cli:cli_main
@@ -0,0 +1,55 @@
1
+ # Sustainable Use License
2
+
3
+ Version 1.0
4
+
5
+ ## Acceptance
6
+
7
+ By using the software, you agree to all of the terms and conditions below.
8
+
9
+ ## Copyright License
10
+
11
+ The licensor grants you a non-exclusive, royalty-free, worldwide, non-sublicensable, non-transferable license to use, copy, distribute, make available, and prepare derivative works of the software, in each case subject to the limitations below.
12
+
13
+ ## Limitations
14
+
15
+ You may use or modify the software only for your own internal business purposes or for non-commercial or personal use. You may distribute the software or provide it to others only if you do so free of charge for non-commercial purposes. You may not alter, remove, or obscure any licensing, copyright, or other notices of the licensor in the software. Any use of the licensor's trademarks is subject to applicable law.
16
+
17
+ ## Patents
18
+
19
+ The licensor grants you a license, under any patent claims the licensor can license, or becomes able to license, to make, have made, use, sell, offer for sale, import and have imported the software, in each case subject to the limitations and conditions in this license. This license does not cover any patent claims that you cause to be infringed by modifications or additions to the software. If you or your company make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company.
20
+
21
+ ## Notices
22
+
23
+ You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these terms. If you modify the software, you must include in any modified copies of the software a prominent notice stating that you have modified the software.
24
+
25
+ ## No Other Rights
26
+
27
+ These terms do not imply any licenses other than those expressly granted in these terms.
28
+
29
+ ## Termination
30
+
31
+ If you use the software in violation of these terms, such use is not licensed, and your license will automatically terminate. If the licensor provides you with a notice of your violation, and you cease all violation of this license no later than 30 days after you receive that notice, your license will be reinstated retroactively. However, if you violate these terms after such reinstatement, any additional violation of these terms will cause your license to terminate automatically and permanently.
32
+
33
+ ## No Liability
34
+
35
+ As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.
36
+
37
+ ## Definitions
38
+
39
+ The "licensor" is Nold AI (Owner: Dominikus Nold).
40
+
41
+ The "software" is the SpecFact CLI software the licensor makes available under these terms, including any portion of it.
42
+
43
+ "You" refers to the individual or entity agreeing to these terms.
44
+
45
+ "Your company" is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all organizations that have control over, are under the control of, or are under common control with that organization. Control means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect.
46
+
47
+ "Your license" is the license granted to you for the software under these terms.
48
+
49
+ "Use" means anything you do with the software requiring your license.
50
+
51
+ "Trademark" means trademarks, service marks, and similar rights.
52
+
53
+ ---
54
+
55
+ Copyright (c) 2025 Nold AI (Owner: Dominikus Nold)