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,1220 @@
1
+ """Root CLI dispatch handlers."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ from pathlib import Path
7
+ from typing import Any
8
+
9
+ from agent_lifecycle import __version__
10
+ from agent_lifecycle.audit import (
11
+ build_final_implementation_audit,
12
+ build_implementation_audit_report,
13
+ build_ownership_report,
14
+ require_review_verdict_pass,
15
+ validate_review_verdict,
16
+ )
17
+ from agent_lifecycle.audit.ownership import report_has_category
18
+ from agent_lifecycle.changesets import changed_files
19
+ from agent_lifecycle.compiler import compile_small_model_packets, compile_task_packets
20
+ from agent_lifecycle.contracts import LifecycleError, canonical_digest, read_json_object, write_json_create
21
+ from agent_lifecycle.contracts.compatibility import (
22
+ build_contract_policy,
23
+ require_contract_policy_pass,
24
+ validate_contract_policy,
25
+ )
26
+ from agent_lifecycle.contracts.schemas import get_schema, list_schemas
27
+ from agent_lifecycle.context import check_context, load_context_profile, render_context
28
+ from agent_lifecycle.context.external_memory import build_episode_retrieval_with_external_context, import_external_memory_context
29
+ from agent_lifecycle.diagnostics import build_diagnostic_bundle, build_readiness_report
30
+ from agent_lifecycle.evidence_index import (
31
+ build_evidence_index,
32
+ require_evidence_index_pass,
33
+ require_evidence_search_pass,
34
+ search_evidence_index,
35
+ validate_evidence_index,
36
+ )
37
+ from agent_lifecycle.freeze import verify_plan_lock
38
+ from agent_lifecycle.cli.adapter import dispatch_adapter
39
+ from agent_lifecycle.cli.followup import dispatch_followup
40
+ from agent_lifecycle.cli.policy import dispatch_policy
41
+ from agent_lifecycle.cli.progress_hooks import maybe_emit_workflow_progress_hook, validate_workflow_progress_hook_request
42
+ from agent_lifecycle.cli.worktree import dispatch_worktree
43
+ from agent_lifecycle.goal import build_goal_progress_view, build_objective_snapshot, update_goal_record, validate_goal_record
44
+ from agent_lifecycle.imports import (
45
+ bmad_profile,
46
+ external_dialect_registry,
47
+ import_external_dialect,
48
+ import_markdown_collection,
49
+ import_planning_input,
50
+ openspec_profile,
51
+ require_external_import_pass,
52
+ require_import_validation_pass,
53
+ require_skill_proposal_pass,
54
+ spec_kit_profile,
55
+ spec_kitty_profile,
56
+ validate_external_import_result,
57
+ validate_import_result,
58
+ validate_skill_improvement_proposal,
59
+ )
60
+ from agent_lifecycle.model_routing import (
61
+ resolve_model_route,
62
+ validate_host_model_profile,
63
+ validate_model_routing_profile,
64
+ validate_usage_receipt,
65
+ )
66
+ from agent_lifecycle.metrics import (
67
+ build_quality_cost_signals,
68
+ build_task_outcome_index,
69
+ build_usage_export,
70
+ build_lifecycle_cost_summary,
71
+ build_lifecycle_recommendation_summary,
72
+ generate_lifecycle_cost_report,
73
+ recommend_from_quality_cost_signals,
74
+ recommend_lifecycle_mode,
75
+ require_lifecycle_cost_pass,
76
+ require_lifecycle_recommendation_pass,
77
+ require_usage_export_pass,
78
+ validate_lifecycle_cost_report,
79
+ validate_usage_export,
80
+ )
81
+ from agent_lifecycle.planning import (
82
+ load_plan_completeness_profile,
83
+ build_plan_snapshot,
84
+ build_task_template_library,
85
+ reconcile_plan_snapshot,
86
+ require_task_template_validation_pass,
87
+ render_plan_handoff,
88
+ require_reconciliation_pass,
89
+ require_repository_references_pass,
90
+ resolve_sdd_tier,
91
+ validate_acceptance_checklist,
92
+ validate_plan_completeness,
93
+ validate_plan_manifest,
94
+ validate_repository_references,
95
+ validate_task_template_library,
96
+ )
97
+ from agent_lifecycle.quality import (
98
+ build_bug_forensics_recipe_library,
99
+ build_default_quality_pack,
100
+ require_behavior_checks_pass,
101
+ require_bug_forensics_recipe_pass,
102
+ require_quality_pack_pass,
103
+ run_behavior_checks,
104
+ validate_bug_forensics_recipe_library,
105
+ validate_quality_pack,
106
+ )
107
+ from agent_lifecycle.review_mesh import (
108
+ build_quorum_from_synthesis,
109
+ build_review_mesh_assignment_packet,
110
+ build_review_mesh_profile,
111
+ import_review_mesh_result,
112
+ list_review_mesh_operator_templates,
113
+ parse_reviewer_spec,
114
+ prepare_review_mesh_operator_packets,
115
+ recommend_review_mesh_for_intake,
116
+ recommend_review_mesh_for_plan_manifest,
117
+ recommend_review_mesh_for_text,
118
+ require_review_mesh_profile_pass,
119
+ require_review_mesh_recommendation_pass,
120
+ source_from_handoff,
121
+ source_from_intake,
122
+ source_from_manifest,
123
+ synthesize_review_mesh_results,
124
+ validate_review_mesh_profile,
125
+ validate_review_mesh_recommendation,
126
+ )
127
+ from agent_lifecycle.reporting import (
128
+ build_change_summary_receipt,
129
+ build_lifecycle_progress_view,
130
+ build_lifecycle_progress_watch,
131
+ build_progress_bridge_receipt,
132
+ build_status_view,
133
+ build_workflow_event_feed,
134
+ render_progress_bridge_terminal,
135
+ render_goal_view_terminal,
136
+ render_progress_terminal,
137
+ render_usage_export_json,
138
+ render_usage_export_table,
139
+ )
140
+ from agent_lifecycle.runner import (
141
+ build_runner_snapshot,
142
+ initialize_runner_state,
143
+ load_runner_policy,
144
+ load_runner_state,
145
+ request_runner_stop,
146
+ resume_runner,
147
+ transition_runner,
148
+ validate_runner_state,
149
+ )
150
+ from agent_lifecycle.runner.core import write_runner_state, write_runner_state_create
151
+ from agent_lifecycle.specification import build_completion_gate_receipt, validate_specification
152
+ from agent_lifecycle.workflow import (
153
+ accept_task,
154
+ adopt_plan,
155
+ apply_budget_decision,
156
+ block_run,
157
+ commit_task_result,
158
+ finalize_run,
159
+ next_action,
160
+ pause_for_budget_decision,
161
+ resolve_blocker,
162
+ run_managed_lifecycle_step,
163
+ start_execution,
164
+ start_task,
165
+ status,
166
+ validate_budget_exceeded_policy,
167
+ )
168
+
169
+
170
+ def dispatch(args: argparse.Namespace, remainder: list[str]) -> dict[str, Any] | str | None:
171
+ if args.command == "version":
172
+ return {"schemaVersion": "agent-lifecycle-version.v1", "version": __version__}
173
+ if args.command == "schema":
174
+ if args.schema_command == "list":
175
+ return list_schemas()
176
+ if args.schema_command == "show":
177
+ return get_schema(args.schema_id)
178
+ if args.command == "contract":
179
+ return _dispatch_contract(args)
180
+ if args.command == "diagnose":
181
+ return build_readiness_report(
182
+ project_root=Path(args.project_root),
183
+ adapter_paths=[Path(item) for item in args.adapter] if args.adapter else None,
184
+ include_install_plans=not args.no_install_plans,
185
+ include_host_probes=args.include_host_probes,
186
+ timeout_seconds=args.timeout_seconds,
187
+ max_host_probes=args.max_host_probes,
188
+ context_profile=Path(args.context_profile) if args.context_profile else None,
189
+ model_profile=Path(args.model_profile) if args.model_profile else None,
190
+ adapter_baseline=Path(args.adapter_baseline) if args.adapter_baseline else None,
191
+ )
192
+ if args.command == "diagnostics":
193
+ return _dispatch_diagnostics(args)
194
+ if args.command == "evidence":
195
+ return _dispatch_evidence(args)
196
+ if args.command == "import":
197
+ return _dispatch_import(args)
198
+ if args.command == "quality":
199
+ return _dispatch_quality(args)
200
+ if args.command == "review-mesh":
201
+ return _dispatch_review_mesh(args)
202
+ if args.command == "report":
203
+ return _dispatch_report(args)
204
+ if args.command == "policy":
205
+ return dispatch_policy(args)
206
+ if args.command == "workflow":
207
+ return _dispatch_workflow(args)
208
+ if args.command == "audit":
209
+ return _dispatch_audit(args)
210
+ if args.command == "context":
211
+ return _dispatch_context(args)
212
+ if args.command == "goal":
213
+ return _dispatch_goal(args)
214
+ if args.command == "followup":
215
+ return dispatch_followup(args)
216
+ if args.command == "worktree":
217
+ return dispatch_worktree(args)
218
+ if args.command == "model":
219
+ return _dispatch_model(args)
220
+ if args.command == "metrics":
221
+ return _dispatch_metrics(args)
222
+ if args.command == "runner":
223
+ return _dispatch_runner(args)
224
+ if args.command == "tier":
225
+ return _dispatch_tier(args)
226
+ if args.command == "specification":
227
+ return _dispatch_specification(args)
228
+ if args.command == "plan":
229
+ return _dispatch_plan(args)
230
+ if args.command == "task":
231
+ return _dispatch_task(args)
232
+ if args.command == "adapter":
233
+ return dispatch_adapter(args)
234
+ raise LifecycleError(
235
+ "command-not-implemented",
236
+ f"{args.command} command group is reserved but not implemented in this build",
237
+ )
238
+
239
+
240
+ def _dispatch_diagnostics(args: argparse.Namespace) -> dict[str, Any]:
241
+ if args.diagnostics_command == "bundle":
242
+ payload = build_diagnostic_bundle(
243
+ project_root=Path(args.project_root),
244
+ artifact_paths=[Path(item) for item in args.artifact],
245
+ max_artifacts=args.max_artifacts,
246
+ max_input_bytes=args.max_input_bytes,
247
+ )
248
+ if args.out:
249
+ write_json_create(Path(args.out), payload)
250
+ return payload
251
+ raise LifecycleError("command-not-implemented", "diagnostics command is not implemented")
252
+
253
+
254
+ def _dispatch_contract(args: argparse.Namespace) -> dict[str, Any]:
255
+ if args.contract_command == "policy":
256
+ payload = build_contract_policy()
257
+ if args.out:
258
+ write_json_create(Path(args.out), payload)
259
+ return payload
260
+ if args.contract_command == "check":
261
+ policy = read_json_object(Path(args.policy), label="public contract policy") if args.policy else build_contract_policy()
262
+ return require_contract_policy_pass(validate_contract_policy(policy))
263
+ raise LifecycleError("command-not-implemented", "contract command is not implemented")
264
+
265
+
266
+ def _dispatch_evidence(args: argparse.Namespace) -> dict[str, Any]:
267
+ if args.evidence_command == "index":
268
+ payload = build_evidence_index(
269
+ Path(args.project_root),
270
+ list(args.artifact),
271
+ max_artifacts=args.max_artifacts,
272
+ max_input_bytes=args.max_input_bytes,
273
+ target_tokens=args.target_tokens,
274
+ )
275
+ require_evidence_index_pass(validate_evidence_index(payload))
276
+ require_evidence_index_pass(payload)
277
+ if args.out:
278
+ write_json_create(Path(args.out), payload)
279
+ return payload
280
+ if args.evidence_command == "search":
281
+ payload = search_evidence_index(
282
+ read_json_object(Path(args.index), label="evidence index"),
283
+ query=args.query or "",
284
+ max_results=args.max_results,
285
+ target_tokens=args.target_tokens,
286
+ )
287
+ require_evidence_search_pass(payload)
288
+ if args.out:
289
+ write_json_create(Path(args.out), payload)
290
+ return payload
291
+ raise LifecycleError("command-not-implemented", "evidence command is not implemented")
292
+
293
+
294
+ def _dispatch_import(args: argparse.Namespace) -> dict[str, Any]:
295
+ if args.import_command == "profile-list":
296
+ payload = external_dialect_registry()
297
+ if args.out:
298
+ write_json_create(Path(args.out), payload)
299
+ return payload
300
+ if args.import_command == "plan":
301
+ source = Path(args.source)
302
+ dialect_profile = _planning_import_profile(args.dialect, max_input_bytes=args.max_input_bytes, target_tokens=args.target_tokens)
303
+ if source.is_dir() or dialect_profile is not None:
304
+ payload = import_markdown_collection(
305
+ source,
306
+ package_id=args.package_id,
307
+ max_input_bytes=args.max_input_bytes,
308
+ target_tokens=args.target_tokens,
309
+ max_files=args.max_files,
310
+ dialect_profile=dialect_profile,
311
+ )
312
+ else:
313
+ payload = import_planning_input(
314
+ source,
315
+ package_id=args.package_id,
316
+ max_input_bytes=args.max_input_bytes,
317
+ target_tokens=args.target_tokens,
318
+ )
319
+ require_import_validation_pass(validate_import_result(payload))
320
+ if args.out:
321
+ write_json_create(Path(args.out), payload)
322
+ return payload
323
+ if args.import_command == "external":
324
+ payload = import_external_dialect(
325
+ Path(args.source),
326
+ family=args.family,
327
+ profile_id=args.profile,
328
+ package_id=args.package_id,
329
+ max_input_bytes=args.max_input_bytes,
330
+ target_tokens=args.target_tokens,
331
+ )
332
+ require_external_import_pass(validate_external_import_result(payload))
333
+ if args.out:
334
+ write_json_create(Path(args.out), payload)
335
+ return payload
336
+ if args.import_command == "check":
337
+ return require_import_validation_pass(validate_import_result(read_json_object(Path(args.candidate), label="planning import result")))
338
+ if args.import_command == "external-check":
339
+ return require_external_import_pass(validate_external_import_result(read_json_object(Path(args.candidate), label="external dialect import result")))
340
+ if args.import_command == "proposal-check":
341
+ return require_skill_proposal_pass(validate_skill_improvement_proposal(read_json_object(Path(args.proposal), label="skill proposal")))
342
+ raise LifecycleError("command-not-implemented", "import command is not implemented")
343
+
344
+
345
+ def _planning_import_profile(
346
+ dialect: str | None,
347
+ *,
348
+ max_input_bytes: int,
349
+ target_tokens: int,
350
+ ) -> dict[str, Any] | None:
351
+ if dialect is None:
352
+ return None
353
+ builders = {
354
+ "openspec": openspec_profile,
355
+ "spec-kit": spec_kit_profile,
356
+ "bmad": bmad_profile,
357
+ "spec-kitty": spec_kitty_profile,
358
+ }
359
+ return builders[dialect](max_input_bytes=max_input_bytes, target_tokens=target_tokens)
360
+
361
+
362
+ def _dispatch_quality(args: argparse.Namespace) -> dict[str, Any]:
363
+ if args.quality_command == "pack-check":
364
+ manifest = read_json_object(Path(args.manifest), label="quality pack") if args.manifest else build_default_quality_pack()
365
+ return require_quality_pack_pass(validate_quality_pack(manifest))
366
+ if args.quality_command == "behavior-check":
367
+ manifest = read_json_object(Path(args.manifest), label="quality pack") if args.manifest else build_default_quality_pack()
368
+ fixtures = [read_json_object(Path(item), label="behavior fixture") for item in args.fixture]
369
+ return require_behavior_checks_pass(run_behavior_checks(manifest, fixtures))
370
+ if args.quality_command == "template-list":
371
+ payload = build_task_template_library()
372
+ if args.out:
373
+ write_json_create(Path(args.out), payload)
374
+ return payload
375
+ if args.quality_command == "template-check":
376
+ payload = validate_task_template_library(project_root=Path(args.project_root), template_id=args.template_id)
377
+ require_task_template_validation_pass(payload)
378
+ if args.out:
379
+ write_json_create(Path(args.out), payload)
380
+ return payload
381
+ if args.quality_command == "bug-recipe-list":
382
+ payload = build_bug_forensics_recipe_library()
383
+ if args.out:
384
+ write_json_create(Path(args.out), payload)
385
+ return payload
386
+ if args.quality_command == "bug-recipe-check":
387
+ payload = validate_bug_forensics_recipe_library(recipe_id=args.recipe_id)
388
+ require_bug_forensics_recipe_pass(payload)
389
+ if args.out:
390
+ write_json_create(Path(args.out), payload)
391
+ return payload
392
+ raise LifecycleError("command-not-implemented", "quality command is not implemented")
393
+
394
+
395
+ def _dispatch_review_mesh(args: argparse.Namespace) -> dict[str, Any]:
396
+ if args.review_mesh_command == "template-list":
397
+ payload = list_review_mesh_operator_templates()
398
+ if args.out:
399
+ write_json_create(Path(args.out), payload)
400
+ return payload
401
+ if args.review_mesh_command == "profile":
402
+ budget_cap = _review_mesh_budget_cap(args)
403
+ payload = build_review_mesh_profile(
404
+ profile_id=args.profile_id,
405
+ modes=args.mode or None,
406
+ default_mode=args.default_mode,
407
+ budget_cap=budget_cap,
408
+ live_calls_allowed=args.allow_live_calls,
409
+ independence_required=args.require_independence,
410
+ independence_dimensions=args.independence_dimension or None,
411
+ reviewer_model_classes=args.reviewer_model_class or None,
412
+ )
413
+ require_review_mesh_profile_pass(validate_review_mesh_profile(payload))
414
+ if args.out:
415
+ write_json_create(Path(args.out), payload)
416
+ return payload
417
+ if args.review_mesh_command == "recommend":
418
+ if args.text is not None:
419
+ payload = recommend_review_mesh_for_text(
420
+ args.text,
421
+ sdd_tier=args.sdd_tier,
422
+ risk_flags=args.risk_flag,
423
+ )
424
+ elif args.file:
425
+ path = Path(args.file)
426
+ payload = recommend_review_mesh_for_text(
427
+ path.read_text(encoding="utf-8"),
428
+ source_label=path.name,
429
+ sdd_tier=args.sdd_tier,
430
+ risk_flags=args.risk_flag,
431
+ )
432
+ elif args.intake:
433
+ payload = recommend_review_mesh_for_intake(read_json_object(Path(args.intake), label="adapter task intake receipt"))
434
+ elif args.manifest:
435
+ payload = recommend_review_mesh_for_plan_manifest(read_json_object(Path(args.manifest), label="plan manifest"))
436
+ else:
437
+ raise LifecycleError("review-mesh-recommendation-source-missing", "one recommendation source is required")
438
+ require_review_mesh_recommendation_pass(validate_review_mesh_recommendation(payload))
439
+ if args.out:
440
+ write_json_create(Path(args.out), payload)
441
+ return payload
442
+ if args.review_mesh_command == "prepare":
443
+ if args.manifest:
444
+ source = source_from_manifest(read_json_object(Path(args.manifest), label="plan manifest"))
445
+ elif args.intake:
446
+ source = source_from_intake(read_json_object(Path(args.intake), label="adapter task intake receipt"))
447
+ elif args.handoff:
448
+ source = source_from_handoff(read_json_object(Path(args.handoff), label="plan handoff"))
449
+ else:
450
+ raise LifecycleError("review-mesh-prepare-source-missing", "one prepare source is required")
451
+ payload = prepare_review_mesh_operator_packets(
452
+ source=source,
453
+ template_id=args.template,
454
+ reviewers=[parse_reviewer_spec(spec) for spec in args.reviewer] if args.reviewer else None,
455
+ profile_id=args.profile_id,
456
+ phase=args.phase,
457
+ blocking=args.blocking,
458
+ evidence_ids=args.evidence_id,
459
+ out_dir=Path(args.out_dir) if args.out_dir else None,
460
+ )
461
+ if args.out:
462
+ write_json_create(Path(args.out), payload)
463
+ return payload
464
+ if args.review_mesh_command == "assign":
465
+ if args.manifest:
466
+ source = source_from_manifest(read_json_object(Path(args.manifest), label="plan manifest"))
467
+ elif args.intake:
468
+ source = source_from_intake(read_json_object(Path(args.intake), label="adapter task intake receipt"))
469
+ elif args.handoff:
470
+ source = source_from_handoff(read_json_object(Path(args.handoff), label="plan handoff"))
471
+ else:
472
+ raise LifecycleError("review-mesh-assignment-source-missing", "one assignment source is required")
473
+ profile = read_json_object(Path(args.profile), label="review mesh profile") if args.profile else build_review_mesh_profile(default_mode=args.mode, independence_required=False)
474
+ payload = build_review_mesh_assignment_packet(
475
+ source=source,
476
+ mode=args.mode,
477
+ phase=args.phase,
478
+ assignment_id=args.assignment_id,
479
+ reviewer_id=args.reviewer_id,
480
+ reviewer_role=args.reviewer_role,
481
+ reviewer_model_class=args.reviewer_model_class,
482
+ reviewer_host_identity_hash=args.reviewer_host_identity_hash,
483
+ reviewer_model_identity_hash=args.reviewer_model_identity_hash,
484
+ blocking=args.blocking,
485
+ profile=profile,
486
+ evidence_ids=args.evidence_id,
487
+ )
488
+ if args.out:
489
+ write_json_create(Path(args.out), payload)
490
+ return payload
491
+ if args.review_mesh_command == "import-result":
492
+ assignment_payload = read_json_object(Path(args.assignment), label="review mesh assignment")
493
+ assignment = assignment_payload.get("assignment") if isinstance(assignment_payload.get("assignment"), dict) else assignment_payload
494
+ payload = import_review_mesh_result(
495
+ profile=read_json_object(Path(args.profile), label="review mesh profile"),
496
+ assignment=assignment,
497
+ reviewer_output=read_json_object(Path(args.reviewer_output), label="reviewer output"),
498
+ allow_local_evidence_refs=args.allow_local_evidence_ref,
499
+ )
500
+ if args.out:
501
+ write_json_create(Path(args.out), payload)
502
+ return payload
503
+ if args.review_mesh_command == "synthesize":
504
+ payload = synthesize_review_mesh_results(
505
+ profile=read_json_object(Path(args.profile), label="review mesh profile"),
506
+ results=[read_json_object(Path(path), label="review mesh result") for path in args.result],
507
+ mode=args.mode,
508
+ accepted_finding_ids=args.accepted_finding_id,
509
+ rejected_finding_ids=args.rejected_finding_id,
510
+ )
511
+ if args.out:
512
+ write_json_create(Path(args.out), payload)
513
+ return payload
514
+ if args.review_mesh_command == "quorum":
515
+ profile = read_json_object(Path(args.profile), label="review mesh profile")
516
+ synthesis = read_json_object(Path(args.synthesis), label="review mesh synthesis")
517
+ payload = build_quorum_from_synthesis(
518
+ profile=profile,
519
+ synthesis=synthesis,
520
+ quorum_policy={"minReviewers": args.min_reviewers, "requiredRoles": args.required_role},
521
+ reviewer_roles=args.reviewer_role,
522
+ )
523
+ if args.out:
524
+ write_json_create(Path(args.out), payload)
525
+ return payload
526
+ raise LifecycleError("command-not-implemented", "review-mesh command is not implemented")
527
+
528
+
529
+ def _review_mesh_budget_cap(args: argparse.Namespace) -> dict[str, int] | None:
530
+ budget_cap = {
531
+ key: value
532
+ for key, value in {
533
+ "maxInvocations": args.max_invocations,
534
+ "maxInputTokens": args.max_input_tokens,
535
+ "maxOutputTokens": args.max_output_tokens,
536
+ "maxWallSeconds": args.max_wall_seconds,
537
+ }.items()
538
+ if value is not None
539
+ }
540
+ return budget_cap or None
541
+
542
+
543
+ def _dispatch_report(args: argparse.Namespace) -> dict[str, Any] | str:
544
+ if args.report_command == "status-view":
545
+ payload = build_status_view(
546
+ project_root=Path(args.project_root),
547
+ artifact_paths=[Path(item) for item in args.artifact],
548
+ max_items=args.max_items,
549
+ target_window=args.target_window,
550
+ )
551
+ if args.out:
552
+ write_json_create(Path(args.out), payload)
553
+ return payload
554
+ if args.report_command == "progress-bridge":
555
+ payload = build_progress_bridge_receipt(
556
+ adapter_id=args.adapter,
557
+ support_level=args.support_level,
558
+ hook_point=args.hook_point,
559
+ state_path=Path(args.state),
560
+ usage_receipt_paths=[Path(item) for item in args.usage_receipt],
561
+ change_summary_path=Path(args.change_summary) if args.change_summary else None,
562
+ display_mode=args.display_mode,
563
+ watch=args.watch,
564
+ iterations=args.watch_iterations,
565
+ interval_seconds=args.watch_interval,
566
+ )
567
+ if args.out:
568
+ write_json_create(Path(args.out), payload)
569
+ if args.terminal:
570
+ return render_progress_bridge_terminal(payload)
571
+ return payload
572
+ if args.report_command == "event-feed":
573
+ payload = build_workflow_event_feed(state_path=Path(args.state))
574
+ if args.out:
575
+ write_json_create(Path(args.out), payload)
576
+ return payload
577
+ if args.report_command == "progress":
578
+ if args.watch:
579
+ payload = build_lifecycle_progress_watch(
580
+ state_path=Path(args.state),
581
+ usage_receipt_paths=[Path(item) for item in args.usage_receipt],
582
+ change_summary_path=Path(args.change_summary) if args.change_summary else None,
583
+ iterations=args.watch_iterations,
584
+ interval_seconds=args.watch_interval,
585
+ )
586
+ else:
587
+ payload = build_lifecycle_progress_view(
588
+ state_path=Path(args.state),
589
+ usage_receipt_paths=[Path(item) for item in args.usage_receipt],
590
+ change_summary_path=Path(args.change_summary) if args.change_summary else None,
591
+ )
592
+ if args.out:
593
+ write_json_create(Path(args.out), payload)
594
+ if args.terminal:
595
+ return render_progress_terminal(payload)
596
+ return payload
597
+ if args.report_command == "change-summary":
598
+ payload = build_change_summary_receipt(
599
+ project_root=Path(args.project_root),
600
+ base=args.base,
601
+ head=args.head,
602
+ staged=args.staged,
603
+ paths=args.path,
604
+ )
605
+ if args.out:
606
+ write_json_create(Path(args.out), payload)
607
+ return payload
608
+ raise LifecycleError("command-not-implemented", "report command is not implemented")
609
+
610
+
611
+ def _dispatch_workflow(args: argparse.Namespace) -> dict[str, Any]:
612
+ if args.workflow_command == "budget-policy-check":
613
+ return validate_budget_exceeded_policy(read_json_object(Path(args.policy), label="budget policy"))
614
+ state_path = Path(args.state)
615
+ if args.workflow_command == "status":
616
+ return status(state_path, full=args.full)
617
+ if args.workflow_command == "next":
618
+ return next_action(status(state_path, full=True)["state"])
619
+ if args.workflow_command == "run":
620
+ validate_workflow_progress_hook_request(args, command="workflow run")
621
+ payload = run_managed_lifecycle_step(
622
+ state_path=state_path,
623
+ manifest_path=Path(args.manifest),
624
+ lock_path=Path(args.lock) if args.lock else None,
625
+ operation_id=args.operation_id,
626
+ expected_revision=args.expected_revision,
627
+ source_revision=args.source_revision,
628
+ reason=args.reason,
629
+ )
630
+ if args.out:
631
+ write_json_create(Path(args.out), payload)
632
+ maybe_emit_workflow_progress_hook(args, command="workflow run", state_path=state_path)
633
+ return payload
634
+ if args.workflow_command == "adopt-plan":
635
+ return adopt_plan(
636
+ state_path,
637
+ manifest_path=Path(args.manifest),
638
+ operation_id=args.operation_id,
639
+ expected_revision=args.expected_revision,
640
+ source_revision=args.source_revision,
641
+ reset_tasks=args.reset_tasks,
642
+ preserve_accepted_compatible=args.preserve_accepted_compatible,
643
+ start_mode=args.start_mode,
644
+ authorized_by=args.authorized_by,
645
+ )
646
+ if args.workflow_command == "run-start":
647
+ return start_execution(
648
+ state_path,
649
+ operation_id=args.operation_id,
650
+ expected_revision=args.expected_revision,
651
+ source_revision=args.source_revision,
652
+ reason=args.reason,
653
+ )
654
+ if args.workflow_command == "finalize":
655
+ validate_workflow_progress_hook_request(args, command="workflow finalize")
656
+ payload = finalize_run(
657
+ state_path,
658
+ operation_id=args.operation_id,
659
+ expected_revision=args.expected_revision,
660
+ source_revision=args.source_revision,
661
+ final_audit_path=args.final_audit,
662
+ proof_path=args.proof,
663
+ proof_integrity_path=args.proof_integrity,
664
+ goal_record_path=args.goal_record,
665
+ follow_up_register_path=args.follow_up_register,
666
+ completion_gate_receipt_path=args.completion_gate_receipt,
667
+ final_implementation_audit_path=args.final_implementation_audit,
668
+ review_mesh_quorum_paths=args.review_mesh_quorum,
669
+ reason=args.reason,
670
+ )
671
+ maybe_emit_workflow_progress_hook(args, command="workflow finalize", state_path=state_path)
672
+ return payload
673
+ return _dispatch_workflow_task(args, state_path)
674
+
675
+
676
+ def _dispatch_workflow_task(args: argparse.Namespace, state_path: Path) -> dict[str, Any]:
677
+ if args.workflow_command == "block":
678
+ return block_run(
679
+ state_path,
680
+ operation_id=args.operation_id,
681
+ expected_revision=args.expected_revision,
682
+ blocker_code=args.blocker_code,
683
+ reason=args.reason,
684
+ )
685
+ if args.workflow_command == "resolve":
686
+ return resolve_blocker(
687
+ state_path,
688
+ operation_id=args.operation_id,
689
+ expected_revision=args.expected_revision,
690
+ reason=args.reason,
691
+ )
692
+ if args.workflow_command == "task-start":
693
+ return start_task(
694
+ state_path,
695
+ task_id=args.task,
696
+ operation_id=args.operation_id,
697
+ expected_revision=args.expected_revision,
698
+ source_revision=args.source_revision,
699
+ reason=args.reason,
700
+ )
701
+ if args.workflow_command == "task-result":
702
+ validate_workflow_progress_hook_request(args, command="workflow task-result")
703
+ payload = commit_task_result(
704
+ state_path,
705
+ task_id=args.task,
706
+ operation_id=args.operation_id,
707
+ expected_revision=args.expected_revision,
708
+ source_revision=args.source_revision,
709
+ result_path=args.result,
710
+ model_usage_receipt_path=args.model_usage_receipt,
711
+ budget_targets_path=args.budget_targets,
712
+ reason=args.reason,
713
+ )
714
+ maybe_emit_workflow_progress_hook(args, command="workflow task-result", state_path=state_path)
715
+ return payload
716
+ if args.workflow_command == "budget-decision":
717
+ if args.action:
718
+ _require_args(args, ["decision_receipt", "receipt"], mode="budget-decision apply")
719
+ return apply_budget_decision(
720
+ state_path,
721
+ task_id=args.task,
722
+ operation_id=args.operation_id,
723
+ expected_revision=args.expected_revision,
724
+ source_revision=args.source_revision,
725
+ decision_receipt_path=args.decision_receipt,
726
+ action=args.action,
727
+ applied_receipt_path=args.receipt,
728
+ route_decision_path=args.route_decision,
729
+ split_packet_path=args.split_packet,
730
+ cap_deltas_path=args.cap_deltas,
731
+ operator_identity_hash=args.operator_identity_hash,
732
+ reason=args.reason,
733
+ )
734
+ _require_args(args, ["model_usage_receipt", "budget_policy", "receipt"], mode="budget-decision pause")
735
+ return pause_for_budget_decision(
736
+ state_path,
737
+ task_id=args.task,
738
+ operation_id=args.operation_id,
739
+ expected_revision=args.expected_revision,
740
+ source_revision=args.source_revision,
741
+ usage_receipt_path=args.model_usage_receipt,
742
+ budget_policy_path=args.budget_policy,
743
+ decision_receipt_path=args.receipt,
744
+ reason=args.reason,
745
+ )
746
+ if args.workflow_command == "task-accept":
747
+ validate_workflow_progress_hook_request(args, command="workflow task-accept")
748
+ payload = accept_task(
749
+ state_path,
750
+ task_id=args.task,
751
+ operation_id=args.operation_id,
752
+ expected_revision=args.expected_revision,
753
+ review_path=args.review,
754
+ implementation_audit_path=args.implementation_audit,
755
+ reason=args.reason,
756
+ )
757
+ maybe_emit_workflow_progress_hook(args, command="workflow task-accept", state_path=state_path)
758
+ return payload
759
+ raise LifecycleError("command-not-implemented", "workflow command is not implemented")
760
+
761
+
762
+ def _require_args(args: argparse.Namespace, names: list[str], *, mode: str) -> None:
763
+ missing = [name.replace("_", "-") for name in names if not getattr(args, name, None)]
764
+ if missing:
765
+ raise LifecycleError("missing-cli-argument", f"{mode} requires arguments", {"missing": missing})
766
+
767
+
768
+ def _dispatch_audit(args: argparse.Namespace) -> dict[str, Any]:
769
+ if args.audit_command == "review-check":
770
+ review = read_json_object(Path(args.review), label="task review")
771
+ verdict = review.get("reviewVerdict", review)
772
+ findings = review.get("findings", []) if isinstance(review.get("findings", []), list) else []
773
+ return require_review_verdict_pass(validate_review_verdict(verdict, findings=findings))
774
+ if args.audit_command == "implementation":
775
+ payload = build_implementation_audit_report(
776
+ manifest_path=Path(args.manifest),
777
+ state_path=Path(args.state),
778
+ task_id=args.task,
779
+ result_path=args.result,
780
+ review_path=args.review,
781
+ evidence_paths=args.evidence,
782
+ sandbox_receipt_paths=args.sandbox_receipt,
783
+ review_mesh_quorum_paths=args.review_mesh_quorum,
784
+ changed_paths=args.path or None,
785
+ expected_revision=args.expected_revision,
786
+ base=args.base,
787
+ auditor_id=args.auditor_id,
788
+ auditor_surface=args.auditor_surface,
789
+ )
790
+ if args.out:
791
+ write_json_create(Path(args.out), payload)
792
+ return payload
793
+ if args.audit_command == "final-implementation":
794
+ payload = build_final_implementation_audit(
795
+ manifest_path=Path(args.manifest),
796
+ state_path=Path(args.state),
797
+ report_paths=args.report,
798
+ auditor_id=args.auditor_id,
799
+ auditor_surface=args.auditor_surface,
800
+ )
801
+ if args.out:
802
+ write_json_create(Path(args.out), payload)
803
+ return payload
804
+ paths = args.path or changed_files(Path.cwd(), base=args.base)
805
+ report = build_ownership_report(Path(args.manifest), paths, base=args.base)
806
+ if args.fail_on_forbidden and report_has_category(report, {"forbidden"}):
807
+ raise LifecycleError(
808
+ "forbidden-write-detected",
809
+ "ownership report contains forbidden writes",
810
+ report["summary"],
811
+ )
812
+ if args.fail_on_unowned and report_has_category(report, {"unowned"}):
813
+ raise LifecycleError(
814
+ "unowned-write-detected",
815
+ "ownership report contains unowned writes",
816
+ report["summary"],
817
+ )
818
+ return report
819
+
820
+
821
+ def _dispatch_context(args: argparse.Namespace) -> dict[str, Any]:
822
+ if args.context_command == "profile-check":
823
+ return load_context_profile(Path(args.profile))
824
+ if args.context_command == "check":
825
+ result = check_context(
826
+ Path(args.profile),
827
+ Path(args.task_packet),
828
+ Path(args.summary),
829
+ latest_user=args.latest_user,
830
+ window=args.target_window,
831
+ )
832
+ return _require_context_pass(result)
833
+ if args.context_command == "render":
834
+ profile = read_json_object(Path(args.profile), label="context profile")
835
+ load_context_profile(Path(args.profile))
836
+ result = render_context(
837
+ profile,
838
+ read_json_object(Path(args.task_packet), label="task packet"),
839
+ read_json_object(Path(args.summary), label="state summary"),
840
+ latest_user=args.latest_user,
841
+ window=args.target_window,
842
+ )
843
+ return _require_context_pass(result)
844
+ if args.context_command == "external-import":
845
+ payload = import_external_memory_context(
846
+ Path(args.source),
847
+ citation=args.citation,
848
+ source_id=args.source_id,
849
+ max_input_bytes=args.max_input_bytes,
850
+ target_tokens=args.target_tokens,
851
+ )
852
+ if args.out:
853
+ write_json_create(Path(args.out), payload)
854
+ return payload
855
+ if args.context_command == "episode-retrieve":
856
+ payload = build_episode_retrieval_with_external_context(
857
+ Path(args.project_root),
858
+ list(args.artifact),
859
+ external_context_paths=[Path(item) for item in args.external_context],
860
+ query=args.query,
861
+ max_results=args.max_results,
862
+ max_external_context_hints=args.max_external_context_hints,
863
+ target_tokens=args.target_tokens,
864
+ )
865
+ if args.out:
866
+ write_json_create(Path(args.out), payload)
867
+ return payload
868
+ raise LifecycleError("command-not-implemented", "context command is not implemented")
869
+
870
+
871
+ def _dispatch_goal(args: argparse.Namespace) -> dict[str, Any]:
872
+ record = read_json_object(Path(args.record), label="goal record")
873
+ if args.goal_command == "check":
874
+ state = read_json_object(Path(args.state), label="workflow state") if args.state else None
875
+ return validate_goal_record(record, state=state, require_current=args.current)
876
+ if args.goal_command == "summarize":
877
+ state = read_json_object(Path(args.state), label="workflow state")
878
+ profile = read_json_object(Path(args.profile), label="context profile") if args.profile else None
879
+ return build_objective_snapshot(record, state, profile=profile, window=args.target_window)
880
+ if args.goal_command == "view":
881
+ payload = build_goal_progress_view(
882
+ record_path=Path(args.record),
883
+ state_path=Path(args.state),
884
+ usage_receipt_paths=[Path(item) for item in args.usage_receipt],
885
+ change_summary_path=Path(args.change_summary) if args.change_summary else None,
886
+ require_current=not args.allow_stale_goal,
887
+ )
888
+ if args.out:
889
+ write_json_create(Path(args.out), payload)
890
+ if args.terminal:
891
+ return render_goal_view_terminal(payload)
892
+ return payload
893
+ if args.goal_command == "update":
894
+ state = read_json_object(Path(args.state), label="workflow state")
895
+ updated = update_goal_record(
896
+ record,
897
+ state,
898
+ status=args.status,
899
+ reason=args.reason,
900
+ evidence_ids=args.evidence_id,
901
+ )
902
+ if args.out:
903
+ write_json_create(Path(args.out), updated)
904
+ return updated
905
+ raise LifecycleError("command-not-implemented", "goal command is not implemented")
906
+
907
+
908
+ def _dispatch_model(args: argparse.Namespace) -> dict[str, Any]:
909
+ if args.model_command == "profile-check":
910
+ profile = read_json_object(Path(args.profile), label="model profile")
911
+ if args.type == "routing":
912
+ return validate_model_routing_profile(profile)
913
+ if args.type == "host":
914
+ return validate_host_model_profile(profile)
915
+ if profile.get("schemaVersion") in {
916
+ "agent-lifecycle-host-model-profile.v1",
917
+ "agent-host-model-selection-profile.v1",
918
+ }:
919
+ return validate_host_model_profile(profile)
920
+ return validate_model_routing_profile(profile)
921
+ if args.model_command == "route":
922
+ routing_profile = read_json_object(Path(args.profile), label="model routing profile")
923
+ host_profile = read_json_object(Path(args.host_profile), label="host model profile") if args.host_profile else None
924
+ request = read_json_object(Path(args.request), label="model route request")
925
+ return resolve_model_route(request, routing_profile, host_profile=host_profile)
926
+ if args.model_command == "usage-check":
927
+ receipt = read_json_object(Path(args.receipt), label="model usage receipt")
928
+ decision = read_json_object(Path(args.route_decision), label="model route decision") if args.route_decision else None
929
+ targets = read_json_object(Path(args.budget_targets), label="budget targets") if args.budget_targets else None
930
+ result = validate_usage_receipt(receipt, budget_targets=targets, route_decision=decision)
931
+ if result["status"] == "FAIL":
932
+ raise LifecycleError("model-usage-validation-failed", "model usage receipt validation failed", {"validation": result})
933
+ return result
934
+ raise LifecycleError("command-not-implemented", "model command is not implemented")
935
+
936
+
937
+ def _dispatch_metrics(args: argparse.Namespace) -> dict[str, Any]:
938
+ if args.metrics_command == "cost-check":
939
+ report = read_json_object(Path(args.receipt), label="lifecycle cost report")
940
+ return require_lifecycle_cost_pass(validate_lifecycle_cost_report(report))
941
+ if args.metrics_command == "cost-report":
942
+ report = generate_lifecycle_cost_report(
943
+ artifact_paths=[Path(item) for item in args.artifact],
944
+ mode=args.mode,
945
+ root=Path(args.project_root),
946
+ )
947
+ validation = require_lifecycle_cost_pass(validate_lifecycle_cost_report(report))
948
+ report_bytes = write_json_create(Path(args.out), report)
949
+ summary_path = None
950
+ summary_digest = None
951
+ if args.summary_out:
952
+ summary = build_lifecycle_cost_summary(report)
953
+ write_json_create(Path(args.summary_out), summary)
954
+ summary_path = args.summary_out
955
+ summary_digest = canonical_digest(summary)
956
+ return {
957
+ "schemaVersion": "agent-lifecycle-cost-generation.v1",
958
+ "status": validation["status"],
959
+ "reportPath": args.out,
960
+ "reportBytes": len(report_bytes),
961
+ "reportDigest": canonical_digest(report),
962
+ "summaryPath": summary_path,
963
+ "summaryDigest": summary_digest,
964
+ "validation": validation,
965
+ "liveCallsStarted": False,
966
+ "productionPromotionClaimed": False,
967
+ }
968
+ if args.metrics_command == "usage-export":
969
+ export = build_usage_export(
970
+ artifact_paths=[Path(item) for item in args.artifact],
971
+ project_root=Path(args.project_root),
972
+ )
973
+ validation = require_usage_export_pass(validate_usage_export(export))
974
+ rendered = render_usage_export_json(export) if args.format == "json" else render_usage_export_table(export)
975
+ output_path = Path(args.out)
976
+ _write_text_create(output_path, rendered)
977
+ return {
978
+ "schemaVersion": "agent-usage-export-generation.v1",
979
+ "status": validation["status"],
980
+ "format": args.format,
981
+ "outputPath": args.out,
982
+ "outputBytes": len(rendered.encode("utf-8")),
983
+ "exportDigest": canonical_digest(export),
984
+ "validation": validation,
985
+ "liveCallsStarted": False,
986
+ "productionPromotionClaimed": False,
987
+ }
988
+ if args.metrics_command == "outcome-index":
989
+ artifacts = [read_json_object(Path(item), label="outcome artifact") for item in args.artifact]
990
+ payload = build_task_outcome_index(artifacts, source_paths=list(args.artifact))
991
+ if args.out:
992
+ write_json_create(Path(args.out), payload)
993
+ return payload
994
+ if args.metrics_command == "quality-signals":
995
+ payload = build_quality_cost_signals(read_json_object(Path(args.index), label="task outcome index"))
996
+ if args.out:
997
+ write_json_create(Path(args.out), payload)
998
+ return payload
999
+ if args.metrics_command == "recommend":
1000
+ reports = [read_json_object(Path(item), label="lifecycle cost report") for item in args.report]
1001
+ baseline_profile = read_json_object(Path(args.baseline_profile), label="lifecycle baseline profile")
1002
+ recommendation = recommend_lifecycle_mode(
1003
+ reports=reports,
1004
+ baseline_profile=baseline_profile,
1005
+ task_shape=args.task_shape,
1006
+ current_mode=args.current_mode,
1007
+ sdd_tier=args.sdd_tier,
1008
+ risk_flags=args.risk,
1009
+ )
1010
+ require_lifecycle_recommendation_pass(recommendation)
1011
+ if args.out:
1012
+ write_json_create(Path(args.out), recommendation)
1013
+ if args.summary_out:
1014
+ write_json_create(Path(args.summary_out), build_lifecycle_recommendation_summary(recommendation))
1015
+ return recommendation
1016
+ if args.metrics_command == "learn-recommend":
1017
+ signals = read_json_object(Path(args.signals), label="quality-cost signals")
1018
+ baseline_profile = read_json_object(Path(args.baseline_profile), label="lifecycle baseline profile")
1019
+ recommendation = recommend_from_quality_cost_signals(
1020
+ signals=signals,
1021
+ baseline_profile=baseline_profile,
1022
+ task_shape=args.task_shape,
1023
+ current_mode=args.current_mode,
1024
+ sdd_tier=args.sdd_tier,
1025
+ risk_flags=args.risk,
1026
+ )
1027
+ require_lifecycle_recommendation_pass(recommendation)
1028
+ if args.out:
1029
+ write_json_create(Path(args.out), recommendation)
1030
+ if args.summary_out:
1031
+ write_json_create(Path(args.summary_out), build_lifecycle_recommendation_summary(recommendation))
1032
+ return recommendation
1033
+ raise LifecycleError("command-not-implemented", "metrics command is not implemented")
1034
+
1035
+
1036
+ def _write_text_create(path: Path, text: str) -> bytes:
1037
+ data = text.encode("utf-8")
1038
+ path.parent.mkdir(parents=True, exist_ok=True)
1039
+ try:
1040
+ with path.open("x", encoding="utf-8") as handle:
1041
+ handle.write(text)
1042
+ except FileExistsError as exc:
1043
+ raise LifecycleError("output-already-exists", "output artifact already exists", {"path": path.as_posix()}) from exc
1044
+ return data
1045
+
1046
+
1047
+ def _dispatch_runner(args: argparse.Namespace) -> dict[str, Any]:
1048
+ runner_path = Path(args.runner)
1049
+ if args.runner_command == "start":
1050
+ workflow_state = read_json_object(Path(args.state), label="workflow state")
1051
+ policy = load_runner_policy(Path(args.policy) if args.policy else None)
1052
+ runner_state = initialize_runner_state(
1053
+ workflow_state,
1054
+ policy=policy,
1055
+ operation_id=args.operation_id,
1056
+ reason=args.reason,
1057
+ )
1058
+ write_runner_state_create(runner_path, runner_state)
1059
+ return validate_runner_state(runner_state, workflow_state=workflow_state)
1060
+ runner_state = load_runner_state(runner_path)
1061
+ if args.runner_command == "status":
1062
+ workflow_state = read_json_object(Path(args.state), label="workflow state") if args.state else None
1063
+ if args.profile:
1064
+ if workflow_state is None:
1065
+ raise LifecycleError("missing-cli-argument", "runner status with --profile requires --state")
1066
+ profile = read_json_object(Path(args.profile), label="context profile")
1067
+ return build_runner_snapshot(runner_state, workflow_state, profile=profile, window=args.target_window)
1068
+ return validate_runner_state(runner_state, workflow_state=workflow_state)
1069
+ workflow_state = read_json_object(Path(args.state), label="workflow state")
1070
+ if args.runner_command == "transition":
1071
+ request = read_json_object(Path(args.request), label="runner transition request")
1072
+ payload = transition_runner(runner_state, workflow_state, request)
1073
+ write_runner_state(runner_path, payload["state"])
1074
+ return payload["result"]
1075
+ if args.runner_command == "stop":
1076
+ payload = request_runner_stop(
1077
+ runner_state,
1078
+ workflow_state,
1079
+ operation_id=args.operation_id,
1080
+ expected_runner_revision=args.expected_runner_revision,
1081
+ reason=args.reason,
1082
+ )
1083
+ write_runner_state(runner_path, payload["state"])
1084
+ return payload["result"]
1085
+ if args.runner_command == "resume":
1086
+ payload = resume_runner(
1087
+ runner_state,
1088
+ workflow_state,
1089
+ operation_id=args.operation_id,
1090
+ expected_runner_revision=args.expected_runner_revision,
1091
+ reason=args.reason,
1092
+ )
1093
+ write_runner_state(runner_path, payload["state"])
1094
+ return payload["result"]
1095
+ raise LifecycleError("command-not-implemented", "runner command is not implemented")
1096
+
1097
+
1098
+ def _require_context_pass(result: dict[str, Any]) -> dict[str, Any]:
1099
+ if result.get("status") == "FAIL":
1100
+ raise LifecycleError(
1101
+ "context-overflow",
1102
+ "compact context exceeds target window",
1103
+ {"receipt": result.get("receipt")},
1104
+ )
1105
+ return result
1106
+
1107
+
1108
+ def _dispatch_tier(args: argparse.Namespace) -> dict[str, Any]:
1109
+ if args.tier_command == "resolve":
1110
+ return resolve_sdd_tier(read_json_object(Path(args.request), label="tier request"))
1111
+ raise LifecycleError("command-not-implemented", "tier command is not implemented")
1112
+
1113
+
1114
+ def _dispatch_specification(args: argparse.Namespace) -> dict[str, Any]:
1115
+ if args.specification_command == "check":
1116
+ return validate_specification(read_json_object(Path(args.specification), label="specification"))
1117
+ if args.specification_command == "completion-gate":
1118
+ gate_input = read_json_object(Path(args.input), label="completion gate input") if args.input else {}
1119
+ payload = build_completion_gate_receipt(
1120
+ state=read_json_object(Path(args.state), label="workflow state"),
1121
+ final_audit=read_json_object(Path(args.final_audit), label="final audit") if args.final_audit else None,
1122
+ follow_up_register=read_json_object(Path(args.follow_up_register), label="follow-up register") if args.follow_up_register else None,
1123
+ validation_results=gate_input.get("validationResults", []),
1124
+ required_validation_ids=gate_input.get("requiredValidationIds", []),
1125
+ follow_up_candidates=gate_input.get("followUpCandidates", []),
1126
+ regression_signals=gate_input.get("regressionSignals", []),
1127
+ risk_flags=gate_input.get("riskFlags", []),
1128
+ split_candidates=gate_input.get("splitCandidates", []),
1129
+ verifier_id=args.verifier,
1130
+ )
1131
+ if args.out:
1132
+ write_json_create(Path(args.out), payload)
1133
+ return payload
1134
+ raise LifecycleError("command-not-implemented", "specification command is not implemented")
1135
+
1136
+
1137
+ def _dispatch_plan(args: argparse.Namespace) -> dict[str, Any]:
1138
+ if args.plan_command == "check":
1139
+ manifest = read_json_object(Path(args.manifest), label="plan manifest")
1140
+ lock = read_json_object(Path(args.lock), label="plan lock") if args.lock else None
1141
+ completeness_profile = (
1142
+ load_plan_completeness_profile(Path(args.completeness_profile))
1143
+ if args.completeness_profile
1144
+ else None
1145
+ )
1146
+ return {
1147
+ "schemaVersion": "agent-plan-check.v1",
1148
+ "manifest": validate_plan_manifest(
1149
+ manifest,
1150
+ require_completeness=args.require_completeness,
1151
+ completeness_profile=completeness_profile,
1152
+ ),
1153
+ "lock": verify_plan_lock(manifest, lock) if lock else None,
1154
+ }
1155
+ if args.plan_command == "completeness-check":
1156
+ manifest = read_json_object(Path(args.manifest), label="plan manifest")
1157
+ profile = load_plan_completeness_profile(Path(args.profile)) if args.profile else None
1158
+ payload = validate_plan_completeness(manifest, profile=profile)
1159
+ if args.out:
1160
+ write_json_create(Path(args.out), payload)
1161
+ return payload
1162
+ if args.plan_command == "acceptance-check":
1163
+ manifest_path = Path(args.manifest)
1164
+ acceptance_path = Path(args.acceptance)
1165
+ return validate_acceptance_checklist(
1166
+ read_json_object(manifest_path, label="plan manifest"),
1167
+ acceptance_path.read_text(encoding="utf-8"),
1168
+ )
1169
+ if args.plan_command == "refs-check":
1170
+ manifest = read_json_object(Path(args.manifest), label="plan manifest")
1171
+ return require_repository_references_pass(validate_repository_references(manifest))
1172
+ if args.plan_command == "snapshot":
1173
+ manifest = read_json_object(Path(args.manifest), label="plan manifest")
1174
+ payload = build_plan_snapshot(manifest)
1175
+ if args.out:
1176
+ write_json_create(Path(args.out), payload)
1177
+ return payload
1178
+ if args.plan_command == "reconcile":
1179
+ manifest = read_json_object(Path(args.manifest), label="plan manifest")
1180
+ snapshot = read_json_object(Path(args.snapshot), label="plan snapshot")
1181
+ return require_reconciliation_pass(reconcile_plan_snapshot(snapshot, manifest))
1182
+ if args.plan_command == "handoff":
1183
+ manifest = read_json_object(Path(args.manifest), label="plan manifest")
1184
+ snapshot = read_json_object(Path(args.snapshot), label="plan snapshot") if args.snapshot else None
1185
+ payload = render_plan_handoff(
1186
+ manifest,
1187
+ snapshot=snapshot,
1188
+ max_workstreams=args.max_workstreams,
1189
+ target_tokens=args.target_tokens,
1190
+ )
1191
+ if payload.get("status") != "PASS":
1192
+ raise LifecycleError("plan-handoff-render-failed", "plan handoff did not fit the requested limits", {"handoff": payload})
1193
+ if args.out:
1194
+ write_json_create(Path(args.out), payload)
1195
+ return payload
1196
+ raise LifecycleError("command-not-implemented", "plan command is not implemented")
1197
+
1198
+
1199
+ def _dispatch_task(args: argparse.Namespace) -> dict[str, Any]:
1200
+ if args.task_command == "compile":
1201
+ result = compile_task_packets(
1202
+ Path(args.manifest),
1203
+ out_dir=Path(args.out_dir) if args.out_dir else None,
1204
+ write=args.write,
1205
+ )
1206
+ return {"schemaVersion": "agent-task-packet-compile-result.v1", **result}
1207
+ if args.task_command == "compile-small":
1208
+ adaptive_decision = read_json_object(Path(args.adaptive_decision), label="adaptive lifecycle decision") if args.adaptive_decision else None
1209
+ result = compile_small_model_packets(
1210
+ Path(args.manifest),
1211
+ context_profile_path=Path(args.context_profile),
1212
+ out_dir=Path(args.out_dir) if args.out_dir else None,
1213
+ target_window=args.target_window,
1214
+ adaptive_decision=adaptive_decision,
1215
+ write=args.write,
1216
+ )
1217
+ if result["status"] != "PASS":
1218
+ raise LifecycleError("small-model-packet-compile-failed", "small-model packet compilation failed", {"result": result})
1219
+ return result
1220
+ raise LifecycleError("command-not-implemented", "task command is not implemented")