agent-lifecycle-kit 1.50.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 (227) hide show
  1. agent_lifecycle/__init__.py +5 -0
  2. agent_lifecycle/__main__.py +5 -0
  3. agent_lifecycle/_version.py +3 -0
  4. agent_lifecycle/adapter_sessions/__init__.py +41 -0
  5. agent_lifecycle/adapter_sessions/contracts.py +133 -0
  6. agent_lifecycle/adapter_sessions/env.py +44 -0
  7. agent_lifecycle/adapter_sessions/launcher.py +101 -0
  8. agent_lifecycle/adapter_sessions/process.py +39 -0
  9. agent_lifecycle/adapter_sessions/redaction.py +30 -0
  10. agent_lifecycle/adapter_sessions/session_store.py +64 -0
  11. agent_lifecycle/adapter_sessions/task_intake.py +450 -0
  12. agent_lifecycle/adapter_sessions/workflow_bridge.py +154 -0
  13. agent_lifecycle/audit/__init__.py +67 -0
  14. agent_lifecycle/audit/bug_forensics.py +94 -0
  15. agent_lifecycle/audit/implementation.py +516 -0
  16. agent_lifecycle/audit/ownership.py +119 -0
  17. agent_lifecycle/audit/proof_integrity.py +814 -0
  18. agent_lifecycle/audit/review_verdict.py +116 -0
  19. agent_lifecycle/changesets/__init__.py +5 -0
  20. agent_lifecycle/changesets/git.py +35 -0
  21. agent_lifecycle/cli/__init__.py +5 -0
  22. agent_lifecycle/cli/adapter.py +360 -0
  23. agent_lifecycle/cli/dispatch.py +1220 -0
  24. agent_lifecycle/cli/followup.py +89 -0
  25. agent_lifecycle/cli/main.py +41 -0
  26. agent_lifecycle/cli/metrics_parser.py +49 -0
  27. agent_lifecycle/cli/parsers.py +618 -0
  28. agent_lifecycle/cli/policy.py +101 -0
  29. agent_lifecycle/cli/progress_hooks.py +117 -0
  30. agent_lifecycle/cli/worktree.py +74 -0
  31. agent_lifecycle/compiler/__init__.py +17 -0
  32. agent_lifecycle/compiler/small_model_packets.py +322 -0
  33. agent_lifecycle/compiler/task_packets.py +229 -0
  34. agent_lifecycle/context/__init__.py +20 -0
  35. agent_lifecycle/context/episode_retrieval.py +30 -0
  36. agent_lifecycle/context/external_memory.py +71 -0
  37. agent_lifecycle/context/profiles.py +104 -0
  38. agent_lifecycle/context/rendering.py +226 -0
  39. agent_lifecycle/contracts/__init__.py +25 -0
  40. agent_lifecycle/contracts/adapter_contract_schemas.py +130 -0
  41. agent_lifecycle/contracts/adapter_event_schemas.py +118 -0
  42. agent_lifecycle/contracts/adapter_session_schemas.py +130 -0
  43. agent_lifecycle/contracts/adapter_task_schemas.py +90 -0
  44. agent_lifecycle/contracts/audit_schemas.py +133 -0
  45. agent_lifecycle/contracts/bug_forensics_schemas.py +400 -0
  46. agent_lifecycle/contracts/canonical.py +55 -0
  47. agent_lifecycle/contracts/compatibility.py +242 -0
  48. agent_lifecycle/contracts/context_model_schemas.py +265 -0
  49. agent_lifecycle/contracts/core_schemas.py +252 -0
  50. agent_lifecycle/contracts/cross_check_schemas.py +121 -0
  51. agent_lifecycle/contracts/errors.py +26 -0
  52. agent_lifecycle/contracts/evidence_import_schemas.py +152 -0
  53. agent_lifecycle/contracts/host_capability_schemas.py +64 -0
  54. agent_lifecycle/contracts/import_dialect_schemas.py +166 -0
  55. agent_lifecycle/contracts/metric_schemas.py +315 -0
  56. agent_lifecycle/contracts/paths.py +31 -0
  57. agent_lifecycle/contracts/plan_contract_schemas.py +148 -0
  58. agent_lifecycle/contracts/policy_schemas.py +350 -0
  59. agent_lifecycle/contracts/progress_bridge_schemas.py +114 -0
  60. agent_lifecycle/contracts/progress_hook_schemas.py +119 -0
  61. agent_lifecycle/contracts/proof_integrity_schemas.py +240 -0
  62. agent_lifecycle/contracts/release_contract_schemas.py +476 -0
  63. agent_lifecycle/contracts/review_mesh_recommendation_schemas.py +64 -0
  64. agent_lifecycle/contracts/review_mesh_schemas.py +222 -0
  65. agent_lifecycle/contracts/review_quality_schemas.py +109 -0
  66. agent_lifecycle/contracts/runner_schemas.py +91 -0
  67. agent_lifecycle/contracts/runner_worktree_schemas.py +389 -0
  68. agent_lifecycle/contracts/sandbox_schemas.py +159 -0
  69. agent_lifecycle/contracts/schema_builders.py +23 -0
  70. agent_lifecycle/contracts/schemas.py +93 -0
  71. agent_lifecycle/contracts/status_goal_schemas.py +469 -0
  72. agent_lifecycle/contracts/task_template_schemas.py +96 -0
  73. agent_lifecycle/contracts/usage_export_schemas.py +68 -0
  74. agent_lifecycle/diagnostics/__init__.py +17 -0
  75. agent_lifecycle/diagnostics/bundles.py +124 -0
  76. agent_lifecycle/diagnostics/readiness.py +733 -0
  77. agent_lifecycle/evidence_index/__init__.py +39 -0
  78. agent_lifecycle/evidence_index/core.py +272 -0
  79. agent_lifecycle/evidence_index/episode_index.py +329 -0
  80. agent_lifecycle/evidence_index/external_context.py +276 -0
  81. agent_lifecycle/followup/__init__.py +23 -0
  82. agent_lifecycle/followup/records.py +404 -0
  83. agent_lifecycle/freeze/__init__.py +5 -0
  84. agent_lifecycle/freeze/locks.py +23 -0
  85. agent_lifecycle/goal/__init__.py +15 -0
  86. agent_lifecycle/goal/records.py +244 -0
  87. agent_lifecycle/goal/view.py +109 -0
  88. agent_lifecycle/host_protocol/__init__.py +65 -0
  89. agent_lifecycle/host_protocol/acp_capability.py +195 -0
  90. agent_lifecycle/host_protocol/capabilities.py +268 -0
  91. agent_lifecycle/host_protocol/contracts.py +214 -0
  92. agent_lifecycle/host_protocol/event_capture.py +390 -0
  93. agent_lifecycle/host_protocol/events.py +196 -0
  94. agent_lifecycle/host_protocol/inspection.py +194 -0
  95. agent_lifecycle/host_protocol/inspection_common.py +310 -0
  96. agent_lifecycle/host_protocol/inspection_cursor.py +164 -0
  97. agent_lifecycle/host_protocol/inspection_gemini_cli.py +163 -0
  98. agent_lifecycle/host_protocol/inspection_hermes.py +161 -0
  99. agent_lifecycle/host_protocol/inspection_kimi_code.py +169 -0
  100. agent_lifecycle/host_protocol/inspection_opencode.py +147 -0
  101. agent_lifecycle/host_protocol/inspection_qwen_code.py +143 -0
  102. agent_lifecycle/host_protocol/receipts.py +58 -0
  103. agent_lifecycle/host_protocol/scaffold.py +329 -0
  104. agent_lifecycle/host_protocol/validation.py +229 -0
  105. agent_lifecycle/imports/__init__.py +76 -0
  106. agent_lifecycle/imports/agentskills_profile.py +54 -0
  107. agent_lifecycle/imports/bmad_profile.py +49 -0
  108. agent_lifecycle/imports/constitution_adr.py +91 -0
  109. agent_lifecycle/imports/dialect_profiles.py +121 -0
  110. agent_lifecycle/imports/external_agent.py +28 -0
  111. agent_lifecycle/imports/external_dialects.py +486 -0
  112. agent_lifecycle/imports/external_workflow.py +28 -0
  113. agent_lifecycle/imports/multi_markdown.py +111 -0
  114. agent_lifecycle/imports/openspec_profile.py +49 -0
  115. agent_lifecycle/imports/planning.py +536 -0
  116. agent_lifecycle/imports/spec_kit_profile.py +49 -0
  117. agent_lifecycle/imports/spec_kitty_profile.py +49 -0
  118. agent_lifecycle/metrics/__init__.py +60 -0
  119. agent_lifecycle/metrics/cost_collection.py +315 -0
  120. agent_lifecycle/metrics/costs.py +203 -0
  121. agent_lifecycle/metrics/outcome_index.py +330 -0
  122. agent_lifecycle/metrics/phase_resources.py +208 -0
  123. agent_lifecycle/metrics/recommendations.py +507 -0
  124. agent_lifecycle/metrics/regression_signals.py +64 -0
  125. agent_lifecycle/metrics/usage_export.py +390 -0
  126. agent_lifecycle/model_routing/__init__.py +19 -0
  127. agent_lifecycle/model_routing/profiles.py +323 -0
  128. agent_lifecycle/model_routing/receipts.py +140 -0
  129. agent_lifecycle/model_routing/resolver.py +566 -0
  130. agent_lifecycle/neutrality/__init__.py +12 -0
  131. agent_lifecycle/neutrality/__main__.py +6 -0
  132. agent_lifecycle/neutrality/authority.py +265 -0
  133. agent_lifecycle/neutrality/canonical.py +28 -0
  134. agent_lifecycle/neutrality/cli.py +294 -0
  135. agent_lifecycle/neutrality/ed25519.py +124 -0
  136. agent_lifecycle/neutrality/errors.py +89 -0
  137. agent_lifecycle/neutrality/gate.py +269 -0
  138. agent_lifecycle/neutrality/paths.py +92 -0
  139. agent_lifecycle/neutrality/policy.py +76 -0
  140. agent_lifecycle/neutrality/receipt.py +135 -0
  141. agent_lifecycle/neutrality/scanner.py +310 -0
  142. agent_lifecycle/neutrality/test_runner.py +116 -0
  143. agent_lifecycle/planning/__init__.py +47 -0
  144. agent_lifecycle/planning/acceptance_markdown.py +159 -0
  145. agent_lifecycle/planning/completeness.py +362 -0
  146. agent_lifecycle/planning/continuity.py +255 -0
  147. agent_lifecycle/planning/templates.py +294 -0
  148. agent_lifecycle/planning/tiering.py +87 -0
  149. agent_lifecycle/planning/validation.py +72 -0
  150. agent_lifecycle/policy/__init__.py +37 -0
  151. agent_lifecycle/policy/adaptive_lifecycle.py +416 -0
  152. agent_lifecycle/policy/apply.py +44 -0
  153. agent_lifecycle/policy/proposals.py +189 -0
  154. agent_lifecycle/policy/quality_floor.py +144 -0
  155. agent_lifecycle/policy/runtime_receipts.py +160 -0
  156. agent_lifecycle/py.typed +1 -0
  157. agent_lifecycle/quality/__init__.py +89 -0
  158. agent_lifecycle/quality/bug_forensics.py +727 -0
  159. agent_lifecycle/quality/bug_forensics_advisor.py +88 -0
  160. agent_lifecycle/quality/bug_forensics_recipes.py +239 -0
  161. agent_lifecycle/quality/cross_check.py +437 -0
  162. agent_lifecycle/quality/failure_classification.py +318 -0
  163. agent_lifecycle/quality/packs.py +265 -0
  164. agent_lifecycle/reporting/__init__.py +37 -0
  165. agent_lifecycle/reporting/change_summary.py +156 -0
  166. agent_lifecycle/reporting/event_feed.py +101 -0
  167. agent_lifecycle/reporting/progress_bridge.py +153 -0
  168. agent_lifecycle/reporting/progress_hooks.py +161 -0
  169. agent_lifecycle/reporting/progress_terminal.py +95 -0
  170. agent_lifecycle/reporting/progress_view.py +284 -0
  171. agent_lifecycle/reporting/status_view.py +125 -0
  172. agent_lifecycle/reporting/usage_export.py +59 -0
  173. agent_lifecycle/review/__init__.py +5 -0
  174. agent_lifecycle/review/validation.py +29 -0
  175. agent_lifecycle/review_mesh/__init__.py +83 -0
  176. agent_lifecycle/review_mesh/assignments.py +160 -0
  177. agent_lifecycle/review_mesh/contracts.py +685 -0
  178. agent_lifecycle/review_mesh/operator_templates.py +320 -0
  179. agent_lifecycle/review_mesh/quorum.py +38 -0
  180. agent_lifecycle/review_mesh/recommendation.py +487 -0
  181. agent_lifecycle/review_mesh/results.py +98 -0
  182. agent_lifecycle/review_mesh/synthesis.py +102 -0
  183. agent_lifecycle/runner/__init__.py +47 -0
  184. agent_lifecycle/runner/attempt_snapshots.py +244 -0
  185. agent_lifecycle/runner/core.py +653 -0
  186. agent_lifecycle/runner/sandbox_receipts.py +628 -0
  187. agent_lifecycle/specification/__init__.py +23 -0
  188. agent_lifecycle/specification/completion_check.py +135 -0
  189. agent_lifecycle/specification/completion_gate.py +501 -0
  190. agent_lifecycle/specification/completion_signal.py +75 -0
  191. agent_lifecycle/specification/validation.py +48 -0
  192. agent_lifecycle/workflow/__init__.py +79 -0
  193. agent_lifecycle/workflow/artifacts.py +74 -0
  194. agent_lifecycle/workflow/budget_decisions.py +370 -0
  195. agent_lifecycle/workflow/budget_policy.py +140 -0
  196. agent_lifecycle/workflow/budget_receipts.py +70 -0
  197. agent_lifecycle/workflow/bug_forensics_gates.py +284 -0
  198. agent_lifecycle/workflow/controller.py +45 -0
  199. agent_lifecycle/workflow/events.py +50 -0
  200. agent_lifecycle/workflow/final_proof_integrity.py +74 -0
  201. agent_lifecycle/workflow/finalization.py +422 -0
  202. agent_lifecycle/workflow/gates.py +185 -0
  203. agent_lifecycle/workflow/implementation_audit_gate.py +126 -0
  204. agent_lifecycle/workflow/leases.py +220 -0
  205. agent_lifecycle/workflow/lineage.py +108 -0
  206. agent_lifecycle/workflow/managed_runner.py +167 -0
  207. agent_lifecycle/workflow/model_usage.py +106 -0
  208. agent_lifecycle/workflow/next_action.py +86 -0
  209. agent_lifecycle/workflow/operation_kernel.py +98 -0
  210. agent_lifecycle/workflow/plan_adoption.py +439 -0
  211. agent_lifecycle/workflow/query.py +52 -0
  212. agent_lifecycle/workflow/review_mesh_gate.py +93 -0
  213. agent_lifecycle/workflow/reviews.py +168 -0
  214. agent_lifecycle/workflow/run_transitions.py +163 -0
  215. agent_lifecycle/workflow/sandbox_policy.py +214 -0
  216. agent_lifecycle/workflow/selectors.py +57 -0
  217. agent_lifecycle/workflow/state.py +130 -0
  218. agent_lifecycle/workflow/task_transitions.py +421 -0
  219. agent_lifecycle/worktree/__init__.py +17 -0
  220. agent_lifecycle/worktree/isolation.py +407 -0
  221. agent_lifecycle_kit-1.50.1.dist-info/METADATA +201 -0
  222. agent_lifecycle_kit-1.50.1.dist-info/RECORD +227 -0
  223. agent_lifecycle_kit-1.50.1.dist-info/WHEEL +5 -0
  224. agent_lifecycle_kit-1.50.1.dist-info/entry_points.txt +3 -0
  225. agent_lifecycle_kit-1.50.1.dist-info/licenses/LICENSE +201 -0
  226. agent_lifecycle_kit-1.50.1.dist-info/licenses/NOTICE +5 -0
  227. agent_lifecycle_kit-1.50.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,407 @@
1
+ """Provider-neutral worktree isolation receipts."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from datetime import UTC, datetime
6
+ from typing import Any
7
+
8
+ from agent_lifecycle.contracts import LifecycleError, canonical_digest
9
+ from agent_lifecycle.contracts.paths import is_under_repo_path, normalize_repo_path
10
+
11
+ LINEAGE_KEYS = ("runId", "packageId", "planRevision", "planDigest", "sourceRevision")
12
+ OUTCOMES = {"PASS", "FAILED", "BLOCKED"}
13
+ CLEANUP_DECISIONS = {"PRESERVE", "REMOVE"}
14
+ WRITEBACK_DECISIONS = {"APPLY", "DISCARD"}
15
+
16
+
17
+ def validate_worktree_policy(policy: dict[str, Any]) -> dict[str, Any]:
18
+ if not isinstance(policy, dict):
19
+ raise LifecycleError("invalid-worktree-policy", "worktree policy must be an object")
20
+ if policy.get("schemaVersion") != "agent-worktree-isolation-policy.v1":
21
+ raise LifecycleError("invalid-worktree-policy", "worktree policy schemaVersion is unsupported")
22
+ worktree_root = normalize_repo_path(_required_string(policy.get("worktreeRoot"), label="worktreeRoot"), label="worktreeRoot")
23
+ allowed_write_roots = _path_list(policy.get("allowedWriteRoots", []), label="allowedWriteRoots", allow_empty=True)
24
+ preserve_failed = _required_bool(policy.get("preserveFailedAttempts"), label="preserveFailedAttempts")
25
+ cleanup_requires_operator = _required_bool(policy.get("cleanupRequiresOperator"), label="cleanupRequiresOperator")
26
+ body = {
27
+ "schemaVersion": "agent-worktree-isolation-policy-validation.v1",
28
+ "status": "PASS",
29
+ "worktreeRoot": worktree_root,
30
+ "allowedWriteRoots": allowed_write_roots,
31
+ "preserveFailedAttempts": preserve_failed,
32
+ "cleanupRequiresOperator": cleanup_requires_operator,
33
+ "policyDigest": canonical_digest(policy),
34
+ }
35
+ return body
36
+
37
+
38
+ def build_attempt_isolation_receipt(
39
+ workflow_state: dict[str, Any],
40
+ *,
41
+ task_id: str,
42
+ attempt: int,
43
+ policy: dict[str, Any],
44
+ worktree_path: str,
45
+ baseline_ref: str,
46
+ baseline_sha: str,
47
+ changed_files: list[str],
48
+ outcome: str,
49
+ cleanup_decision: str | None = None,
50
+ operator_authorization: dict[str, Any] | None = None,
51
+ reason: str,
52
+ ) -> dict[str, Any]:
53
+ validation = validate_worktree_policy(policy)
54
+ task = _workflow_task(workflow_state, task_id)
55
+ decision = cleanup_decision or "PRESERVE"
56
+ body = {
57
+ "schemaVersion": "agent-worktree-attempt-receipt.v1",
58
+ "status": "PASS",
59
+ "lineage": _lineage_from_workflow(workflow_state),
60
+ "taskId": task_id,
61
+ "attempt": _positive_int(attempt, label="attempt"),
62
+ "policyDigest": validation["policyDigest"],
63
+ "isolation": {
64
+ "strategy": "git-worktree",
65
+ "worktreePath": normalize_repo_path(worktree_path, label="worktreePath"),
66
+ "worktreeRoot": validation["worktreeRoot"],
67
+ "baselineRef": _required_string(baseline_ref, label="baselineRef"),
68
+ "baselineSha": _required_string(baseline_sha, label="baselineSha"),
69
+ "mainWorktreeClean": True,
70
+ "allowedWriteRoots": _allowed_roots(validation["allowedWriteRoots"], task),
71
+ "changedFiles": _path_list(changed_files, label="changedFiles", allow_empty=True),
72
+ },
73
+ "outcome": _enum(outcome, OUTCOMES, label="outcome"),
74
+ "cleanup": {
75
+ "decision": _enum(decision, CLEANUP_DECISIONS, label="cleanupDecision"),
76
+ "operatorAuthorization": operator_authorization,
77
+ "reason": reason,
78
+ },
79
+ "createdAt": _now_iso(),
80
+ }
81
+ result = validate_attempt_isolation_receipt(body, workflow_state=workflow_state, policy=policy)
82
+ return {**body, "receiptDigest": result["receiptDigest"]}
83
+
84
+
85
+ def validate_attempt_isolation_receipt(
86
+ receipt: dict[str, Any],
87
+ *,
88
+ workflow_state: dict[str, Any] | None = None,
89
+ policy: dict[str, Any] | None = None,
90
+ ) -> dict[str, Any]:
91
+ if not isinstance(receipt, dict):
92
+ raise LifecycleError("invalid-worktree-receipt", "worktree receipt must be an object")
93
+ if receipt.get("schemaVersion") != "agent-worktree-attempt-receipt.v1":
94
+ raise LifecycleError("invalid-worktree-receipt", "worktree receipt schemaVersion is unsupported")
95
+ if receipt.get("status") != "PASS":
96
+ raise LifecycleError("worktree-isolation-not-pass", "worktree isolation receipt must be PASS")
97
+ lineage = _lineage(receipt.get("lineage"))
98
+ if workflow_state is not None:
99
+ _validate_workflow_binding(lineage, workflow_state)
100
+ task_id = _required_string(receipt.get("taskId"), label="taskId")
101
+ attempt = _positive_int(receipt.get("attempt"), label="attempt")
102
+ isolation = _isolation(receipt.get("isolation"))
103
+ cleanup = _cleanup(receipt.get("cleanup"))
104
+ if policy is not None:
105
+ policy_validation = validate_worktree_policy(policy)
106
+ if receipt.get("policyDigest") != policy_validation["policyDigest"]:
107
+ raise LifecycleError("worktree-policy-mismatch", "worktree receipt policyDigest mismatch")
108
+ if not is_under_repo_path(isolation["worktreePath"], policy_validation["worktreeRoot"]):
109
+ raise LifecycleError("worktree-path-outside-root", "worktree path is outside policy root")
110
+ if policy_validation["cleanupRequiresOperator"] and cleanup["decision"] == "REMOVE" and cleanup["operatorAuthorization"] is None:
111
+ raise LifecycleError("worktree-cleanup-authorization-required", "worktree cleanup requires operator authorization")
112
+ if policy_validation["preserveFailedAttempts"] and receipt.get("outcome") == "FAILED" and cleanup["decision"] == "REMOVE":
113
+ authorization = cleanup["operatorAuthorization"]
114
+ if not isinstance(authorization, dict) or authorization.get("allowFailedAttemptRemoval") is not True:
115
+ raise LifecycleError("worktree-failed-attempt-preserved", "failed attempt cleanup requires explicit removal authorization")
116
+ if workflow_state is not None:
117
+ task = _workflow_task(workflow_state, task_id)
118
+ _validate_changed_files_in_scope(isolation["changedFiles"], _allowed_roots(isolation["allowedWriteRoots"], task))
119
+ stored_digest = receipt.get("receiptDigest")
120
+ receipt_digest = _receipt_digest(receipt)
121
+ if stored_digest is not None and stored_digest != receipt_digest:
122
+ raise LifecycleError("worktree-receipt-digest-mismatch", "worktree receiptDigest does not match receipt")
123
+ body = {
124
+ "schemaVersion": "agent-worktree-attempt-receipt-validation.v1",
125
+ "status": "PASS",
126
+ "lineage": lineage,
127
+ "taskId": task_id,
128
+ "attempt": attempt,
129
+ "outcome": receipt.get("outcome"),
130
+ "cleanupDecision": cleanup["decision"],
131
+ "receiptDigest": receipt_digest,
132
+ }
133
+ return body
134
+
135
+
136
+ def build_worktree_writeback_receipt(
137
+ workflow_state: dict[str, Any],
138
+ *,
139
+ task_id: str,
140
+ attempt: int,
141
+ overlay_digest: str,
142
+ changed_files: list[str],
143
+ decision: str,
144
+ operator_authorization: dict[str, Any],
145
+ reason: str,
146
+ applied_files: list[str] | None = None,
147
+ discarded_files: list[str] | None = None,
148
+ isolation_receipt_digest: str | None = None,
149
+ ) -> dict[str, Any]:
150
+ selected_decision = _enum(decision, WRITEBACK_DECISIONS, label="decision.action")
151
+ changed = _path_list(changed_files, label="changedFiles", allow_empty=True)
152
+ applied = _path_list(
153
+ applied_files if applied_files is not None else (changed if selected_decision == "APPLY" else []),
154
+ label="appliedFiles",
155
+ allow_empty=True,
156
+ )
157
+ discarded = _path_list(
158
+ discarded_files if discarded_files is not None else (changed if selected_decision == "DISCARD" else []),
159
+ label="discardedFiles",
160
+ allow_empty=True,
161
+ )
162
+ body = {
163
+ "schemaVersion": "agent-worktree-writeback-receipt.v1",
164
+ "status": "PASS",
165
+ "lineage": _lineage_from_workflow(workflow_state),
166
+ "taskId": task_id,
167
+ "attempt": _positive_int(attempt, label="attempt"),
168
+ "boundary": {
169
+ "kind": "isolated-overlay",
170
+ "isolationReceiptDigest": isolation_receipt_digest,
171
+ "overlayDigest": _digest(overlay_digest, label="overlayDigest"),
172
+ "runtimeAgnostic": True,
173
+ },
174
+ "decision": {
175
+ "action": selected_decision,
176
+ "operatorAuthorization": _operator_authorization(operator_authorization),
177
+ "reason": _required_string(reason, label="decision.reason"),
178
+ },
179
+ "changedFiles": changed,
180
+ "appliedFiles": applied,
181
+ "discardedFiles": discarded,
182
+ "createdAt": _now_iso(),
183
+ "productionPromotionClaimed": False,
184
+ }
185
+ result = validate_worktree_writeback_receipt(body, workflow_state=workflow_state)
186
+ return {**body, "receiptDigest": result["receiptDigest"]}
187
+
188
+
189
+ def validate_worktree_writeback_receipt(
190
+ receipt: dict[str, Any],
191
+ *,
192
+ workflow_state: dict[str, Any] | None = None,
193
+ ) -> dict[str, Any]:
194
+ if not isinstance(receipt, dict):
195
+ raise LifecycleError("invalid-worktree-writeback-receipt", "worktree write-back receipt must be an object")
196
+ if receipt.get("schemaVersion") != "agent-worktree-writeback-receipt.v1":
197
+ raise LifecycleError("invalid-worktree-writeback-receipt", "worktree write-back schemaVersion is unsupported")
198
+ if receipt.get("status") != "PASS":
199
+ raise LifecycleError("worktree-writeback-not-pass", "worktree write-back receipt must be PASS")
200
+ lineage = _lineage(receipt.get("lineage"))
201
+ if workflow_state is not None:
202
+ _validate_workflow_binding(lineage, workflow_state)
203
+ task_id = _required_string(receipt.get("taskId"), label="taskId")
204
+ attempt = _positive_int(receipt.get("attempt"), label="attempt")
205
+ boundary = _writeback_boundary(receipt.get("boundary"))
206
+ decision = _writeback_decision(receipt.get("decision"))
207
+ changed = _path_list(receipt.get("changedFiles", []), label="changedFiles", allow_empty=True)
208
+ applied = _path_list(receipt.get("appliedFiles", []), label="appliedFiles", allow_empty=True)
209
+ discarded = _path_list(receipt.get("discardedFiles", []), label="discardedFiles", allow_empty=True)
210
+ _validate_writeback_paths(changed, applied=applied, discarded=discarded, decision=decision["action"])
211
+ if workflow_state is not None:
212
+ task = _workflow_task(workflow_state, task_id)
213
+ _validate_changed_files_in_scope(changed, _allowed_roots([], task))
214
+ if receipt.get("productionPromotionClaimed") is not False:
215
+ raise LifecycleError("worktree-writeback-production-claim", "write-back receipt must not claim production promotion")
216
+ stored_digest = receipt.get("receiptDigest")
217
+ receipt_digest = _receipt_digest(receipt)
218
+ if stored_digest is not None and stored_digest != receipt_digest:
219
+ raise LifecycleError("worktree-writeback-receipt-digest-mismatch", "worktree write-back receiptDigest does not match receipt")
220
+ return {
221
+ "schemaVersion": "agent-worktree-writeback-receipt-validation.v1",
222
+ "status": "PASS",
223
+ "lineage": lineage,
224
+ "taskId": task_id,
225
+ "attempt": attempt,
226
+ "decision": decision["action"],
227
+ "overlayDigest": boundary["overlayDigest"],
228
+ "changedFileCount": len(changed),
229
+ "appliedFileCount": len(applied),
230
+ "discardedFileCount": len(discarded),
231
+ "receiptDigest": receipt_digest,
232
+ }
233
+
234
+
235
+ def _isolation(value: Any) -> dict[str, Any]:
236
+ if not isinstance(value, dict):
237
+ raise LifecycleError("invalid-worktree-receipt", "worktree isolation is required")
238
+ strategy = value.get("strategy")
239
+ if strategy != "git-worktree":
240
+ raise LifecycleError("invalid-worktree-receipt", "worktree isolation strategy is unsupported")
241
+ if value.get("mainWorktreeClean") is not True:
242
+ raise LifecycleError("worktree-main-dirty", "main worktree must be clean before isolated attempt")
243
+ return {
244
+ "strategy": strategy,
245
+ "worktreePath": normalize_repo_path(_required_string(value.get("worktreePath"), label="isolation.worktreePath"), label="isolation.worktreePath"),
246
+ "worktreeRoot": normalize_repo_path(_required_string(value.get("worktreeRoot"), label="isolation.worktreeRoot"), label="isolation.worktreeRoot"),
247
+ "baselineRef": _required_string(value.get("baselineRef"), label="isolation.baselineRef"),
248
+ "baselineSha": _required_string(value.get("baselineSha"), label="isolation.baselineSha"),
249
+ "allowedWriteRoots": _path_list(value.get("allowedWriteRoots", []), label="isolation.allowedWriteRoots", allow_empty=True),
250
+ "changedFiles": _path_list(value.get("changedFiles", []), label="isolation.changedFiles", allow_empty=True),
251
+ }
252
+
253
+
254
+ def _cleanup(value: Any) -> dict[str, Any]:
255
+ if not isinstance(value, dict):
256
+ raise LifecycleError("invalid-worktree-receipt", "worktree cleanup is required")
257
+ decision = _enum(value.get("decision"), CLEANUP_DECISIONS, label="cleanup.decision")
258
+ authorization = value.get("operatorAuthorization")
259
+ if authorization is not None and not isinstance(authorization, dict):
260
+ raise LifecycleError("invalid-worktree-receipt", "operatorAuthorization must be an object")
261
+ _required_string(value.get("reason"), label="cleanup.reason")
262
+ return {"decision": decision, "operatorAuthorization": authorization}
263
+
264
+
265
+ def _writeback_boundary(value: Any) -> dict[str, Any]:
266
+ if not isinstance(value, dict):
267
+ raise LifecycleError("invalid-worktree-writeback-receipt", "write-back boundary is required")
268
+ if value.get("kind") != "isolated-overlay":
269
+ raise LifecycleError("invalid-worktree-writeback-receipt", "write-back boundary kind is unsupported")
270
+ if value.get("runtimeAgnostic") is not True:
271
+ raise LifecycleError("invalid-worktree-writeback-receipt", "write-back boundary must be runtime agnostic")
272
+ isolation_digest = value.get("isolationReceiptDigest")
273
+ if isolation_digest is not None:
274
+ _digest(isolation_digest, label="boundary.isolationReceiptDigest")
275
+ return {
276
+ "kind": "isolated-overlay",
277
+ "isolationReceiptDigest": isolation_digest,
278
+ "overlayDigest": _digest(value.get("overlayDigest"), label="boundary.overlayDigest"),
279
+ "runtimeAgnostic": True,
280
+ }
281
+
282
+
283
+ def _writeback_decision(value: Any) -> dict[str, Any]:
284
+ if not isinstance(value, dict):
285
+ raise LifecycleError("invalid-worktree-writeback-receipt", "write-back decision is required")
286
+ action = _enum(value.get("action"), WRITEBACK_DECISIONS, label="decision.action")
287
+ authorization = _operator_authorization(value.get("operatorAuthorization"))
288
+ _required_string(value.get("reason"), label="decision.reason")
289
+ return {"action": action, "operatorAuthorization": authorization}
290
+
291
+
292
+ def _operator_authorization(value: Any) -> dict[str, Any]:
293
+ if not isinstance(value, dict):
294
+ raise LifecycleError("invalid-worktree-writeback-receipt", "operatorAuthorization must be an object")
295
+ if not isinstance(value.get("operatorIdentityHash"), str) or not value["operatorIdentityHash"]:
296
+ raise LifecycleError("invalid-worktree-writeback-receipt", "operatorIdentityHash is required")
297
+ return dict(value)
298
+
299
+
300
+ def _validate_writeback_paths(
301
+ changed: list[str],
302
+ *,
303
+ applied: list[str],
304
+ discarded: list[str],
305
+ decision: str,
306
+ ) -> None:
307
+ changed_set = set(changed)
308
+ applied_set = set(applied)
309
+ discarded_set = set(discarded)
310
+ overlap = sorted(applied_set.intersection(discarded_set))
311
+ if overlap:
312
+ raise LifecycleError("worktree-writeback-path-overlap", "applied and discarded paths overlap", {"paths": overlap})
313
+ outside = sorted(applied_set.union(discarded_set) - changed_set)
314
+ if outside:
315
+ raise LifecycleError("worktree-writeback-path-outside-overlay", "write-back path is outside overlay changes", {"paths": outside})
316
+ if decision == "DISCARD" and applied:
317
+ raise LifecycleError("worktree-writeback-discard-applied-paths", "discard decision must not apply files")
318
+ if decision == "APPLY" and changed and not applied:
319
+ raise LifecycleError("worktree-writeback-apply-empty", "apply decision must apply at least one changed file")
320
+
321
+
322
+ def _validate_changed_files_in_scope(changed_files: list[str], allowed_roots: list[str]) -> None:
323
+ for path in changed_files:
324
+ if not any(is_under_repo_path(path, root) for root in allowed_roots):
325
+ raise LifecycleError("worktree-write-scope-violation", "worktree changed file is outside task write scope", {"path": path, "allowedWriteRoots": allowed_roots})
326
+
327
+
328
+ def _allowed_roots(policy_roots: list[str], task: dict[str, Any]) -> list[str]:
329
+ task_writes = _path_list(task.get("writes", []), label="task.writes", allow_empty=False)
330
+ if not policy_roots:
331
+ return task_writes
332
+ return [root for root in policy_roots if any(is_under_repo_path(root, task_root) or is_under_repo_path(task_root, root) for task_root in task_writes)] or task_writes
333
+
334
+
335
+ def _workflow_task(workflow_state: dict[str, Any], task_id: str) -> dict[str, Any]:
336
+ for task in workflow_state.get("tasks", []):
337
+ if isinstance(task, dict) and task.get("id") == task_id:
338
+ return task
339
+ raise LifecycleError("worktree-task-not-found", "worktree task is missing from workflow state", {"taskId": task_id})
340
+
341
+
342
+ def _lineage_from_workflow(state: dict[str, Any]) -> dict[str, Any]:
343
+ return {key: state.get(key) for key in LINEAGE_KEYS}
344
+
345
+
346
+ def _lineage(value: Any) -> dict[str, Any]:
347
+ if not isinstance(value, dict):
348
+ raise LifecycleError("invalid-worktree-receipt", "worktree lineage is required")
349
+ result = {key: value.get(key) for key in LINEAGE_KEYS}
350
+ for key, item in result.items():
351
+ if key == "planRevision":
352
+ _positive_int(item, label="lineage.planRevision")
353
+ elif not isinstance(item, str) or not item:
354
+ raise LifecycleError("invalid-worktree-receipt", f"worktree lineage.{key} is required")
355
+ return result
356
+
357
+
358
+ def _validate_workflow_binding(lineage: dict[str, Any], workflow_state: dict[str, Any]) -> None:
359
+ for key in LINEAGE_KEYS:
360
+ if lineage.get(key) != workflow_state.get(key):
361
+ raise LifecycleError("worktree-lineage-mismatch", f"worktree {key} mismatch")
362
+
363
+
364
+ def _path_list(value: Any, *, label: str, allow_empty: bool) -> list[str]:
365
+ if not isinstance(value, list) or not all(isinstance(item, str) and item for item in value):
366
+ raise LifecycleError("invalid-worktree-receipt", f"{label} must be a list of non-empty paths")
367
+ if not value and not allow_empty:
368
+ raise LifecycleError("invalid-worktree-receipt", f"{label} must not be empty")
369
+ return [normalize_repo_path(item, label=label) for item in value]
370
+
371
+
372
+ def _enum(value: Any, allowed: set[str], *, label: str) -> str:
373
+ if value not in allowed:
374
+ raise LifecycleError("invalid-worktree-receipt", f"{label} is unsupported")
375
+ return str(value)
376
+
377
+
378
+ def _required_string(value: Any, *, label: str) -> str:
379
+ if not isinstance(value, str) or not value:
380
+ raise LifecycleError("invalid-worktree-receipt", f"{label} is required")
381
+ return value
382
+
383
+
384
+ def _required_bool(value: Any, *, label: str) -> bool:
385
+ if not isinstance(value, bool):
386
+ raise LifecycleError("invalid-worktree-policy", f"{label} must be boolean")
387
+ return value
388
+
389
+
390
+ def _digest(value: Any, *, label: str) -> str:
391
+ if not isinstance(value, str) or len(value) != 64:
392
+ raise LifecycleError("invalid-worktree-writeback-receipt", f"{label} must be a sha256 digest")
393
+ return value
394
+
395
+
396
+ def _positive_int(value: Any, *, label: str) -> int:
397
+ if not isinstance(value, int) or isinstance(value, bool) or value < 1:
398
+ raise LifecycleError("invalid-worktree-receipt", f"{label} must be a positive integer")
399
+ return value
400
+
401
+
402
+ def _receipt_digest(receipt: dict[str, Any]) -> str:
403
+ return canonical_digest({key: value for key, value in receipt.items() if key != "receiptDigest"})
404
+
405
+
406
+ def _now_iso() -> str:
407
+ return datetime.now(UTC).replace(microsecond=0).isoformat().replace("+00:00", "Z")
@@ -0,0 +1,201 @@
1
+ Metadata-Version: 2.4
2
+ Name: agent-lifecycle-kit
3
+ Version: 1.50.1
4
+ Summary: Provider-neutral lifecycle control layer that helps coding agents plan, execute, validate, and prove software tasks to completion.
5
+ Author: Agent Lifecycle Kit contributors
6
+ License: Apache-2.0
7
+ Keywords: adapter-conformance,agent-lifecycle,agent-workflows,agents,ai-agents,audit,coding-agents,lifecycle,model-routing,planning,sdd,software-delivery,task-orchestration,workflow
8
+ Classifier: Development Status :: 5 - Production/Stable
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: Apache Software License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Typing :: Typed
16
+ Requires-Python: <3.14,>=3.11
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ License-File: NOTICE
20
+ Dynamic: license-file
21
+
22
+ <p align="center">
23
+ <img src="docs/assets/agent-lifecycle-kit-banner.svg?v=2026-08-02-1" alt="Agent Lifecycle Kit - plan, execute, prove, finish agent work" width="100%">
24
+ </p>
25
+
26
+ # Agent Lifecycle Kit
27
+
28
+ [![License: Apache-2.0](https://img.shields.io/badge/license-Apache--2.0-green.svg)](LICENSE)
29
+ [![Release](https://img.shields.io/github/v/release/avksp/agent-lifecycle-kit?label=release)](https://github.com/avksp/agent-lifecycle-kit/releases)
30
+ ![Python](https://img.shields.io/badge/python-3.11--3.13-blue.svg)
31
+
32
+ **Agent Lifecycle Kit (ALK)** gives coding agents one delivery workflow from
33
+ request to verified result. It turns a user task into a reviewed specification,
34
+ an approved plan, bounded implementation work, review, and final proof, so
35
+ agents finish the job instead of stopping at a patch.
36
+
37
+ The workflow is provider-neutral. Codex, Claude Code, Qwen Code, Goose,
38
+ OpenInterpreter, Pi, Grok Build, or another CLI can follow the same lifecycle,
39
+ while provider commands, model choice, and secret handling stay in adapters or
40
+ host-local profiles.
41
+
42
+ ## Quick start
43
+
44
+ From a source checkout:
45
+
46
+ ```bash
47
+ python -m pip install -e .
48
+ agent-lifecycle version
49
+ agent-lifecycle diagnose --no-install-plans
50
+ agent-lifecycle adapter validate --descriptor adapters/codex/adapter.descriptor.json
51
+ ```
52
+
53
+ Package install, when available for the release:
54
+ `python -m pip install agent-lifecycle-kit==1.50.1`.
55
+
56
+ For a short walkthrough, use [Quickstart](docs/guides/quickstart.md) and the [Lifecycle cookbook](docs/guides/lifecycle-cookbook.md). For structure and positioning, see [System architecture](docs/architecture/system-architecture.md) and [Project comparison](docs/reference/project-comparison.md). Russian documentation starts at [Документация на русском](docs/ru/README.md).
57
+
58
+ ## What it gives you
59
+
60
+ - A finish-oriented lifecycle: plan, execute, review, and prove the result.
61
+ - One process for different CLIs: adapter-specific commands stay outside the
62
+ core, and new adapters can be added without changing lifecycle schemas.
63
+ - Small-model friendly packets: compact context, clear next actions, and
64
+ deterministic checks for local or cheaper models.
65
+ - Quality without overengineering: optional profiles turn on only when risk or
66
+ task type requires them.
67
+ - Usage visibility: tokens, time, and resource counters are native; monetary
68
+ cost is optional and only used when a metered host reports it.
69
+ - Read-only progress and managed sessions: host UIs can show lifecycle state,
70
+ attested tokens and Git-style change counters; `adapter task start` accepts
71
+ task text, Markdown or frozen run requests while preserving review/freeze
72
+ boundaries.
73
+
74
+ ## Feature areas
75
+
76
+ ### Plan and execute
77
+
78
+ - Reviewed specification and plan flow before implementation starts.
79
+ - Deterministic task packets for splitting work across agents.
80
+ - Execution records capture completion checks, blockers, retries, and final
81
+ proof; missing required evidence fails the step.
82
+ - Ready-made task templates cover bug fixes, idea-to-PR flow, PR review,
83
+ merge-conflict repair, and release-readiness work.
84
+
85
+ ### Quality and proof
86
+
87
+ - Implementation audits compare results with the frozen plan and acceptance
88
+ evidence.
89
+ - For explicit bug and regression repair, the optional Bug Forensics profile
90
+ records reproduction, fingerprint, failure class, hypotheses, minimal patch,
91
+ regression proof, and reusable recipes.
92
+ - Optional proof-integrity evidence for high-risk final proofs: stable findings,
93
+ root-cause digests, fix-impact receipts, and hash chains.
94
+ - Cross-checks and runtime-policy receipts are opt-in controls; plans can
95
+ require proof for an external system update before acceptance.
96
+ - Optional Review Mesh covers leader-draft review, parallel research synthesis
97
+ and audit panels. The advisor can suggest a mode; `review-mesh prepare`
98
+ creates local reviewer packets; opted-in plans can require
99
+ assignment/result/synthesis/quorum receipts, but ALK core does not start hosts.
100
+
101
+ ### Routing and resource control
102
+
103
+ - Compact context profiles, small-model packets, objective snapshots, and
104
+ local quality-cost learning help choose the lightest safe mode.
105
+ - Phase resource measurements reuse the usage export envelope for tokens,
106
+ duration, and resource counters without mandatory monetary accounting.
107
+ - Usage/session exports include tokens, resources, receipt digests, and optional
108
+ host-reported `cost_usd`.
109
+
110
+ ### Security and containment
111
+
112
+ - Neutrality filters use host-supplied deny rules to keep local paths, secrets, trust roots, and signing keys out of portable artifacts.
113
+ - Host env files require explicit `--host-env-allow`; receipts store redacted metadata, not secret values or private env-file paths.
114
+ - Imports, diagnostics, and usage exports redact local paths and common secret markers before validation.
115
+ - Sandbox receipts separate runtime filesystem, network, process, and environment containment from git write-scope.
116
+ - Release security gates reject leaked local paths, credentials, and unsupported adapter or production claims.
117
+
118
+ ### Adapters and interop
119
+
120
+ - Adapter contracts keep host-specific projections separate from lifecycle
121
+ schemas.
122
+ - New CLI hosts start as adapters: descriptor, command projection, environment
123
+ boundary, and verification evidence live outside the lifecycle core.
124
+ - Adapter capability checks and progress bridge support compare live receipts
125
+ and display lifecycle state without automatic maturity changes.
126
+ - Import mappers and issue-to-spec intake treat external workflows, agent
127
+ dialects, and tickets as untrusted draft inputs.
128
+ - Lightweight episode retrieval over receipt/session summaries keeps digest
129
+ provenance and explicit `chainVerified` or `chainUnchecked` state.
130
+
131
+ ### Operations
132
+
133
+ - Runner recovery receipts cover attempt snapshot, restore, abandon, selected
134
+ attempt, worker lease, and heartbeat state.
135
+ - Read-only diagnostics, event feeds, managed lifecycle steps, progress watch
136
+ receipts, and change summaries inspect checkout and workflow state without
137
+ model calls.
138
+
139
+ ## Daily flow
140
+
141
+ Spec -> frozen plan -> bounded work -> implementation audit -> final proof.
142
+ Core commands cover specification, plan, workflow, audit, adapters, imports, metrics,
143
+ policy, diagnostics, runner state, and adapter task intake. See [CLI reference](docs/reference/cli.md) and [Source of truth](docs/reference/source-of-truth.md).
144
+
145
+ ## Adapter maturity
146
+
147
+ `EXPERIMENTAL` means offline checks exist; bounded live host conformance and
148
+ usage/resource calibration are still required before `VERIFIED`. The verified
149
+ claim is host-specific and also requires accepted redacted evidence and
150
+ lifecycle final proof for the tested host range. New hosts can be added as
151
+ adapters first and promoted only for the exact CLI/version/provider binding that
152
+ has evidence. Monetary accounting is required only for metered modes.
153
+
154
+ | Host | Current claim |
155
+ | --- | --- |
156
+ | Codex | `VERIFIED` for Codex CLI 0.145.0. Public Plugins Directory approval is not claimed. |
157
+ | Claude Code | `VERIFIED` for Claude Code 2.1.220. Official directory approval is not claimed. |
158
+ | OpenCode | `VERIFIED` for OpenCode CLI 1.18.9. npm publication is not claimed. |
159
+ | Hermes | `VERIFIED` for Hermes Agent v0.19.0. Public directory approval is not claimed. |
160
+ | Qwen Code | `VERIFIED` for Qwen Code 0.21.0 on the tested host-local provider/model binding. Public package approval is not claimed. |
161
+ | Cursor | `EXPERIMENTAL`; local safe inspection passed, but accepted live receipts are incomplete. |
162
+ | Gemini CLI | `EXPERIMENTAL`; local live canary is blocked by the current Gemini Code Assist tier. |
163
+ | Goose | `VERIFIED` for Goose 1.45.0 on the tested host-local provider/model binding. Public directory approval is not claimed. |
164
+ | Kimi Code | `EXPERIMENTAL`; live proof requires a configured provider and model alias. |
165
+ | Grok Build | `VERIFIED` for Grok Build 0.2.117 on the tested host-local provider/model binding. Public directory approval is not claimed. |
166
+ | OpenInterpreter | `VERIFIED` for `interpreter` 0.0.34 on the tested host-local provider/model binding. Public directory approval is not claimed. |
167
+ | Pi | `VERIFIED` for Pi 0.83.0 on the tested host-local provider/model binding. Public directory approval is not claimed. |
168
+
169
+ Adapter installation and maturity details live in [Adapter install](docs/adapters/install.md) and [Adapter support matrix](docs/adapters/support-matrix.md).
170
+
171
+ ## Contract map
172
+
173
+ The public lifecycle surface is schema-backed. Full stable schema ids, compatibility rules, runner recovery, cross-check, Review Mesh, Bug Forensics and usage export details are listed in [Public contracts](docs/reference/public-contracts.md).
174
+
175
+ ## Design boundaries
176
+
177
+ - The core stays provider-neutral. Concrete host commands and model bindings
178
+ belong to adapters or host-local profiles.
179
+ - New CLIs are integrated through adapters: descriptor, command projection,
180
+ environment boundary, and verification evidence. The lifecycle schemas remain
181
+ stable while host support grows.
182
+ - Small models get compact packets, deterministic checks, and explicit
183
+ next-action lists instead of long narrative state.
184
+ - Larger models keep the same gates; better reasoning does not bypass evidence.
185
+ - Public release claims are limited to tracked source files and redacted
186
+ evidence summaries.
187
+ - External dialect imports and retrieved episodes are context aids only; they
188
+ do not replace reviewed ALK source-of-truth artifacts.
189
+ - Optional cross-check, Review Mesh and runner recovery receipts add evidence
190
+ only when a task or plan requests them; they are not default multi-model execution.
191
+
192
+ ## Documentation
193
+
194
+ - Start: [English documentation](docs/README.md), [Русская документация](docs/ru/README.md), [Quickstart](docs/guides/quickstart.md), [Lifecycle cookbook](docs/guides/lifecycle-cookbook.md), and [Code review workflows](docs/guides/code-review-workflows.md).
195
+ - Planning and adapters: [Issue to specification drafts](docs/guides/issue-to-spec.md), [Adapter install](docs/adapters/install.md), and [Adapter support matrix](docs/adapters/support-matrix.md).
196
+ - Reference: [System architecture](docs/architecture/system-architecture.md), [CLI reference](docs/reference/cli.md), [Source of truth](docs/reference/source-of-truth.md), [Managed lifecycle runner](docs/reference/managed-lifecycle-runner.md), [Managed adapter sessions](docs/reference/managed-adapter-sessions.md), [Implementation audit](docs/reference/implementation-audit.md), [Plan completeness](docs/reference/plan-completeness.md), [Public contracts](docs/reference/public-contracts.md), and [Readiness diagnostics](docs/reference/readiness-diagnostics.md).
197
+ - Quality and resources: [Small-model packets](docs/reference/small-model-packets.md), [model routing](docs/reference/model-routing.md), [adaptive policy](docs/reference/adaptive-lifecycle-policy.md), [quality-cost learning](docs/reference/quality-cost-learning.md), [lifecycle cost accounting](docs/reference/lifecycle-cost.md), [Usage export](docs/reference/usage-export.md), and [Evidence integrity](docs/reference/evidence-integrity.md).
198
+ - Profiles and operations: [Read-only status views](docs/reference/read-only-status-view.md), [Adapter progress bridge](docs/reference/automatic-progress-bridge.md), [Sandbox boundaries](docs/reference/sandbox-boundaries.md), [Import mappers](docs/reference/import-mappers.md), [Episode retrieval](docs/reference/episode-retrieval.md), [Runner recovery](docs/reference/runner-recovery.md), [Cross-check profile](docs/reference/cross-check-profile.md), [Review Mesh](docs/reference/review-mesh.md), [Bug Forensics profile](docs/reference/bug-forensics.md), and [Bug Forensics context budget](docs/reference/bug-forensics-context-budget.md).
199
+ - Release assets: [Task templates](templates/tasks/README.md) and [Release security](docs/security/release-security.md).
200
+
201
+ Apache-2.0. See [LICENSE](LICENSE).