core-runtime-engine 11.5.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. core_runtime/__init__.py +10 -0
  2. core_runtime/__version__.py +17 -0
  3. core_runtime/cli/__init__.py +7 -0
  4. core_runtime/cli/__main__.py +22 -0
  5. core_runtime/cli/bump_version.py +176 -0
  6. core_runtime/cli/contract_preflight.py +69 -0
  7. core_runtime/cli/create_domain.py +66 -0
  8. core_runtime/cli/doctor.py +44 -0
  9. core_runtime/cli/inventory.py +85 -0
  10. core_runtime/cli/lint.py +8 -0
  11. core_runtime/cli/main.py +579 -0
  12. core_runtime/cli/release_check.py +65 -0
  13. core_runtime/cli/repair_artifact_paths.py +48 -0
  14. core_runtime/cli/sync_template.py +67 -0
  15. core_runtime/cli/validate.py +73 -0
  16. core_runtime/core/__init__.py +34 -0
  17. core_runtime/core/audit_event.py +760 -0
  18. core_runtime/core/audit_trail_index.py +100 -0
  19. core_runtime/core/canonicalization.py +55 -0
  20. core_runtime/core/contract_evaluator.py +945 -0
  21. core_runtime/core/contract_executability.py +307 -0
  22. core_runtime/core/contract_loader.py +57 -0
  23. core_runtime/core/contract_probes.py +630 -0
  24. core_runtime/core/contract_program.py +131 -0
  25. core_runtime/core/contract_program_registry.py +104 -0
  26. core_runtime/core/contract_program_v2.py +126 -0
  27. core_runtime/core/dsk_v3.py +142 -0
  28. core_runtime/core/explainability.py +2115 -0
  29. core_runtime/core/numeric_normalization.py +120 -0
  30. core_runtime/core/rule_anchor.py +1388 -0
  31. core_runtime/core/schema_fingerprint.py +69 -0
  32. core_runtime/core/sensor_evidence.py +548 -0
  33. core_runtime/data/contracts/CoreAnchor.sol +109 -0
  34. core_runtime/data/contracts/CoreRuleAnchor.abi.json +111 -0
  35. core_runtime/data/contracts/CoreRuleAnchor.bin +1 -0
  36. core_runtime/data/contracts/CoreRuleAnchor.build.json +20 -0
  37. core_runtime/data/contracts/CoreRuleAnchor.runtime.bin +1 -0
  38. core_runtime/data/contracts/CoreRuleAnchor.sol +74 -0
  39. core_runtime/data/package_data_manifest.v1.json +173 -0
  40. core_runtime/data/schemas/core/causal_trace.v1.json +141 -0
  41. core_runtime/data/schemas/core/context_gate.v1.json +38 -0
  42. core_runtime/data/schemas/core/context_threshold.v1.json +46 -0
  43. core_runtime/data/schemas/core/contract_program.v1.json +186 -0
  44. core_runtime/data/schemas/core/contract_program.v2.json +187 -0
  45. core_runtime/data/schemas/core/control_decision.v1.json +114 -0
  46. core_runtime/data/schemas/core/dsk.v3.json +105 -0
  47. core_runtime/data/schemas/core/effect_result.v1.json +39 -0
  48. core_runtime/data/schemas/core/entropy_signal.v1.json +108 -0
  49. core_runtime/data/schemas/core/execution_receipt.v1.json +93 -0
  50. core_runtime/data/schemas/core/frozen_release_manifest.v1.json +87 -0
  51. core_runtime/data/schemas/core/frozen_release_manifest.v2.json +72 -0
  52. core_runtime/data/schemas/core/frozen_release_manifest.v3.json +38 -0
  53. core_runtime/data/schemas/core/frozen_release_manifest.v4.json +72 -0
  54. core_runtime/data/schemas/core/frozen_release_manifest.v5.json +38 -0
  55. core_runtime/data/schemas/core/frozen_release_manifest.v6.json +116 -0
  56. core_runtime/data/schemas/core/frozen_release_manifest.v7.json +37 -0
  57. core_runtime/data/schemas/core/frozen_release_manifest.v8.json +114 -0
  58. core_runtime/data/schemas/core/frozen_rule_set.v1.json +282 -0
  59. core_runtime/data/schemas/core/memory_artifact.v1.json +120 -0
  60. core_runtime/data/schemas/core/memory_generation_result.v1.json +37 -0
  61. core_runtime/data/schemas/core/operational_learning_event.v1.json +63 -0
  62. core_runtime/data/schemas/core/pattern_candidate.v1.json +114 -0
  63. core_runtime/data/schemas/core/physical_safety_assurance_case.v1.json +676 -0
  64. core_runtime/data/schemas/core/policy_lifecycle.v1.json +99 -0
  65. core_runtime/data/schemas/core/retention_manifest.v1.json +53 -0
  66. core_runtime/data/schemas/core/reversibility_policy.v1.json +107 -0
  67. core_runtime/data/schemas/core/rule_anchor_batch.v1.json +93 -0
  68. core_runtime/data/schemas/core/rule_anchor_chain_evidence.v1.json +56 -0
  69. core_runtime/data/schemas/core/rule_approval.v1.json +49 -0
  70. core_runtime/data/schemas/core/rule_approval_request.v1.json +42 -0
  71. core_runtime/data/schemas/core/state_transition.v1.json +115 -0
  72. core_runtime/data/schemas/core/task_closeout.v1.json +47 -0
  73. core_runtime/data/schemas/core/template_promotion_candidate.v1.json +83 -0
  74. core_runtime/data/schemas/core/unsigned_rule_anchor_deployment.v1.json +106 -0
  75. core_runtime/data/schemas/core/unsigned_rule_anchor_transaction.v1.json +116 -0
  76. core_runtime/tooling/__init__.py +48 -0
  77. core_runtime/tooling/bump_version.py +900 -0
  78. core_runtime/tooling/contract_preflight.py +293 -0
  79. core_runtime/tooling/create_domain.py +254 -0
  80. core_runtime/tooling/diagnostics.py +129 -0
  81. core_runtime/tooling/doctor.py +482 -0
  82. core_runtime/tooling/file_inventory.py +182 -0
  83. core_runtime/tooling/json_checks.py +100 -0
  84. core_runtime/tooling/release_check.py +1017 -0
  85. core_runtime/tooling/repair_artifact_paths.py +458 -0
  86. core_runtime/tooling/report_writer.py +176 -0
  87. core_runtime/tooling/repository_inventory.py +399 -0
  88. core_runtime/tooling/safety_checks.py +172 -0
  89. core_runtime/tooling/sync_template.py +303 -0
  90. core_runtime/tooling/validation.py +507 -0
  91. core_runtime/tooling/version_inventory.py +256 -0
  92. core_runtime_engine-11.5.1.dist-info/METADATA +35 -0
  93. core_runtime_engine-11.5.1.dist-info/RECORD +96 -0
  94. core_runtime_engine-11.5.1.dist-info/WHEEL +5 -0
  95. core_runtime_engine-11.5.1.dist-info/entry_points.txt +2 -0
  96. core_runtime_engine-11.5.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,303 @@
1
+ """Dry-run-first template synchronization planning for CORE tooling."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass, field
6
+ from pathlib import Path
7
+ from typing import Any
8
+
9
+ from core_runtime.tooling.create_domain import DomainScaffolder
10
+ from core_runtime.tooling.diagnostics import DiagnosticCollection
11
+
12
+
13
+ @dataclass(frozen=True)
14
+ class SyncTemplateItem:
15
+ """A planned template sync artifact."""
16
+
17
+ kind: str
18
+ name: str
19
+ path: str
20
+ status: str
21
+ details: dict[str, Any] = field(default_factory=dict)
22
+
23
+ def to_dict(self) -> dict[str, Any]:
24
+ result = {
25
+ "kind": self.kind,
26
+ "name": self.name,
27
+ "path": self.path,
28
+ "status": self.status,
29
+ }
30
+ if self.details:
31
+ result["details"] = self.details
32
+ return result
33
+
34
+
35
+ @dataclass
36
+ class SyncTemplateReport:
37
+ """Normalized report for `core-runtime sync-template`."""
38
+
39
+ tool: str
40
+ command: str
41
+ status: str
42
+ mutation_performed: bool = False
43
+ summary: dict[str, Any] = field(default_factory=dict)
44
+ selection: dict[str, Any] | None = None
45
+ items: list[SyncTemplateItem] = field(default_factory=list)
46
+ diagnostics: DiagnosticCollection = field(default_factory=DiagnosticCollection)
47
+
48
+ def to_dict(self) -> dict[str, Any]:
49
+ counts = self.diagnostics.count_by_severity()
50
+ summary = dict(self.summary)
51
+ summary.setdefault("info", counts["info"])
52
+ summary.setdefault("warning", counts["warning"])
53
+ summary.setdefault("error", counts["error"])
54
+ summary.setdefault("blocked", counts["blocked"])
55
+ return {
56
+ "tool": self.tool,
57
+ "command": self.command,
58
+ "status": self.status,
59
+ "mutation_performed": self.mutation_performed,
60
+ "summary": summary,
61
+ "selection": self.selection,
62
+ "items": [item.to_dict() for item in self.items],
63
+ "diagnostics": [d.to_dict() for d in self.diagnostics.diagnostics],
64
+ }
65
+
66
+ def to_markdown(self) -> str:
67
+ counts = self.diagnostics.count_by_severity()
68
+ summary = dict(self.summary)
69
+ summary.setdefault("info", counts["info"])
70
+ summary.setdefault("warning", counts["warning"])
71
+ summary.setdefault("error", counts["error"])
72
+ summary.setdefault("blocked", counts["blocked"])
73
+ lines: list[str] = []
74
+ lines.append("# CORE sync-template plan")
75
+ lines.append("")
76
+ lines.append("## Summary")
77
+ lines.append("")
78
+ lines.append("| Metric | Value |")
79
+ lines.append("|--------|-------|")
80
+ lines.append("| Tool | {0} |".format(self.tool))
81
+ lines.append("| Command | {0} |".format(self.command))
82
+ lines.append("| Status | {0} |".format(self.status.upper()))
83
+ lines.append("| Mutation Performed | No |")
84
+ lines.append("| Items | {0} |".format(summary.get("item_count", len(self.items))))
85
+ lines.append("| Info | {0} |".format(counts["info"]))
86
+ lines.append("| Warning | {0} |".format(counts["warning"]))
87
+ lines.append("| Error | {0} |".format(counts["error"]))
88
+ lines.append("| Blocked | {0} |".format(counts["blocked"]))
89
+ lines.append("")
90
+
91
+ if self.selection is not None:
92
+ lines.append("## Selection")
93
+ lines.append("")
94
+ for key, value in self.selection.items():
95
+ lines.append("- **{0}**: {1}".format(key, value))
96
+ lines.append("")
97
+
98
+ if self.items:
99
+ lines.append("## Planned Changes")
100
+ lines.append("")
101
+ lines.append("| Kind | Name | Path | Status |")
102
+ lines.append("|------|------|------|--------|")
103
+ for item in self.items:
104
+ lines.append("| {0} | {1} | {2} | {3} |".format(item.kind, item.name, item.path, item.status))
105
+ lines.append("")
106
+
107
+ if self.diagnostics.diagnostics:
108
+ lines.append("## Diagnostics")
109
+ lines.append("")
110
+ lines.append("| Severity | Code | Path | Message |")
111
+ lines.append("|----------|------|------|---------|")
112
+ for diagnostic in self.diagnostics.diagnostics:
113
+ path = diagnostic.path or "-"
114
+ message = diagnostic.message.replace("|", "\\|")
115
+ lines.append(
116
+ "| {0} | {1} | {2} | {3} |".format(
117
+ diagnostic.severity.value.upper(),
118
+ diagnostic.code,
119
+ path,
120
+ message,
121
+ )
122
+ )
123
+ lines.append("")
124
+
125
+ return "\n".join(lines)
126
+
127
+
128
+ class TemplateSyncPlanner:
129
+ """Compare existing domains against a canonical scaffold template."""
130
+
131
+ def __init__(self, repo_root: Path):
132
+ self.repo_root = repo_root
133
+ self.scaffolder = DomainScaffolder(repo_root)
134
+
135
+ def build_plan(
136
+ self,
137
+ domain: str | None = None,
138
+ all_domains: bool = False,
139
+ template: str = "generic",
140
+ diagnostics: DiagnosticCollection | None = None,
141
+ ) -> SyncTemplateReport:
142
+ diagnostics = diagnostics or DiagnosticCollection()
143
+ if not domain and not all_domains:
144
+ diagnostics.add_blocked(
145
+ code="core.sync_template.mode_required",
146
+ message="sync-template requires --domain or --all",
147
+ path="sync-template",
148
+ expected="--domain <name> or --all",
149
+ actual="missing mode",
150
+ )
151
+ return SyncTemplateReport(
152
+ tool="core-runtime sync-template",
153
+ command="sync-template",
154
+ status="blocked",
155
+ summary={"mode": "missing", "item_count": 0},
156
+ selection={"mode": "missing"},
157
+ diagnostics=diagnostics,
158
+ )
159
+
160
+ domain_names = self._domain_names(domain=domain, all_domains=all_domains)
161
+ if not domain_names:
162
+ diagnostics.add_blocked(
163
+ code="core.sync_template.domain_missing",
164
+ message="No domains available for template sync",
165
+ path="core_runtime/domains",
166
+ expected="at least one domain",
167
+ actual="empty",
168
+ )
169
+ return SyncTemplateReport(
170
+ tool="core-runtime sync-template",
171
+ command=self._command(domain=domain, all_domains=all_domains),
172
+ status="blocked",
173
+ summary={"mode": "missing", "item_count": 0},
174
+ selection={"mode": "missing"},
175
+ diagnostics=diagnostics,
176
+ )
177
+
178
+ items: list[SyncTemplateItem] = []
179
+ additions = 0
180
+ preserved = 0
181
+ collisions = 0
182
+ for domain_name in domain_names:
183
+ plan_items, domain_additions, domain_preserved, domain_collisions = self._plan_domain(
184
+ domain_name, template, diagnostics
185
+ )
186
+ items.extend(plan_items)
187
+ additions += domain_additions
188
+ preserved += domain_preserved
189
+ collisions += domain_collisions
190
+
191
+ status = "pass"
192
+ if collisions:
193
+ status = "blocked"
194
+ elif additions or preserved:
195
+ status = "warning"
196
+
197
+ return SyncTemplateReport(
198
+ tool="core-runtime sync-template",
199
+ command=self._command(domain=domain, all_domains=all_domains),
200
+ status=status,
201
+ summary={
202
+ "mode": "all" if all_domains else "domain",
203
+ "item_count": len(items),
204
+ "planned_additions": additions,
205
+ "preserved_custom": preserved,
206
+ "collisions": collisions,
207
+ "template": template,
208
+ },
209
+ selection={"domain": domain, "all": all_domains, "template": template},
210
+ items=items,
211
+ diagnostics=diagnostics,
212
+ )
213
+
214
+ def _domain_names(self, domain: str | None, all_domains: bool) -> list[str]:
215
+ domains_dir = self.repo_root / "core_runtime" / "domains"
216
+ if all_domains:
217
+ if not domains_dir.is_dir():
218
+ return []
219
+ return sorted(
220
+ path.name
221
+ for path in domains_dir.iterdir()
222
+ if path.is_dir() and not path.name.startswith("__")
223
+ )
224
+ if domain is None:
225
+ return []
226
+ return [domain]
227
+
228
+ def _plan_domain(
229
+ self,
230
+ domain_name: str,
231
+ template: str,
232
+ diagnostics: DiagnosticCollection,
233
+ ) -> tuple[list[SyncTemplateItem], int, int, int]:
234
+ expected_plan, _, _ = self.scaffolder._plan_items(domain_name, template)
235
+ expected_paths = {Path(item.path).as_posix() for item in expected_plan}
236
+ domain_dir = self.repo_root / "core_runtime" / "domains" / domain_name
237
+ items: list[SyncTemplateItem] = []
238
+ additions = 0
239
+ preserved = 0
240
+ collisions = 0
241
+
242
+ if not domain_dir.exists():
243
+ collisions += 1
244
+ diagnostics.add_blocked(
245
+ code="core.sync_template.domain_missing",
246
+ message="Domain not found for template sync",
247
+ path=str(domain_dir.relative_to(self.repo_root)),
248
+ expected="existing domain directory",
249
+ actual="missing",
250
+ )
251
+ items.append(
252
+ SyncTemplateItem(
253
+ kind="domain",
254
+ name=domain_name,
255
+ path=str(domain_dir.relative_to(self.repo_root)),
256
+ status="blocked",
257
+ details={"reason": "domain_missing"},
258
+ )
259
+ )
260
+ return items, additions, preserved, collisions
261
+
262
+ actual_files = sorted(
263
+ path for path in domain_dir.rglob("*") if path.is_file() and "__pycache__" not in path.parts
264
+ )
265
+ actual_paths = {path.relative_to(self.repo_root).as_posix() for path in actual_files}
266
+
267
+ for item in expected_plan:
268
+ exists = item.details.get("exists", False)
269
+ if exists:
270
+ preserved += 1
271
+ status = "preserved"
272
+ else:
273
+ additions += 1
274
+ status = "planned_addition"
275
+ items.append(
276
+ SyncTemplateItem(
277
+ kind=item.kind,
278
+ name=item.name,
279
+ path=item.path,
280
+ status=status,
281
+ details=item.details,
282
+ )
283
+ )
284
+
285
+ custom_paths = sorted(actual_paths - expected_paths)
286
+ for rel_path in custom_paths:
287
+ preserved += 1
288
+ items.append(
289
+ SyncTemplateItem(
290
+ kind="custom_file",
291
+ name=Path(rel_path).name,
292
+ path=rel_path,
293
+ status="preserved",
294
+ details={"reason": "custom_domain_file"},
295
+ )
296
+ )
297
+
298
+ return items, additions, preserved, collisions
299
+
300
+ def _command(self, domain: str | None, all_domains: bool) -> str:
301
+ if all_domains:
302
+ return "sync-template --all --dry-run"
303
+ return "sync-template --domain {0} --dry-run".format(domain or "")