ai-sdlc-framework 0.1.0__tar.gz

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 (159) hide show
  1. ai_sdlc_framework-0.1.0/.gitignore +51 -0
  2. ai_sdlc_framework-0.1.0/PKG-INFO +86 -0
  3. ai_sdlc_framework-0.1.0/README.md +58 -0
  4. ai_sdlc_framework-0.1.0/pyproject.toml +62 -0
  5. ai_sdlc_framework-0.1.0/src/ai_sdlc/__init__.py +40 -0
  6. ai_sdlc_framework-0.1.0/src/ai_sdlc/_utils/__init__.py +0 -0
  7. ai_sdlc_framework-0.1.0/src/ai_sdlc/_utils/duration.py +42 -0
  8. ai_sdlc_framework-0.1.0/src/ai_sdlc/adapters/__init__.py +1 -0
  9. ai_sdlc_framework-0.1.0/src/ai_sdlc/adapters/event_bus.py +39 -0
  10. ai_sdlc_framework-0.1.0/src/ai_sdlc/adapters/git_resolver.py +111 -0
  11. ai_sdlc_framework-0.1.0/src/ai_sdlc/adapters/github.py +187 -0
  12. ai_sdlc_framework-0.1.0/src/ai_sdlc/adapters/interfaces.py +353 -0
  13. ai_sdlc_framework-0.1.0/src/ai_sdlc/adapters/linear.py +87 -0
  14. ai_sdlc_framework-0.1.0/src/ai_sdlc/adapters/registry.py +115 -0
  15. ai_sdlc_framework-0.1.0/src/ai_sdlc/adapters/resolve_secret.py +21 -0
  16. ai_sdlc_framework-0.1.0/src/ai_sdlc/adapters/scanner.py +84 -0
  17. ai_sdlc_framework-0.1.0/src/ai_sdlc/adapters/stubs/__init__.py +1 -0
  18. ai_sdlc_framework-0.1.0/src/ai_sdlc/adapters/stubs/bitbucket.py +80 -0
  19. ai_sdlc_framework-0.1.0/src/ai_sdlc/adapters/stubs/code_analysis.py +57 -0
  20. ai_sdlc_framework-0.1.0/src/ai_sdlc/adapters/stubs/deployment_target.py +75 -0
  21. ai_sdlc_framework-0.1.0/src/ai_sdlc/adapters/stubs/gitlab.py +135 -0
  22. ai_sdlc_framework-0.1.0/src/ai_sdlc/adapters/stubs/jira.py +109 -0
  23. ai_sdlc_framework-0.1.0/src/ai_sdlc/adapters/stubs/messenger.py +51 -0
  24. ai_sdlc_framework-0.1.0/src/ai_sdlc/adapters/stubs/semgrep.py +73 -0
  25. ai_sdlc_framework-0.1.0/src/ai_sdlc/adapters/stubs/sonarqube.py +61 -0
  26. ai_sdlc_framework-0.1.0/src/ai_sdlc/adapters/webhook_bridge.py +62 -0
  27. ai_sdlc_framework-0.1.0/src/ai_sdlc/agents/__init__.py +11 -0
  28. ai_sdlc_framework-0.1.0/src/ai_sdlc/agents/discovery.py +161 -0
  29. ai_sdlc_framework-0.1.0/src/ai_sdlc/agents/executor.py +350 -0
  30. ai_sdlc_framework-0.1.0/src/ai_sdlc/agents/memory/__init__.py +1 -0
  31. ai_sdlc_framework-0.1.0/src/ai_sdlc/agents/memory/file_backend.py +160 -0
  32. ai_sdlc_framework-0.1.0/src/ai_sdlc/agents/memory/in_memory.py +171 -0
  33. ai_sdlc_framework-0.1.0/src/ai_sdlc/agents/memory/types.py +86 -0
  34. ai_sdlc_framework-0.1.0/src/ai_sdlc/agents/orchestration.py +101 -0
  35. ai_sdlc_framework-0.1.0/src/ai_sdlc/agents/runner.py +166 -0
  36. ai_sdlc_framework-0.1.0/src/ai_sdlc/agents/runner_registry.py +95 -0
  37. ai_sdlc_framework-0.1.0/src/ai_sdlc/audit/__init__.py +1 -0
  38. ai_sdlc_framework-0.1.0/src/ai_sdlc/audit/file_sink.py +101 -0
  39. ai_sdlc_framework-0.1.0/src/ai_sdlc/audit/logger.py +131 -0
  40. ai_sdlc_framework-0.1.0/src/ai_sdlc/audit/memory_sink.py +55 -0
  41. ai_sdlc_framework-0.1.0/src/ai_sdlc/audit/types.py +60 -0
  42. ai_sdlc_framework-0.1.0/src/ai_sdlc/builders/__init__.py +25 -0
  43. ai_sdlc_framework-0.1.0/src/ai_sdlc/builders/builders.py +418 -0
  44. ai_sdlc_framework-0.1.0/src/ai_sdlc/builders/distribution.py +95 -0
  45. ai_sdlc_framework-0.1.0/src/ai_sdlc/compliance/__init__.py +1 -0
  46. ai_sdlc_framework-0.1.0/src/ai_sdlc/compliance/checker.py +59 -0
  47. ai_sdlc_framework-0.1.0/src/ai_sdlc/compliance/mappings.py +309 -0
  48. ai_sdlc_framework-0.1.0/src/ai_sdlc/core/__init__.py +1 -0
  49. ai_sdlc_framework-0.1.0/src/ai_sdlc/core/compare.py +38 -0
  50. ai_sdlc_framework-0.1.0/src/ai_sdlc/core/provenance.py +112 -0
  51. ai_sdlc_framework-0.1.0/src/ai_sdlc/core/types.py +548 -0
  52. ai_sdlc_framework-0.1.0/src/ai_sdlc/core/validation.py +115 -0
  53. ai_sdlc_framework-0.1.0/src/ai_sdlc/metrics/__init__.py +1 -0
  54. ai_sdlc_framework-0.1.0/src/ai_sdlc/metrics/instrumentation.py +161 -0
  55. ai_sdlc_framework-0.1.0/src/ai_sdlc/metrics/store.py +103 -0
  56. ai_sdlc_framework-0.1.0/src/ai_sdlc/metrics/types.py +168 -0
  57. ai_sdlc_framework-0.1.0/src/ai_sdlc/policy/__init__.py +3 -0
  58. ai_sdlc_framework-0.1.0/src/ai_sdlc/policy/abac.py +95 -0
  59. ai_sdlc_framework-0.1.0/src/ai_sdlc/policy/admission.py +136 -0
  60. ai_sdlc_framework-0.1.0/src/ai_sdlc/policy/authentication.py +58 -0
  61. ai_sdlc_framework-0.1.0/src/ai_sdlc/policy/authorization.py +171 -0
  62. ai_sdlc_framework-0.1.0/src/ai_sdlc/policy/autonomy.py +145 -0
  63. ai_sdlc_framework-0.1.0/src/ai_sdlc/policy/cel_evaluator.py +335 -0
  64. ai_sdlc_framework-0.1.0/src/ai_sdlc/policy/complexity.py +142 -0
  65. ai_sdlc_framework-0.1.0/src/ai_sdlc/policy/enforcement.py +196 -0
  66. ai_sdlc_framework-0.1.0/src/ai_sdlc/policy/evaluator.py +156 -0
  67. ai_sdlc_framework-0.1.0/src/ai_sdlc/policy/expression.py +187 -0
  68. ai_sdlc_framework-0.1.0/src/ai_sdlc/policy/llm_evaluator.py +104 -0
  69. ai_sdlc_framework-0.1.0/src/ai_sdlc/policy/mutating_gate.py +98 -0
  70. ai_sdlc_framework-0.1.0/src/ai_sdlc/policy/rego_evaluator.py +261 -0
  71. ai_sdlc_framework-0.1.0/src/ai_sdlc/py.typed +0 -0
  72. ai_sdlc_framework-0.1.0/src/ai_sdlc/reconciler/__init__.py +1 -0
  73. ai_sdlc_framework-0.1.0/src/ai_sdlc/reconciler/autonomy_reconciler.py +98 -0
  74. ai_sdlc_framework-0.1.0/src/ai_sdlc/reconciler/diff.py +71 -0
  75. ai_sdlc_framework-0.1.0/src/ai_sdlc/reconciler/gate_reconciler.py +56 -0
  76. ai_sdlc_framework-0.1.0/src/ai_sdlc/reconciler/loop.py +167 -0
  77. ai_sdlc_framework-0.1.0/src/ai_sdlc/reconciler/pipeline_reconciler.py +234 -0
  78. ai_sdlc_framework-0.1.0/src/ai_sdlc/reconciler/types.py +48 -0
  79. ai_sdlc_framework-0.1.0/src/ai_sdlc/security/__init__.py +1 -0
  80. ai_sdlc_framework-0.1.0/src/ai_sdlc/security/approval_tier.py +60 -0
  81. ai_sdlc_framework-0.1.0/src/ai_sdlc/security/docker_sandbox.py +82 -0
  82. ai_sdlc_framework-0.1.0/src/ai_sdlc/security/env_secret_store.py +44 -0
  83. ai_sdlc_framework-0.1.0/src/ai_sdlc/security/github_jit.py +124 -0
  84. ai_sdlc_framework-0.1.0/src/ai_sdlc/security/github_sandbox.py +104 -0
  85. ai_sdlc_framework-0.1.0/src/ai_sdlc/security/interfaces.py +91 -0
  86. ai_sdlc_framework-0.1.0/src/ai_sdlc/security/stubs.py +178 -0
  87. ai_sdlc_framework-0.1.0/src/ai_sdlc/telemetry/__init__.py +1 -0
  88. ai_sdlc_framework-0.1.0/src/ai_sdlc/telemetry/instrumentation.py +51 -0
  89. ai_sdlc_framework-0.1.0/src/ai_sdlc/telemetry/logging.py +147 -0
  90. ai_sdlc_framework-0.1.0/src/ai_sdlc/telemetry/semantic_conventions.py +57 -0
  91. ai_sdlc_framework-0.1.0/tests/adapters/__init__.py +0 -0
  92. ai_sdlc_framework-0.1.0/tests/adapters/test_event_bus.py +41 -0
  93. ai_sdlc_framework-0.1.0/tests/adapters/test_git_resolver.py +82 -0
  94. ai_sdlc_framework-0.1.0/tests/adapters/test_github_adapter.py +46 -0
  95. ai_sdlc_framework-0.1.0/tests/adapters/test_linear_adapter.py +20 -0
  96. ai_sdlc_framework-0.1.0/tests/adapters/test_registry.py +103 -0
  97. ai_sdlc_framework-0.1.0/tests/adapters/test_resolve_secret.py +21 -0
  98. ai_sdlc_framework-0.1.0/tests/adapters/test_scanner.py +75 -0
  99. ai_sdlc_framework-0.1.0/tests/adapters/test_stubs.py +181 -0
  100. ai_sdlc_framework-0.1.0/tests/adapters/test_webhook_bridge.py +47 -0
  101. ai_sdlc_framework-0.1.0/tests/agents/__init__.py +0 -0
  102. ai_sdlc_framework-0.1.0/tests/agents/memory/__init__.py +0 -0
  103. ai_sdlc_framework-0.1.0/tests/agents/memory/test_file_backend.py +96 -0
  104. ai_sdlc_framework-0.1.0/tests/agents/memory/test_in_memory.py +94 -0
  105. ai_sdlc_framework-0.1.0/tests/agents/test_discovery.py +145 -0
  106. ai_sdlc_framework-0.1.0/tests/agents/test_executor.py +260 -0
  107. ai_sdlc_framework-0.1.0/tests/agents/test_orchestration.py +90 -0
  108. ai_sdlc_framework-0.1.0/tests/agents/test_runner.py +149 -0
  109. ai_sdlc_framework-0.1.0/tests/agents/test_runner_registry.py +91 -0
  110. ai_sdlc_framework-0.1.0/tests/audit/__init__.py +0 -0
  111. ai_sdlc_framework-0.1.0/tests/audit/test_logger.py +55 -0
  112. ai_sdlc_framework-0.1.0/tests/audit/test_memory_sink.py +16 -0
  113. ai_sdlc_framework-0.1.0/tests/builders/__init__.py +0 -0
  114. ai_sdlc_framework-0.1.0/tests/builders/test_builders.py +141 -0
  115. ai_sdlc_framework-0.1.0/tests/builders/test_distribution.py +103 -0
  116. ai_sdlc_framework-0.1.0/tests/compliance/__init__.py +0 -0
  117. ai_sdlc_framework-0.1.0/tests/compliance/test_checker.py +35 -0
  118. ai_sdlc_framework-0.1.0/tests/core/__init__.py +0 -0
  119. ai_sdlc_framework-0.1.0/tests/core/test_compare.py +43 -0
  120. ai_sdlc_framework-0.1.0/tests/core/test_duration.py +47 -0
  121. ai_sdlc_framework-0.1.0/tests/core/test_provenance.py +85 -0
  122. ai_sdlc_framework-0.1.0/tests/core/test_types.py +142 -0
  123. ai_sdlc_framework-0.1.0/tests/core/test_validation.py +54 -0
  124. ai_sdlc_framework-0.1.0/tests/metrics/__init__.py +0 -0
  125. ai_sdlc_framework-0.1.0/tests/metrics/test_instrumentation.py +125 -0
  126. ai_sdlc_framework-0.1.0/tests/metrics/test_store.py +74 -0
  127. ai_sdlc_framework-0.1.0/tests/policy/__init__.py +0 -0
  128. ai_sdlc_framework-0.1.0/tests/policy/test_abac.py +90 -0
  129. ai_sdlc_framework-0.1.0/tests/policy/test_admission.py +145 -0
  130. ai_sdlc_framework-0.1.0/tests/policy/test_authentication.py +46 -0
  131. ai_sdlc_framework-0.1.0/tests/policy/test_authorization.py +130 -0
  132. ai_sdlc_framework-0.1.0/tests/policy/test_autonomy.py +201 -0
  133. ai_sdlc_framework-0.1.0/tests/policy/test_cel_evaluator.py +106 -0
  134. ai_sdlc_framework-0.1.0/tests/policy/test_complexity.py +61 -0
  135. ai_sdlc_framework-0.1.0/tests/policy/test_enforcement.py +204 -0
  136. ai_sdlc_framework-0.1.0/tests/policy/test_evaluator.py +210 -0
  137. ai_sdlc_framework-0.1.0/tests/policy/test_expression.py +72 -0
  138. ai_sdlc_framework-0.1.0/tests/policy/test_llm_evaluator.py +72 -0
  139. ai_sdlc_framework-0.1.0/tests/policy/test_mutating_gate.py +65 -0
  140. ai_sdlc_framework-0.1.0/tests/policy/test_rego_evaluator.py +80 -0
  141. ai_sdlc_framework-0.1.0/tests/reconciler/__init__.py +0 -0
  142. ai_sdlc_framework-0.1.0/tests/reconciler/test_autonomy_reconciler.py +166 -0
  143. ai_sdlc_framework-0.1.0/tests/reconciler/test_diff.py +88 -0
  144. ai_sdlc_framework-0.1.0/tests/reconciler/test_gate_reconciler.py +77 -0
  145. ai_sdlc_framework-0.1.0/tests/reconciler/test_loop.py +115 -0
  146. ai_sdlc_framework-0.1.0/tests/reconciler/test_pipeline_reconciler.py +167 -0
  147. ai_sdlc_framework-0.1.0/tests/reconciler/test_types.py +39 -0
  148. ai_sdlc_framework-0.1.0/tests/security/__init__.py +0 -0
  149. ai_sdlc_framework-0.1.0/tests/security/test_approval_tier.py +47 -0
  150. ai_sdlc_framework-0.1.0/tests/security/test_docker_sandbox.py +51 -0
  151. ai_sdlc_framework-0.1.0/tests/security/test_env_secret_store.py +28 -0
  152. ai_sdlc_framework-0.1.0/tests/security/test_github_jit.py +72 -0
  153. ai_sdlc_framework-0.1.0/tests/security/test_github_sandbox.py +58 -0
  154. ai_sdlc_framework-0.1.0/tests/security/test_stubs.py +66 -0
  155. ai_sdlc_framework-0.1.0/tests/telemetry/__init__.py +0 -0
  156. ai_sdlc_framework-0.1.0/tests/telemetry/test_logging.py +39 -0
  157. ai_sdlc_framework-0.1.0/tests/telemetry/test_semantic_conventions.py +24 -0
  158. ai_sdlc_framework-0.1.0/tests/test_conformance.py +319 -0
  159. ai_sdlc_framework-0.1.0/tests/test_smoke.py +7 -0
@@ -0,0 +1,51 @@
1
+ # Dependencies
2
+ node_modules/
3
+
4
+ # Build output
5
+ dist/
6
+ *.tsbuildinfo
7
+ .next/
8
+
9
+ # Coverage
10
+ coverage/
11
+ .nyc_output/
12
+
13
+ # Environment
14
+ .env
15
+ .env.*
16
+ !.env.example
17
+
18
+ # IDE
19
+ .idea/
20
+ .vscode/
21
+ *.swp
22
+ *.swo
23
+ *~
24
+
25
+ # OS
26
+ .DS_Store
27
+ Thumbs.db
28
+
29
+ # Logs
30
+ *.log
31
+ npm-debug.log*
32
+ pnpm-debug.log*
33
+
34
+ # AI-SDLC runtime artifacts
35
+ .ai-sdlc/audit.jsonl
36
+
37
+ # Package manager
38
+ .pnpm-store/
39
+
40
+ # Python
41
+ __pycache__/
42
+ *.py[cod]
43
+ *.egg-info/
44
+ *.egg
45
+ *.whl
46
+ .venv/
47
+ .mypy_cache/
48
+ .pytest_cache/
49
+ .ruff_cache/
50
+ build/
51
+ *.pyz
@@ -0,0 +1,86 @@
1
+ Metadata-Version: 2.4
2
+ Name: ai-sdlc-framework
3
+ Version: 0.1.0
4
+ Summary: Python SDK for the AI-SDLC Framework
5
+ Project-URL: Homepage, https://github.com/ai-sdlc-framework/ai-sdlc
6
+ Project-URL: Repository, https://github.com/ai-sdlc-framework/ai-sdlc/tree/main/sdk-python
7
+ Project-URL: Issues, https://github.com/ai-sdlc-framework/ai-sdlc/issues
8
+ Author: AI-SDLC Framework
9
+ License-Expression: Apache-2.0
10
+ Keywords: agents,ai,pipelines,quality-gates,sdlc
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Typing :: Typed
17
+ Requires-Python: >=3.11
18
+ Requires-Dist: jsonschema>=4.20
19
+ Requires-Dist: opentelemetry-api>=1.20
20
+ Requires-Dist: pydantic<3,>=2.0
21
+ Requires-Dist: pyyaml>=6.0
22
+ Provides-Extra: dev
23
+ Requires-Dist: mypy>=1.8; extra == 'dev'
24
+ Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
25
+ Requires-Dist: pytest>=7; extra == 'dev'
26
+ Requires-Dist: ruff>=0.4; extra == 'dev'
27
+ Description-Content-Type: text/markdown
28
+
29
+ # ai-sdlc
30
+
31
+ Python SDK for the [AI-SDLC Framework](https://ai-sdlc.io) — a Kubernetes-style declarative framework for governing AI agents in software development lifecycles.
32
+
33
+ ## Installation
34
+
35
+ ```bash
36
+ pip install ai-sdlc
37
+ ```
38
+
39
+ ## Quick Start
40
+
41
+ ```python
42
+ from ai_sdlc.core.types import Pipeline, API_VERSION
43
+ from ai_sdlc.core.validation import validate_resource
44
+ from ai_sdlc.builders.builders import PipelineBuilder
45
+
46
+ # Build a pipeline using the fluent API
47
+ pipeline = (
48
+ PipelineBuilder("my-pipeline")
49
+ .add_trigger({"event": "issue.assigned"})
50
+ .add_provider("github", {"type": "github"})
51
+ .add_stage({"name": "implement"})
52
+ .build()
53
+ )
54
+
55
+ # Validate against JSON Schema
56
+ result = validate_resource(pipeline.model_dump(by_alias=True))
57
+ assert result.valid
58
+ ```
59
+
60
+ ## Modules
61
+
62
+ | Module | Description |
63
+ |--------|------------|
64
+ | `core` | Pydantic models for all 5 resource types, JSON Schema validation, comparison, provenance |
65
+ | `builders` | Fluent builder classes for resource construction |
66
+ | `policy` | Enforcement engine, autonomy evaluation, complexity routing, authorization |
67
+ | `adapters` | Interface Protocols, adapter registry, community stubs |
68
+ | `reconciler` | asyncio-based reconciliation loop with domain reconcilers |
69
+ | `agents` | Orchestration patterns, executor, multi-tier memory |
70
+ | `security` | Sandbox, JIT credentials, kill switch, approval workflow Protocols |
71
+ | `telemetry` | OpenTelemetry semantic conventions, structured logging |
72
+ | `compliance` | Regulatory framework mappings (EU AI Act, NIST AI RMF, ISO 42001, etc.) |
73
+ | `metrics` | Metric store, standard metric definitions |
74
+ | `audit` | JSONL audit logging with tamper-evident hashing |
75
+
76
+ ## Requirements
77
+
78
+ - Python 3.11+
79
+ - pydantic >= 2.0
80
+ - jsonschema >= 4.20
81
+ - PyYAML >= 6.0
82
+ - opentelemetry-api >= 1.20
83
+
84
+ ## License
85
+
86
+ Apache-2.0
@@ -0,0 +1,58 @@
1
+ # ai-sdlc
2
+
3
+ Python SDK for the [AI-SDLC Framework](https://ai-sdlc.io) — a Kubernetes-style declarative framework for governing AI agents in software development lifecycles.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install ai-sdlc
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```python
14
+ from ai_sdlc.core.types import Pipeline, API_VERSION
15
+ from ai_sdlc.core.validation import validate_resource
16
+ from ai_sdlc.builders.builders import PipelineBuilder
17
+
18
+ # Build a pipeline using the fluent API
19
+ pipeline = (
20
+ PipelineBuilder("my-pipeline")
21
+ .add_trigger({"event": "issue.assigned"})
22
+ .add_provider("github", {"type": "github"})
23
+ .add_stage({"name": "implement"})
24
+ .build()
25
+ )
26
+
27
+ # Validate against JSON Schema
28
+ result = validate_resource(pipeline.model_dump(by_alias=True))
29
+ assert result.valid
30
+ ```
31
+
32
+ ## Modules
33
+
34
+ | Module | Description |
35
+ |--------|------------|
36
+ | `core` | Pydantic models for all 5 resource types, JSON Schema validation, comparison, provenance |
37
+ | `builders` | Fluent builder classes for resource construction |
38
+ | `policy` | Enforcement engine, autonomy evaluation, complexity routing, authorization |
39
+ | `adapters` | Interface Protocols, adapter registry, community stubs |
40
+ | `reconciler` | asyncio-based reconciliation loop with domain reconcilers |
41
+ | `agents` | Orchestration patterns, executor, multi-tier memory |
42
+ | `security` | Sandbox, JIT credentials, kill switch, approval workflow Protocols |
43
+ | `telemetry` | OpenTelemetry semantic conventions, structured logging |
44
+ | `compliance` | Regulatory framework mappings (EU AI Act, NIST AI RMF, ISO 42001, etc.) |
45
+ | `metrics` | Metric store, standard metric definitions |
46
+ | `audit` | JSONL audit logging with tamper-evident hashing |
47
+
48
+ ## Requirements
49
+
50
+ - Python 3.11+
51
+ - pydantic >= 2.0
52
+ - jsonschema >= 4.20
53
+ - PyYAML >= 6.0
54
+ - opentelemetry-api >= 1.20
55
+
56
+ ## License
57
+
58
+ Apache-2.0
@@ -0,0 +1,62 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "ai-sdlc-framework"
7
+ version = "0.1.0"
8
+ description = "Python SDK for the AI-SDLC Framework"
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ license = "Apache-2.0"
12
+ authors = [
13
+ { name = "AI-SDLC Framework" },
14
+ ]
15
+ keywords = ["ai", "sdlc", "agents", "quality-gates", "pipelines"]
16
+ classifiers = [
17
+ "Development Status :: 3 - Alpha",
18
+ "Intended Audience :: Developers",
19
+ "Programming Language :: Python :: 3.11",
20
+ "Programming Language :: Python :: 3.12",
21
+ "Programming Language :: Python :: 3.13",
22
+ "Typing :: Typed",
23
+ ]
24
+ dependencies = [
25
+ "pydantic>=2.0,<3",
26
+ "jsonschema>=4.20",
27
+ "PyYAML>=6.0",
28
+ "opentelemetry-api>=1.20",
29
+ ]
30
+
31
+ [project.urls]
32
+ Homepage = "https://github.com/ai-sdlc-framework/ai-sdlc"
33
+ Repository = "https://github.com/ai-sdlc-framework/ai-sdlc/tree/main/sdk-python"
34
+ Issues = "https://github.com/ai-sdlc-framework/ai-sdlc/issues"
35
+
36
+ [project.optional-dependencies]
37
+ dev = [
38
+ "pytest>=7",
39
+ "pytest-asyncio>=0.21",
40
+ "mypy>=1.8",
41
+ "ruff>=0.4",
42
+ ]
43
+
44
+ [tool.hatch.build.targets.wheel]
45
+ packages = ["src/ai_sdlc"]
46
+
47
+ [tool.pytest.ini_options]
48
+ testpaths = ["tests"]
49
+ asyncio_mode = "auto"
50
+
51
+ [tool.mypy]
52
+ strict = true
53
+ python_version = "3.11"
54
+ plugins = ["pydantic.mypy"]
55
+
56
+ [tool.ruff]
57
+ target-version = "py311"
58
+ line-length = 99
59
+
60
+ [tool.ruff.lint]
61
+ select = ["E", "F", "I", "N", "W", "UP", "B", "SIM", "TC"]
62
+ ignore = ["SIM118"]
@@ -0,0 +1,40 @@
1
+ """AI-SDLC Python SDK — native implementation of the AI-SDLC Framework."""
2
+
3
+ __version__ = "0.1.0"
4
+
5
+ from ai_sdlc.builders.builders import (
6
+ AdapterBindingBuilder,
7
+ AgentRoleBuilder,
8
+ AutonomyPolicyBuilder,
9
+ PipelineBuilder,
10
+ QualityGateBuilder,
11
+ )
12
+ from ai_sdlc.core.types import (
13
+ API_VERSION,
14
+ AdapterBinding,
15
+ AgentRole,
16
+ AnyResource,
17
+ AutonomyPolicy,
18
+ Pipeline,
19
+ QualityGate,
20
+ ResourceKind,
21
+ )
22
+ from ai_sdlc.core.validation import validate_resource
23
+
24
+ __all__ = [
25
+ "__version__",
26
+ "API_VERSION",
27
+ "AdapterBinding",
28
+ "AgentRole",
29
+ "AnyResource",
30
+ "AutonomyPolicy",
31
+ "Pipeline",
32
+ "QualityGate",
33
+ "ResourceKind",
34
+ "validate_resource",
35
+ "AdapterBindingBuilder",
36
+ "AgentRoleBuilder",
37
+ "AutonomyPolicyBuilder",
38
+ "PipelineBuilder",
39
+ "QualityGateBuilder",
40
+ ]
File without changes
@@ -0,0 +1,42 @@
1
+ """Parse duration strings in shorthand (60s, 5m, 2h, 1d, 2w) or ISO 8601 format."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+
7
+ _SHORTHAND_RE = re.compile(r"^(\d+)([smhdw])$")
8
+ _ISO_RE = re.compile(r"^PT(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?$")
9
+
10
+ _SHORTHAND_MULTIPLIERS: dict[str, int] = {
11
+ "s": 1_000,
12
+ "m": 60_000,
13
+ "h": 3_600_000,
14
+ "d": 86_400_000,
15
+ "w": 604_800_000,
16
+ }
17
+
18
+
19
+ def parse_duration(value: str) -> int:
20
+ """Parse a duration string and return milliseconds.
21
+
22
+ Supports:
23
+ - Shorthand: ``60s``, ``5m``, ``2h``, ``1d``, ``2w``
24
+ - ISO 8601: ``PT1H30M``, ``PT30S``
25
+
26
+ Raises:
27
+ ValueError: If the duration string is invalid.
28
+ """
29
+ m = _SHORTHAND_RE.match(value)
30
+ if m:
31
+ return int(m.group(1)) * _SHORTHAND_MULTIPLIERS[m.group(2)]
32
+
33
+ m = _ISO_RE.match(value)
34
+ if m:
35
+ hours = int(m.group(1) or 0)
36
+ minutes = int(m.group(2) or 0)
37
+ seconds = int(m.group(3) or 0)
38
+ if hours == 0 and minutes == 0 and seconds == 0:
39
+ raise ValueError(f"Invalid ISO 8601 duration: {value}")
40
+ return (hours * 3600 + minutes * 60 + seconds) * 1000
41
+
42
+ raise ValueError(f"Invalid duration: {value}")
@@ -0,0 +1 @@
1
+ """Adapter interfaces, registry, and stubs."""
@@ -0,0 +1,39 @@
1
+ """In-process EventBus implementation backed by a simple dict of handlers."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING, Any
6
+
7
+ if TYPE_CHECKING:
8
+ from collections.abc import Callable
9
+
10
+
11
+ class InProcessEventBus:
12
+ """In-process pub/sub event bus."""
13
+
14
+ def __init__(self) -> None:
15
+ self._handlers: dict[str, list[Callable[..., Any]]] = {}
16
+
17
+ async def publish(self, topic: str, payload: Any) -> None:
18
+ for handler in self._handlers.get(topic, []):
19
+ handler(payload)
20
+
21
+ def subscribe(
22
+ self, topic: str, handler: Callable[..., Any],
23
+ ) -> Callable[[], None]:
24
+ self._handlers.setdefault(topic, []).append(handler)
25
+
26
+ def unsubscribe() -> None:
27
+ handlers = self._handlers.get(topic, [])
28
+ if handler in handlers:
29
+ handlers.remove(handler)
30
+
31
+ return unsubscribe
32
+
33
+ def subscriber_count(self, topic: str) -> int:
34
+ return len(self._handlers.get(topic, []))
35
+
36
+
37
+ def create_in_process_event_bus() -> InProcessEventBus:
38
+ """Create an in-process event bus."""
39
+ return InProcessEventBus()
@@ -0,0 +1,111 @@
1
+ """Git-based adapter resolver.
2
+
3
+ Resolves adapter metadata from git repository references (PRD Section 9.3).
4
+ Format: ``github.com/<org>/<repo>@<ref>``
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import re
10
+ from dataclasses import dataclass
11
+ from typing import Protocol
12
+
13
+ from ai_sdlc.adapters.registry import AdapterMetadata, validate_adapter_metadata
14
+ from ai_sdlc.adapters.scanner import parse_metadata_yaml
15
+
16
+ _GIT_REF_PATTERN = re.compile(r"^([^/]+)/([^/]+)/([^@]+)@(.+)$")
17
+
18
+
19
+ @dataclass(frozen=True)
20
+ class GitAdapterReference:
21
+ host: str
22
+ org: str
23
+ repo: str
24
+ ref: str
25
+
26
+
27
+ class GitAdapterFetcher(Protocol):
28
+ """Abstraction for fetching raw file content from a git host."""
29
+
30
+ async def fetch(self, url: str) -> str | None: ...
31
+
32
+
33
+ @dataclass(frozen=True)
34
+ class GitResolveResult:
35
+ metadata: AdapterMetadata | None
36
+ error: str | None = None
37
+
38
+
39
+ def parse_git_adapter_ref(ref: str) -> GitAdapterReference:
40
+ """Parse a git adapter reference string.
41
+
42
+ Expected format: ``github.com/org/repo@v1.0.0``
43
+ """
44
+ match = _GIT_REF_PATTERN.match(ref)
45
+ if not match:
46
+ raise ValueError(
47
+ f'Invalid git adapter reference "{ref}": '
48
+ "expected format <host>/<org>/<repo>@<ref>"
49
+ )
50
+ return GitAdapterReference(
51
+ host=match.group(1),
52
+ org=match.group(2),
53
+ repo=match.group(3),
54
+ ref=match.group(4),
55
+ )
56
+
57
+
58
+ def build_raw_url(parsed: GitAdapterReference) -> str:
59
+ """Build the raw content URL for a metadata.yaml file."""
60
+ if parsed.host == "github.com":
61
+ return (
62
+ f"https://raw.githubusercontent.com/"
63
+ f"{parsed.org}/{parsed.repo}/{parsed.ref}/metadata.yaml"
64
+ )
65
+ raise ValueError(f"Unsupported git host: {parsed.host}")
66
+
67
+
68
+ def create_stub_git_adapter_fetcher(entries: dict[str, str]) -> GitAdapterFetcher:
69
+ """Create a stub fetcher for testing. Maps URLs to YAML content strings."""
70
+
71
+ class _StubFetcher:
72
+ async def fetch(self, url: str) -> str | None:
73
+ return entries.get(url)
74
+
75
+ return _StubFetcher()
76
+
77
+
78
+ async def resolve_git_adapter(
79
+ ref: str,
80
+ fetcher: GitAdapterFetcher,
81
+ ) -> GitResolveResult:
82
+ """Resolve adapter metadata from a git reference."""
83
+ try:
84
+ parsed = parse_git_adapter_ref(ref)
85
+ except ValueError as err:
86
+ return GitResolveResult(metadata=None, error=str(err))
87
+
88
+ try:
89
+ url = build_raw_url(parsed)
90
+ except ValueError as err:
91
+ return GitResolveResult(metadata=None, error=str(err))
92
+
93
+ content = await fetcher.fetch(url)
94
+ if content is None:
95
+ return GitResolveResult(
96
+ metadata=None, error=f"Failed to fetch metadata from {url}"
97
+ )
98
+
99
+ try:
100
+ metadata = parse_metadata_yaml(content)
101
+ except Exception as err:
102
+ return GitResolveResult(metadata=None, error=f"Invalid YAML: {err}")
103
+
104
+ validation = validate_adapter_metadata(metadata)
105
+ if not validation.valid:
106
+ return GitResolveResult(
107
+ metadata=None,
108
+ error=f"Validation failed: {'; '.join(validation.errors)}",
109
+ )
110
+
111
+ return GitResolveResult(metadata=metadata)
@@ -0,0 +1,187 @@
1
+ """GitHub adapter stubs — SourceControl, IssueTracker, CIPipeline.
2
+
3
+ These are stub/protocol implementations. Real API calls require
4
+ an injected Octokit-like client (not bundled as a dependency).
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from dataclasses import dataclass
10
+ from typing import TYPE_CHECKING, Any, Protocol
11
+
12
+ if TYPE_CHECKING:
13
+ from collections.abc import AsyncIterator
14
+
15
+ from ai_sdlc.adapters.interfaces import (
16
+ Branch,
17
+ Build,
18
+ BuildEvent,
19
+ BuildFilter,
20
+ BuildStatus,
21
+ ChangedFile,
22
+ CommitStatus,
23
+ CoverageReport,
24
+ CreateBranchInput,
25
+ CreateIssueInput,
26
+ CreatePRInput,
27
+ FileContent,
28
+ Issue,
29
+ IssueComment,
30
+ IssueEvent,
31
+ IssueFilter,
32
+ MergeResult,
33
+ MergeStrategy,
34
+ PREvent,
35
+ PRFilter,
36
+ PullRequest,
37
+ TestResults,
38
+ TriggerBuildInput,
39
+ UpdateIssueInput,
40
+ )
41
+
42
+
43
+ @dataclass
44
+ class GitHubConfig:
45
+ org: str
46
+ repo: str | None = None
47
+ token_secret_ref: str | None = None
48
+
49
+
50
+ class GitHubClient(Protocol):
51
+ """Minimal protocol for a GitHub API client."""
52
+
53
+ async def request(
54
+ self, method: str, url: str, **kwargs: Any,
55
+ ) -> Any: ...
56
+
57
+
58
+ def _empty_async_iter() -> AsyncIterator[Any]:
59
+ async def _gen() -> AsyncIterator[Any]:
60
+ return
61
+ yield # noqa: RET504 # pragma: no cover
62
+ return _gen()
63
+
64
+
65
+ class _GitHubIssueTracker:
66
+ def __init__(self, client: GitHubClient, config: GitHubConfig) -> None:
67
+ self._client = client
68
+ self._config = config
69
+
70
+ async def list_issues(self, filter: IssueFilter) -> list[Issue]:
71
+ return []
72
+
73
+ async def get_issue(self, id: str) -> Issue:
74
+ return Issue(
75
+ id=id, title="", status="open",
76
+ url=f"https://github.com/{self._config.org}/{self._config.repo}/issues/{id}",
77
+ )
78
+
79
+ async def create_issue(self, input: CreateIssueInput) -> Issue:
80
+ return Issue(
81
+ id="1", title=input.title, status="open",
82
+ url=f"https://github.com/{self._config.org}/{self._config.repo}/issues/1",
83
+ description=input.description, labels=input.labels,
84
+ assignee=input.assignee,
85
+ )
86
+
87
+ async def update_issue(self, id: str, input: UpdateIssueInput) -> Issue:
88
+ return await self.get_issue(id)
89
+
90
+ async def transition_issue(self, id: str, transition: str) -> Issue:
91
+ return await self.get_issue(id)
92
+
93
+ async def add_comment(self, id: str, body: str) -> None:
94
+ pass
95
+
96
+ async def get_comments(self, id: str) -> list[IssueComment]:
97
+ return []
98
+
99
+ def watch_issues(self, filter: IssueFilter) -> AsyncIterator[IssueEvent]:
100
+ return _empty_async_iter()
101
+
102
+
103
+ class _GitHubSourceControl:
104
+ def __init__(self, client: GitHubClient, config: GitHubConfig) -> None:
105
+ self._client = client
106
+ self._config = config
107
+
108
+ async def create_branch(self, input: CreateBranchInput) -> Branch:
109
+ return Branch(name=input.name, sha="stub-sha")
110
+
111
+ async def create_pr(self, input: CreatePRInput) -> PullRequest:
112
+ return PullRequest(
113
+ id="1", title=input.title,
114
+ source_branch=input.source_branch,
115
+ target_branch=input.target_branch,
116
+ status="open", author="stub-user",
117
+ url=f"https://github.com/{self._config.org}/{self._config.repo}/pull/1",
118
+ description=input.description,
119
+ )
120
+
121
+ async def merge_pr(self, id: str, strategy: MergeStrategy) -> MergeResult:
122
+ return MergeResult(sha="merge-sha", merged=True)
123
+
124
+ async def get_file_contents(self, path: str, ref: str) -> FileContent:
125
+ return FileContent(path=path, content="", encoding="utf-8")
126
+
127
+ async def list_changed_files(self, pr_id: str) -> list[ChangedFile]:
128
+ return []
129
+
130
+ async def set_commit_status(
131
+ self, sha: str, status: CommitStatus,
132
+ ) -> None:
133
+ pass
134
+
135
+ def watch_pr_events(self, filter: PRFilter) -> AsyncIterator[PREvent]:
136
+ return _empty_async_iter()
137
+
138
+
139
+ class _GitHubCIPipeline:
140
+ def __init__(self, client: GitHubClient, config: GitHubConfig) -> None:
141
+ self._client = client
142
+ self._config = config
143
+
144
+ async def trigger_build(self, input: TriggerBuildInput) -> Build:
145
+ return Build(id="1", status="queued")
146
+
147
+ async def get_build_status(self, id: str) -> BuildStatus:
148
+ return BuildStatus(id=id, status="succeeded")
149
+
150
+ async def get_test_results(self, build_id: str) -> TestResults:
151
+ return TestResults(passed=0, failed=0, skipped=0)
152
+
153
+ async def get_coverage_report(self, build_id: str) -> CoverageReport:
154
+ return CoverageReport(line_coverage=0.0)
155
+
156
+ def watch_build_events(
157
+ self, filter: BuildFilter,
158
+ ) -> AsyncIterator[BuildEvent]:
159
+ return _empty_async_iter()
160
+
161
+
162
+ def create_github_issue_tracker(
163
+ config: GitHubConfig, client: GitHubClient | None = None,
164
+ ) -> _GitHubIssueTracker:
165
+ """Create a GitHub IssueTracker adapter."""
166
+ return _GitHubIssueTracker(client or _NoOpClient(), config)
167
+
168
+
169
+ def create_github_source_control(
170
+ config: GitHubConfig, client: GitHubClient | None = None,
171
+ ) -> _GitHubSourceControl:
172
+ """Create a GitHub SourceControl adapter."""
173
+ return _GitHubSourceControl(client or _NoOpClient(), config)
174
+
175
+
176
+ def create_github_ci_pipeline(
177
+ config: GitHubConfig, client: GitHubClient | None = None,
178
+ ) -> _GitHubCIPipeline:
179
+ """Create a GitHub CIPipeline adapter."""
180
+ return _GitHubCIPipeline(client or _NoOpClient(), config)
181
+
182
+
183
+ class _NoOpClient:
184
+ async def request(
185
+ self, method: str, url: str, **kwargs: Any,
186
+ ) -> Any:
187
+ return None