technical-debt-engine-runtime 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 (57) hide show
  1. technical_debt_engine_runtime-0.1.0/PKG-INFO +5 -0
  2. technical_debt_engine_runtime-0.1.0/README.md +30 -0
  3. technical_debt_engine_runtime-0.1.0/pyproject.toml +21 -0
  4. technical_debt_engine_runtime-0.1.0/setup.cfg +4 -0
  5. technical_debt_engine_runtime-0.1.0/src/tde_cli/__init__.py +5 -0
  6. technical_debt_engine_runtime-0.1.0/src/tde_cli/main.py +400 -0
  7. technical_debt_engine_runtime-0.1.0/src/tde_runtime/__init__.py +6 -0
  8. technical_debt_engine_runtime-0.1.0/src/tde_runtime/baseline.py +196 -0
  9. technical_debt_engine_runtime-0.1.0/src/tde_runtime/code_size.py +49 -0
  10. technical_debt_engine_runtime-0.1.0/src/tde_runtime/complexity.py +92 -0
  11. technical_debt_engine_runtime-0.1.0/src/tde_runtime/configuration.py +112 -0
  12. technical_debt_engine_runtime-0.1.0/src/tde_runtime/dependency_health.py +23 -0
  13. technical_debt_engine_runtime-0.1.0/src/tde_runtime/docker_artifact.py +47 -0
  14. technical_debt_engine_runtime-0.1.0/src/tde_runtime/evidence_store.py +69 -0
  15. technical_debt_engine_runtime-0.1.0/src/tde_runtime/execution.py +213 -0
  16. technical_debt_engine_runtime-0.1.0/src/tde_runtime/maintainability.py +11 -0
  17. technical_debt_engine_runtime-0.1.0/src/tde_runtime/models.py +70 -0
  18. technical_debt_engine_runtime-0.1.0/src/tde_runtime/policies/__init__.py +1 -0
  19. technical_debt_engine_runtime-0.1.0/src/tde_runtime/policies/generation-1.json +18 -0
  20. technical_debt_engine_runtime-0.1.0/src/tde_runtime/policy.py +202 -0
  21. technical_debt_engine_runtime-0.1.0/src/tde_runtime/query.py +36 -0
  22. technical_debt_engine_runtime-0.1.0/src/tde_runtime/registries.py +21 -0
  23. technical_debt_engine_runtime-0.1.0/src/tde_runtime/release_bundle.py +34 -0
  24. technical_debt_engine_runtime-0.1.0/src/tde_runtime/release_candidate.py +75 -0
  25. technical_debt_engine_runtime-0.1.0/src/tde_runtime/release_certification.py +87 -0
  26. technical_debt_engine_runtime-0.1.0/src/tde_runtime/release_publication.py +114 -0
  27. technical_debt_engine_runtime-0.1.0/src/tde_runtime/release_qualification.py +115 -0
  28. technical_debt_engine_runtime-0.1.0/src/tde_runtime/runtime.py +193 -0
  29. technical_debt_engine_runtime-0.1.0/src/tde_runtime/runtime_qualification.py +63 -0
  30. technical_debt_engine_runtime-0.1.0/src/tde_runtime/software_assurance.py +183 -0
  31. technical_debt_engine_runtime-0.1.0/src/tde_runtime/trend.py +73 -0
  32. technical_debt_engine_runtime-0.1.0/src/tde_runtime/trusted_delivery.py +137 -0
  33. technical_debt_engine_runtime-0.1.0/src/technical_debt_engine_runtime.egg-info/PKG-INFO +5 -0
  34. technical_debt_engine_runtime-0.1.0/src/technical_debt_engine_runtime.egg-info/SOURCES.txt +55 -0
  35. technical_debt_engine_runtime-0.1.0/src/technical_debt_engine_runtime.egg-info/dependency_links.txt +1 -0
  36. technical_debt_engine_runtime-0.1.0/src/technical_debt_engine_runtime.egg-info/entry_points.txt +2 -0
  37. technical_debt_engine_runtime-0.1.0/src/technical_debt_engine_runtime.egg-info/top_level.txt +2 -0
  38. technical_debt_engine_runtime-0.1.0/tests/test_baseline.py +57 -0
  39. technical_debt_engine_runtime-0.1.0/tests/test_build_reproducibility.py +41 -0
  40. technical_debt_engine_runtime-0.1.0/tests/test_cli.py +166 -0
  41. technical_debt_engine_runtime-0.1.0/tests/test_code_size.py +126 -0
  42. technical_debt_engine_runtime-0.1.0/tests/test_complexity.py +63 -0
  43. technical_debt_engine_runtime-0.1.0/tests/test_docker_artifact.py +45 -0
  44. technical_debt_engine_runtime-0.1.0/tests/test_evidence_store.py +18 -0
  45. technical_debt_engine_runtime-0.1.0/tests/test_execution.py +11 -0
  46. technical_debt_engine_runtime-0.1.0/tests/test_policy.py +97 -0
  47. technical_debt_engine_runtime-0.1.0/tests/test_query.py +9 -0
  48. technical_debt_engine_runtime-0.1.0/tests/test_release_bundle.py +25 -0
  49. technical_debt_engine_runtime-0.1.0/tests/test_release_candidate.py +44 -0
  50. technical_debt_engine_runtime-0.1.0/tests/test_release_certification.py +70 -0
  51. technical_debt_engine_runtime-0.1.0/tests/test_release_publication.py +113 -0
  52. technical_debt_engine_runtime-0.1.0/tests/test_release_qualification.py +48 -0
  53. technical_debt_engine_runtime-0.1.0/tests/test_runtime.py +102 -0
  54. technical_debt_engine_runtime-0.1.0/tests/test_runtime_qualification.py +15 -0
  55. technical_debt_engine_runtime-0.1.0/tests/test_software_assurance.py +53 -0
  56. technical_debt_engine_runtime-0.1.0/tests/test_trend.py +28 -0
  57. technical_debt_engine_runtime-0.1.0/tests/test_trusted_delivery.py +72 -0
@@ -0,0 +1,5 @@
1
+ Metadata-Version: 2.4
2
+ Name: technical-debt-engine-runtime
3
+ Version: 0.1.0
4
+ Summary: Technical Debt Engine runtime foundation API
5
+ Requires-Python: >=3.11
@@ -0,0 +1,30 @@
1
+ # Technical Debt Engine
2
+
3
+ Technical Debt Engine (TDE) is a standalone, capability-based engineering platform for measuring, normalizing, qualifying, and reporting technical debt across software projects.
4
+
5
+ TDE is project-independent, platform-independent, CI-independent, language-independent, and vendor-neutral. DJConnect is the first reference consumer; it does not own TDE's architecture, roadmap, or release lifecycle.
6
+
7
+ The repository contains an operational development package and reproducible
8
+ candidate-build foundation. No package has been published and no release exists.
9
+
10
+ ## Product contracts
11
+
12
+ Consumers integrate only through the future `tde` CLI, configuration, evidence schema, exit codes, and stable released contracts—not runtime internals. See [INTEGRATION_MODEL.md](INTEGRATION_MODEL.md).
13
+
14
+ Operational repository assurance is available through `tde assure`; see [SOFTWARE_ASSURANCE.md](SOFTWARE_ASSURANCE.md) for its canonical evidence and candidate-artifact verification contract.
15
+
16
+ ## Documentation
17
+
18
+ - [Product architecture](PRODUCT_ARCHITECTURE.md)
19
+ - [Platform vision](PLATFORM_VISION.md) and [platform strategy](PLATFORM_STRATEGY.md)
20
+ - [Engineering method](ENGINEERING_METHOD.md) and [session bootstrap](BOOTSTRAP.md)
21
+ - [Capability model](CAPABILITY_MODEL.md)
22
+ - [CLI specification](CLI_SPECIFICATION.md)
23
+ - [Evidence schema](EVIDENCE_SCHEMA.md)
24
+ - [Qualification model](QUALIFICATION_MODEL.md)
25
+ - [Roadmap](PRODUCT_ROADMAP.md) and [backlog](PRODUCT_BACKLOG.md)
26
+ - [Versioning](VERSIONING.md) and [release strategy](RELEASE_STRATEGY.md)
27
+ - [Package build reproducibility](PACKAGING.md)
28
+ - [Repository status](REPOSITORY_STATUS.md)
29
+
30
+ The documentation index is [PROMPT_INDEX.md](PROMPT_INDEX.md).
@@ -0,0 +1,21 @@
1
+ [build-system]
2
+ requires = ["setuptools==80.9.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "technical-debt-engine-runtime"
7
+ version = "0.1.0"
8
+ description = "Technical Debt Engine runtime foundation API"
9
+ requires-python = ">=3.11"
10
+
11
+ [project.scripts]
12
+ tde = "tde_cli.main:console_main"
13
+
14
+ [tool.setuptools.packages.find]
15
+ where = ["src"]
16
+
17
+ [tool.setuptools.package-data]
18
+ tde_runtime = ["policies/*.json"]
19
+
20
+ [tool.unittest]
21
+ start-directory = "tests"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,5 @@
1
+ """Thin command-line presentation layer for the TDE runtime."""
2
+
3
+ from .main import main
4
+
5
+ __all__ = ["main"]
@@ -0,0 +1,400 @@
1
+ """CLI framework that consumes only the public Runtime API."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import json
7
+ import logging
8
+ from pathlib import Path
9
+ import sys
10
+ from typing import Any, Sequence, TextIO
11
+
12
+ from tde_runtime import Runtime, RuntimeConfiguration
13
+ from tde_runtime.baseline import BaselineError, BaselineRepository, ComparisonEngine, ComparisonRepository
14
+ from tde_runtime.policy import PolicyEngine, PolicyError
15
+ from tde_runtime.trend import TrendEngine
16
+ from tde_runtime.evidence_store import EvidenceStore
17
+ from tde_runtime.runtime_qualification import RuntimeQualificationEngine
18
+ from tde_runtime.software_assurance import SoftwareAssurance
19
+ from tde_runtime.trusted_delivery import TrustedDelivery
20
+ from tde_runtime.release_qualification import ReleaseQualification
21
+ from tde_runtime.release_certification import ReleaseCertification
22
+ from tde_runtime.runtime import EVIDENCE_SCHEMA_VERSION, RUNTIME_VERSION
23
+
24
+
25
+ CLI_VERSION = "0.1.0"
26
+ GENERATION = "1"
27
+
28
+
29
+ class ExitCode:
30
+ SUCCESS = 0
31
+ WARNING = 1
32
+ FAILED = 2
33
+ BLOCKED = 3
34
+ NOT_SUPPORTED = 4
35
+
36
+
37
+ def _policy_exit_code(decision: str) -> int:
38
+ """The CLI maps canonical Policy decisions; it never re-evaluates policy."""
39
+ return {"PASS": ExitCode.SUCCESS, "PASS_WITH_WARNINGS": ExitCode.WARNING,
40
+ "FAIL": ExitCode.FAILED, "BLOCKED": ExitCode.BLOCKED,
41
+ "NOT_APPLICABLE": ExitCode.NOT_SUPPORTED}.get(decision, ExitCode.BLOCKED)
42
+
43
+
44
+ COMMANDS: dict[str, dict[str, str]] = {
45
+ "help": {"purpose": "Show generated CLI help."},
46
+ "validate": {"purpose": "Validate runtime configuration and context."},
47
+ "inspect": {"purpose": "Inspect a target and planned Code Size execution."},
48
+ "assess": {"purpose": "Assess a target through selected capabilities."},
49
+ "baseline": {"purpose": "Create an immutable baseline from persisted canonical evidence."},
50
+ "compare": {"purpose": "Persist and qualify a canonical comparison against a baseline."},
51
+ "trend": {"purpose": "Aggregate canonical evidence history into trends."},
52
+ "query": {"purpose": "Query canonical engineering evidence."},
53
+ "store": {"purpose": "Persist canonical Runtime evidence."},
54
+ "history": {"purpose": "List persisted canonical evidence."},
55
+ "run": {"purpose": "Execute registered capabilities through the Execution Engine."},
56
+ "qualify": {"purpose": "Qualify canonical Runtime evidence."},
57
+ "assure": {"purpose": "Assure repository and artifact integrity."},
58
+ "trusted-delivery": {"purpose": "Validate immutable candidate and delivery evidence."},
59
+ "release-qualify": {"purpose": "Qualify a release candidate without publication."},
60
+ "certify": {"purpose": "Certify a qualified Internal Release candidate without publication."},
61
+ "report": {"purpose": "Render a Code Size evidence projection."},
62
+ "explain": {"purpose": "Explain a result (not implemented)."},
63
+ }
64
+
65
+
66
+ def _global_options(parser: argparse.ArgumentParser) -> None:
67
+ parser.add_argument("--verbose", action="store_true", help="Enable INFO logging.")
68
+ parser.add_argument("--quiet", action="store_true", help="Suppress non-error logging.")
69
+ parser.add_argument("--config", help="Path to repository .tde.yml configuration.")
70
+ parser.add_argument("--output", help="Output destination (reserved; console is used now).")
71
+ parser.add_argument("--format", choices=("human", "json", "markdown"), default="human", help="Output format.")
72
+ parser.add_argument("--log-level", choices=("ERROR", "WARNING", "INFO", "DEBUG", "TRACE"), help="Logging level.")
73
+ parser.add_argument("--policy", help="Repository or workspace policy directory.")
74
+ parser.add_argument("--policy-override", action="append", default=[], metavar="RULE=JSON", help="Override a policy rule with a JSON object.")
75
+ parser.add_argument("--baseline-location", help="Directory used for immutable baselines.")
76
+ parser.add_argument("--history-depth", type=int, help="Maximum baseline history depth for trends.")
77
+ parser.add_argument("--store-location", help="Directory used for canonical evidence storage.")
78
+
79
+
80
+ def build_parser() -> argparse.ArgumentParser:
81
+ parser = argparse.ArgumentParser(prog="tde", description="Technical Debt Engine CLI foundation.")
82
+ parser.add_argument("--version", action="store_true", help="Show CLI, runtime, schema, and generation versions.")
83
+ _global_options(parser)
84
+ subcommands = parser.add_subparsers(dest="command", title="commands")
85
+ for identifier, metadata in COMMANDS.items():
86
+ command = subcommands.add_parser(identifier, help=metadata["purpose"], description=metadata["purpose"])
87
+ command.add_argument("target", nargs="?", default=".", help="Repository target (default: current directory).")
88
+ command.add_argument("--capability", action="append", default=[], help="Enable a registered capability.")
89
+ if identifier == "baseline":
90
+ command.add_argument("--name", help="Immutable baseline name.")
91
+ if identifier == "compare":
92
+ command.add_argument("--baseline", help="Baseline name or JSON path.")
93
+ if identifier == "query":
94
+ command.add_argument("--resource", default="repositories", help="Evidence resource.")
95
+ command.add_argument("--filter", action="append", default=[], metavar="KEY=VALUE")
96
+ command.add_argument("--aggregate", choices=("count",))
97
+ if identifier == "assure":
98
+ command.add_argument("--artifact-directory", action="append", default=[], metavar="DIRECTORY",
99
+ help="Candidate build directory; repeat for independent reproducibility verification.")
100
+ if identifier == "trusted-delivery":
101
+ command.add_argument("--artifact-directory", action="append", default=[], metavar="DIRECTORY",
102
+ help="Candidate build directory; repeat for independent reproducibility verification.")
103
+ command.add_argument("--manifest", metavar="PATH", help="Canonical JSON delivery manifest for this candidate.")
104
+ if identifier == "release-qualify":
105
+ command.add_argument("--artifact-directory", action="append", default=[], metavar="DIRECTORY")
106
+ command.add_argument("--docker-artifact-directory", metavar="DIRECTORY")
107
+ command.add_argument("--manifest-output", required=True, metavar="PATH")
108
+ command.add_argument("--release-capability", action="append", default=[], metavar="CAPABILITY",
109
+ help="Required release capability; repeat for every selected capability.")
110
+ if identifier == "certify":
111
+ command.add_argument("--qualification-evidence", required=True, metavar="PATH")
112
+ command.add_argument("--report-output", required=True, metavar="PATH")
113
+ return parser
114
+
115
+
116
+ def _load_configuration(path: str | None, target: str) -> RuntimeConfiguration:
117
+ return RuntimeConfiguration.discover(target, path)
118
+
119
+
120
+ def _configure_logging(arguments: argparse.Namespace) -> None:
121
+ level = arguments.log_level or ("INFO" if arguments.verbose else "ERROR" if arguments.quiet else "WARNING")
122
+ logging.basicConfig(level=logging.DEBUG if level == "TRACE" else getattr(logging, level), format="%(levelname)s %(message)s")
123
+
124
+
125
+ def _render(value: dict[str, Any], output_format: str, stream: TextIO) -> None:
126
+ if output_format == "json":
127
+ print(json.dumps(value, sort_keys=True), file=stream)
128
+ return
129
+ if output_format == "markdown":
130
+ for key, item in value.items():
131
+ print(f"- **{key}:** `{item}`", file=stream)
132
+ return
133
+ for key, item in value.items():
134
+ print(f"{key}: {item}", file=stream)
135
+
136
+
137
+ def _store_location(arguments: argparse.Namespace, target: str) -> Path:
138
+ location = Path(arguments.store_location or ".tde/evidence")
139
+ return location if location.is_absolute() else Path(target) / location
140
+
141
+
142
+ def _runtime_result(command: str, target: str, configuration: RuntimeConfiguration,
143
+ store: EvidenceStore | None = None) -> tuple[int, dict[str, Any]]:
144
+ result = Runtime().execute(target, configuration)
145
+ payload = {"command": command, "runtime": result.report["runtimeSummary"],
146
+ "execution": result.report["executionSummary"], "environment": result.report["environment"], "qualification": result.report["qualification"],
147
+ "runtimeQualification": result.evidence["runtimeQualification"], "validation": result.validation,
148
+ "evidence": result.evidence, "evidenceId": result.evidence["integrity"]["contentDigest"]}
149
+ if store is not None:
150
+ payload["evidenceStore"] = store.persist(result.evidence)
151
+ decision = result.evidence["policyEvidence"]["decision"]
152
+ if decision == "BLOCKED":
153
+ return ExitCode.BLOCKED, payload
154
+ if command in {"assess", "run"} and result.evidence["runtimeQualification"]["level"] != "QUALIFIED":
155
+ return ExitCode.BLOCKED, payload
156
+ return (_policy_exit_code(decision) if command in {"assess", "run"} else ExitCode.SUCCESS), payload
157
+
158
+
159
+ def _render_capability_report(evidence: dict[str, Any], capability: str, output_format: str, stream: TextIO) -> None:
160
+ metrics = {item["metricKey"]: item["value"] for item in evidence.get("measurements", []) if item.get("scope") == "repository" and item.get("capabilityId") == capability}
161
+ title = "Code Size" if capability == "code_size" else "Complexity"
162
+ payload = {"schemaId": "tde.report", "schemaVersion": evidence["schemaVersion"], "evidenceId": evidence["integrity"]["contentDigest"],
163
+ "format": output_format, "content": {"capability": capability, "metrics": metrics,
164
+ "qualification": evidence["runtimeQualification"]["level"]}}
165
+ if output_format == "markdown":
166
+ print(f"# {title} Report", file=stream)
167
+ print("", file=stream)
168
+ for key, value in sorted(metrics.items()):
169
+ print(f"- **{key}:** {value}", file=stream)
170
+ print(f"- **qualification:** {payload['content']['qualification']}", file=stream)
171
+ return
172
+ _render(payload, output_format, stream)
173
+
174
+
175
+ def main(argv: Sequence[str] | None = None, stdout: TextIO | None = None) -> int:
176
+ stream = stdout or sys.stdout
177
+ parser = build_parser()
178
+ arguments = parser.parse_args(argv)
179
+ prepared = _prepare_command(arguments, parser, stream)
180
+ if isinstance(prepared, int): return prepared
181
+ configuration = prepared
182
+ if arguments.command in {"store", "history"}:
183
+ store = EvidenceStore(_store_location(arguments, arguments.target))
184
+ try:
185
+ if arguments.command == "history":
186
+ _render({"command": "history", "records": store.history()}, arguments.format, stream)
187
+ return ExitCode.SUCCESS
188
+ record = Runtime().execute(arguments.target, configuration)
189
+ _render({"command": "store", "record": store.persist(record.evidence)}, arguments.format, stream)
190
+ return ExitCode.SUCCESS
191
+ except (ValueError, OSError, json.JSONDecodeError) as error:
192
+ _render({"command": arguments.command, "status": "BLOCKED", "reason": str(error)}, arguments.format, stream)
193
+ return ExitCode.BLOCKED
194
+ return _execute_command(arguments, configuration, stream)
195
+
196
+
197
+ def _prepare_command(arguments: argparse.Namespace, parser: argparse.ArgumentParser, stream: TextIO) -> RuntimeConfiguration | int:
198
+ if arguments.version:
199
+ _render({"cliVersion": CLI_VERSION, "runtimeVersion": RUNTIME_VERSION,
200
+ "schemaVersion": EVIDENCE_SCHEMA_VERSION, "generation": GENERATION}, arguments.format, stream)
201
+ return ExitCode.SUCCESS
202
+ if not arguments.command:
203
+ parser.print_help(stream)
204
+ return ExitCode.SUCCESS
205
+ if arguments.command == "help":
206
+ parser.print_help(stream)
207
+ return ExitCode.SUCCESS
208
+ _configure_logging(arguments)
209
+ try:
210
+ configuration = _load_configuration(arguments.config, arguments.target)
211
+ except ValueError as error:
212
+ _render({"status": "BLOCKED", "reason": str(error)}, arguments.format, stream)
213
+ return ExitCode.BLOCKED
214
+ if arguments.policy or arguments.policy_override:
215
+ values = configuration.as_dict()
216
+ policy = dict(values["executionOptions"].get("policy", {}))
217
+ if arguments.policy:
218
+ policy["repository"] = arguments.policy
219
+ overrides = dict(policy.get("overrides", {}))
220
+ try:
221
+ for item in arguments.policy_override:
222
+ rule, raw_value = item.split("=", 1)
223
+ overrides[rule] = json.loads(raw_value)
224
+ if not isinstance(overrides[rule], dict):
225
+ raise ValueError("override must be a JSON object")
226
+ except (ValueError, json.JSONDecodeError) as error:
227
+ _render({"status": "BLOCKED", "reason": f"invalid policy override: {error}"}, arguments.format, stream)
228
+ return ExitCode.BLOCKED
229
+ policy["overrides"] = overrides
230
+ values["policy"] = policy
231
+ values["executionOptions"].pop("policy", None)
232
+ configuration = RuntimeConfiguration.load(values)
233
+ if arguments.baseline_location:
234
+ values = configuration.as_dict()
235
+ values["baseline"] = {"location": arguments.baseline_location}
236
+ values["executionOptions"].pop("baseline", None)
237
+ configuration = RuntimeConfiguration.load(values)
238
+ if arguments.history_depth is not None:
239
+ if arguments.history_depth < 0:
240
+ _render({"status": "BLOCKED", "reason": "history depth must not be negative"}, arguments.format, stream)
241
+ return ExitCode.BLOCKED
242
+ values = configuration.as_dict()
243
+ values["trend"] = {"historyDepth": arguments.history_depth}
244
+ values["executionOptions"].pop("trend", None)
245
+ configuration = RuntimeConfiguration.load(values)
246
+ if arguments.command in {"assess", "baseline", "compare", "run", "store", "inspect", "validate", "qualify", "report"} and arguments.capability:
247
+ supported = {"code-size": "code_size", "complexity": "complexity"}
248
+ if len(arguments.capability) != 1 or arguments.capability[0] not in supported:
249
+ _render({"command": arguments.command, "status": "NOT_SUPPORTED", "reason": "This vertical slice supports code-size and complexity."}, arguments.format, stream)
250
+ return ExitCode.NOT_SUPPORTED
251
+ configuration = configuration.with_capability(supported[arguments.capability[0]])
252
+ if arguments.command == "release-qualify":
253
+ supported = {"code-size": "code_size", "complexity": "complexity"}
254
+ if not arguments.release_capability or any(item not in supported for item in arguments.release_capability):
255
+ _render({"command": "release-qualify", "status": "BLOCKED",
256
+ "reason": "release-qualify requires one or more supported --release-capability values"}, arguments.format, stream)
257
+ return ExitCode.BLOCKED
258
+ for capability in sorted(set(arguments.release_capability)):
259
+ configuration = configuration.with_capability(supported[capability])
260
+ return configuration
261
+
262
+
263
+ def _execute_command(arguments: argparse.Namespace, configuration: RuntimeConfiguration, stream: TextIO) -> int:
264
+ if arguments.command in {"baseline", "compare"}:
265
+ return _baseline_command(arguments, configuration, stream)
266
+ if arguments.command == "trend":
267
+ return _trend_command(arguments, configuration, stream)
268
+ if arguments.command == "query":
269
+ return _query_command(arguments, configuration, stream)
270
+ if arguments.command == "qualify":
271
+ try:
272
+ result=Runtime().execute(arguments.target,configuration)
273
+ capability=arguments.capability[0].replace("-","_") if arguments.capability else None
274
+ qualification=RuntimeQualificationEngine().qualify(result.evidence,capability)
275
+ _render({"command":"qualify","runtimeQualification":qualification},arguments.format,stream)
276
+ return ExitCode.SUCCESS if qualification["level"]!="BLOCKED" else ExitCode.BLOCKED
277
+ except ValueError as error:
278
+ _render({"command":"qualify","status":"BLOCKED","reason":str(error)},arguments.format,stream); return ExitCode.BLOCKED
279
+ if arguments.command == "report":
280
+ return _report_command(arguments, stream)
281
+ if arguments.command == "assure":
282
+ evidence=SoftwareAssurance().assure(arguments.target,arguments.artifact_directory)
283
+ _render({"command":"assure","assuranceEvidence":evidence},arguments.format,stream)
284
+ return _policy_exit_code(evidence["decision"])
285
+ if arguments.command == "trusted-delivery":
286
+ result=Runtime().execute(arguments.target,configuration)
287
+ assurance=SoftwareAssurance().assure(arguments.target,arguments.artifact_directory)
288
+ evidence=TrustedDelivery().validate(arguments.target,result.evidence,assurance,arguments.manifest)
289
+ _render({"command":"trusted-delivery","trustedDeliveryEvidence":evidence,"softwareAssurance":assurance},arguments.format,stream)
290
+ return _policy_exit_code(evidence["qualification"])
291
+ if arguments.command == "release-qualify":
292
+ result=Runtime().execute(arguments.target,configuration)
293
+ evidence=ReleaseQualification().qualify(arguments.target,result.evidence,arguments.artifact_directory,arguments.manifest_output,
294
+ [item.replace("-", "_") for item in arguments.release_capability], arguments.docker_artifact_directory)
295
+ _render({"command":"release-qualify","releaseQualificationEvidence":evidence},arguments.format,stream)
296
+ return ExitCode.SUCCESS if evidence["decision"] == "RELEASE_QUALIFIED" else ExitCode.FAILED
297
+ if arguments.command == "certify":
298
+ evidence = ReleaseCertification().certify(arguments.qualification_evidence, arguments.report_output)
299
+ _render({"command": "certify", "releaseCertificationEvidence": evidence}, arguments.format, stream)
300
+ return ExitCode.SUCCESS if evidence["decision"] == "RELEASE_CERTIFIED" else ExitCode.BLOCKED
301
+ if arguments.command in {"validate", "inspect", "assess", "run"}:
302
+ if arguments.command in {"assess", "run"}:
303
+ if not arguments.capability:
304
+ _render({"command": "assess", "status": "NOT_IMPLEMENTED", "reason": "Only code-size and complexity are delivered."}, arguments.format, stream)
305
+ return ExitCode.NOT_SUPPORTED
306
+ try:
307
+ store = EvidenceStore(_store_location(arguments, arguments.target)) if arguments.command in {"assess", "run"} else None
308
+ code, payload = _runtime_result(arguments.command, arguments.target, configuration, store)
309
+ except (ValueError, OSError, json.JSONDecodeError) as error:
310
+ _render({"status": "BLOCKED", "reason": str(error)}, arguments.format, stream)
311
+ return ExitCode.BLOCKED
312
+ _render(payload, arguments.format, stream)
313
+ return code
314
+ _render({"command": arguments.command, "status": "NOT_IMPLEMENTED",
315
+ "reason": "This command framework is present; its capability behavior is not delivered."}, arguments.format, stream)
316
+ return ExitCode.NOT_SUPPORTED
317
+
318
+
319
+ def _baseline_command(arguments: argparse.Namespace, configuration: RuntimeConfiguration, stream: TextIO) -> int:
320
+ location = configuration.execution_options.get("baseline", {}).get("location", ".tde/baselines")
321
+ repository = BaselineRepository(Path(arguments.target) / location if not Path(location).is_absolute() else location)
322
+ evidence_store = EvidenceStore(_store_location(arguments, arguments.target))
323
+ try:
324
+ current = Runtime().execute(arguments.target, configuration)
325
+ persisted = evidence_store.persist(current.evidence)
326
+ evidence = evidence_store.retrieve(persisted["id"])["evidence"]
327
+ if arguments.command == "baseline": return _create_baseline(arguments, repository, evidence, persisted, stream)
328
+ return _compare_baseline(arguments, repository, current, evidence, persisted, stream)
329
+ except (BaselineError, PolicyError, ValueError) as error:
330
+ _render({"command": arguments.command, "status": "BLOCKED", "reason": str(error)}, arguments.format, stream)
331
+ return ExitCode.BLOCKED
332
+
333
+
334
+ def _create_baseline(arguments, repository, evidence, persisted, stream):
335
+ baseline = repository.create(evidence, arguments.name)
336
+ _render({"command": "baseline", "status": "VALID", "evidenceStore": persisted, "baseline": baseline}, arguments.format, stream)
337
+ return ExitCode.SUCCESS
338
+
339
+
340
+ def _compare_baseline(arguments, repository, current, evidence, persisted, stream):
341
+ if not arguments.baseline: raise BaselineError("compare requires --baseline")
342
+ baseline = repository.load(arguments.baseline)
343
+ comparison = ComparisonEngine().compare(evidence, baseline)
344
+ policy = PolicyEngine().load(current.context.configuration, current.context.repository_root, current.context.runtime_version, current.context.schema_version)
345
+ normalized = {"measurements": evidence["measurements"], "findings": evidence["findings"], "capabilityResults": evidence["capabilityResults"], "comparison": comparison}
346
+ policy_evidence = PolicyEngine().evaluate(policy, normalized, current.context.configuration)
347
+ persisted_comparison = ComparisonRepository(repository.location.parent / "comparisons").persist(comparison, policy_evidence, baseline)
348
+ _render({"command": "compare", "evidenceStore": persisted, "comparison": comparison, "comparisonStore": persisted_comparison, "policyEvidence": policy_evidence, "qualificationDelta": persisted_comparison["qualificationDelta"]}, arguments.format, stream)
349
+ return ExitCode.BLOCKED if policy_evidence["decision"] == "BLOCKED" else ExitCode.SUCCESS
350
+
351
+
352
+ def _trend_command(arguments, configuration, stream):
353
+ location = configuration.execution_options.get("baseline", {}).get("location", ".tde/baselines")
354
+ location = Path(arguments.target) / location if not Path(location).is_absolute() else Path(location)
355
+ try:
356
+ current = Runtime().execute(arguments.target, configuration)
357
+ trend = TrendEngine().build(current.evidence, location, configuration.execution_options.get("trend", {}).get("historyDepth"))
358
+ policy = PolicyEngine().load(current.context.configuration, current.context.repository_root, current.context.runtime_version, current.context.schema_version)
359
+ inputs = {"measurements": current.evidence["measurements"], "findings": current.evidence["findings"], "capabilityResults": current.evidence["capabilityResults"], "trend": trend}
360
+ evidence = PolicyEngine().evaluate(policy, inputs, current.context.configuration)
361
+ _render({"command": "trend", "trendEvidence": trend, "policyEvidence": evidence}, arguments.format, stream)
362
+ return ExitCode.BLOCKED if evidence["decision"] == "BLOCKED" else ExitCode.SUCCESS
363
+ except (ValueError, PolicyError) as error:
364
+ _render({"command": "trend", "status": "BLOCKED", "reason": str(error)}, arguments.format, stream); return ExitCode.BLOCKED
365
+
366
+
367
+ def _query_command(arguments, configuration, stream):
368
+ try:
369
+ filters = dict(item.split("=", 1) for item in arguments.filter)
370
+ records = EvidenceStore(_store_location(arguments, arguments.target)).history()
371
+ if not records: raise ValueError("no persisted evidence is available; run assess first")
372
+ evidence = records[-1]["evidence"]
373
+ location = configuration.execution_options.get("baseline", {}).get("location", ".tde/baselines")
374
+ baseline_path = Path(arguments.target) / location if not Path(location).is_absolute() else Path(location)
375
+ comparisons = ComparisonRepository(baseline_path.parent / "comparisons").history()
376
+ baselines = [BaselineRepository(baseline_path).load(path) for path in sorted(baseline_path.glob("*.json"))] if baseline_path.is_dir() else []
377
+ response = Runtime().query(evidence, {"resource": arguments.resource, "filter": filters, "aggregate": arguments.aggregate, "baselines": baselines, "comparisons": comparisons})
378
+ _render({"command": "query", "evidenceId": evidence["integrity"]["contentDigest"], **response}, arguments.format, stream); return ExitCode.SUCCESS
379
+ except (ValueError, PolicyError) as error:
380
+ _render({"command": "query", "status": "BLOCKED", "reason": str(error)}, arguments.format, stream); return ExitCode.BLOCKED
381
+
382
+
383
+ def _report_command(arguments, stream):
384
+ supported = {"code-size": "code_size", "complexity": "complexity"}
385
+ if len(arguments.capability) != 1 or arguments.capability[0] not in supported:
386
+ _render({"command": "report", "status": "NOT_SUPPORTED", "reason": "report requires --capability code-size or --capability complexity"}, arguments.format, stream); return ExitCode.NOT_SUPPORTED
387
+ try:
388
+ capability = supported[arguments.capability[0]]
389
+ records = EvidenceStore(_store_location(arguments, arguments.target)).history()
390
+ evidence = next((record["evidence"] for record in reversed(records) if any(item.get("capabilityId") == capability for item in record["evidence"].get("capabilityResults", []))), None)
391
+ if evidence is None: raise ValueError("no persisted evidence is available for this capability; run assess first")
392
+ except ValueError as error:
393
+ _render({"command": "report", "status": "BLOCKED", "reason": str(error)}, arguments.format, stream); return ExitCode.BLOCKED
394
+ if evidence["runtimeQualification"]["level"] != "QUALIFIED":
395
+ _render({"command": "report", "status": "BLOCKED", "reason": "capability evidence is not qualified"}, arguments.format, stream); return ExitCode.BLOCKED
396
+ _render_capability_report(evidence, capability, arguments.format, stream); return ExitCode.SUCCESS
397
+
398
+
399
+ def console_main() -> None:
400
+ raise SystemExit(main())
@@ -0,0 +1,6 @@
1
+ """Public, CLI-independent API for the Technical Debt Engine runtime foundation."""
2
+
3
+ from .configuration import RuntimeConfiguration
4
+ from .runtime import Runtime
5
+
6
+ __all__ = ["Runtime", "RuntimeConfiguration"]