Skills › Compound Engineering › ce-work › unit-workspace.py
unit-workspace.py
215 lines · skills/ce-work/scripts/unit-workspace.py at 3449230
1#!/usr/bin/env python3
2"""CLI entrypoint for the ce-work crash-recoverable workspace controller."""
4from __future__ import annotations
6import argparse
7import json
8import os
9import sys
11from unit_workspace_state import Operational, TrustFailure, cmd_checkpoint_plan, cmd_init
12from unit_workspace_jobs import cmd_authorize_dispatch, cmd_prepare, cmd_record_job, cmd_sync_job, cmd_terminalize
13from unit_workspace_integration import (
14 cmd_integration_acquire,
15 cmd_integration_release,
16 cmd_mark_applied,
17 cmd_mark_committed,
18 cmd_mark_verified,
19 cmd_preflight,
20 cmd_restore,
21 cmd_wave_advance,
22)
23from unit_workspace_lifecycle import cmd_claim_fallback, cmd_cleanup, cmd_complete_fallback, cmd_reap, cmd_resume, cmd_status
24from unit_workspace_transaction import cmd_integrate, cmd_verify_run
27def build_parser() -> argparse.ArgumentParser:
28 parser = argparse.ArgumentParser(prog="unit-workspace.py")
29 sub = parser.add_subparsers(dest="command", required=True)
31 p = sub.add_parser("init")
32 p.add_argument("--run-id", required=True)
33 p.add_argument("--repo", required=True)
34 source = p.add_mutually_exclusive_group(required=True)
35 source.add_argument("--plan")
36 source.add_argument("--prompt-brief")
37 p.add_argument("--plan-digest")
38 p.add_argument("--prompt-digest")
39 p.add_argument("--binding-json", default="{}")
40 p.add_argument("--egress-json", default="{}")
42 p = sub.add_parser("checkpoint-plan")
43 p.add_argument("--run-id", required=True)
45 p = sub.add_parser("prepare")
46 p.add_argument("--run-id", required=True)
47 p.add_argument("--unit-id", required=True)
48 p.add_argument("--base", required=True)
49 p.add_argument("--packet", required=True)
50 p.add_argument("--attempt-id", default="attempt-1")
51 p.add_argument("--activity-posture", choices=("incremental", "hard-only"), default="hard-only")
52 p.add_argument("--dependency", action="append", default=[])
53 p.add_argument("--wave-id")
54 p.add_argument("--wave-position", type=int, default=0)
56 p = sub.add_parser("record-job")
57 p.add_argument("--run-id", required=True)
58 p.add_argument("--unit-id", required=True)
59 p.add_argument("--attempt-id", required=True)
60 p.add_argument("--job-id", required=True)
62 p = sub.add_parser("authorize-dispatch")
63 p.add_argument("--run-id", required=True)
64 p.add_argument("--unit-id", required=True)
65 p.add_argument("--attempt-id", required=True)
66 p.add_argument("--job-id", required=True)
67 p.add_argument("--authorization", required=True)
68 p.add_argument("--authorization-digest", required=True)
69 p.add_argument("--workspace", required=True)
70 p.add_argument("--packet", required=True)
71 p.add_argument("--packet-digest", required=True)
72 p.add_argument("--result-dir", required=True)
74 for name in ("sync-job", "terminalize", "reap"):
75 p = sub.add_parser(name)
76 p.add_argument("--run-id", required=True)
77 p.add_argument("--unit-id", required=True)
79 p = sub.add_parser("integration-acquire")
80 p.add_argument("--run-id", required=True)
81 p.add_argument("--unit-id", required=True)
82 p.add_argument("--resume", action="store_true")
84 p = sub.add_parser("preflight")
85 p.add_argument("--run-id", required=True)
86 p.add_argument("--unit-id", required=True)
87 p.add_argument("--lock-token", required=True)
88 p.add_argument("--allowed-head", action="append", default=[])
90 p = sub.add_parser("mark-applied")
91 p.add_argument("--run-id", required=True)
92 p.add_argument("--unit-id", required=True)
93 p.add_argument("--lock-token", required=True)
95 p = sub.add_parser("mark-verified")
96 p.add_argument("--run-id", required=True)
97 p.add_argument("--unit-id", required=True)
98 p.add_argument("--lock-token", required=True)
99 p.add_argument("--evidence-digest", required=True)
100 p.add_argument("--summary", default="authoritative verification passed")
101 p.add_argument("--ignored-state", default=None)
103 p = sub.add_parser("mark-committed")
104 p.add_argument("--run-id", required=True)
105 p.add_argument("--unit-id", required=True)
106 p.add_argument("--lock-token", required=True)
108 p = sub.add_parser("integrate")
109 p.add_argument("--run-id", required=True)
110 p.add_argument("--unit-id", required=True)
111 p.add_argument("--commit-message", required=True)
112 p.add_argument("--verification-summary", default="authoritative verification passed")
113 p.add_argument("--allowed-head", action="append", default=[])
114 p.add_argument("verification_command", nargs=argparse.REMAINDER)
116 p = sub.add_parser("verify-run")
117 p.add_argument("--run-id", required=True)
118 p.add_argument("--verification-summary", default="plan-wide authoritative verification passed")
119 p.add_argument("verification_command", nargs=argparse.REMAINDER)
121 p = sub.add_parser("wave-advance")
122 p.add_argument("--run-id", required=True)
123 p.add_argument("--unit-id", required=True)
124 p.add_argument("--lock-token", required=True)
125 p.add_argument("--canonical-commit", required=True)
127 p = sub.add_parser("restore")
128 p.add_argument("--run-id", required=True)
129 p.add_argument("--unit-id", required=True)
130 p.add_argument("--lock-token", required=True)
132 p = sub.add_parser("status")
133 p.add_argument("--run-id", required=True)
134 p.add_argument("--unit-id")
136 p = sub.add_parser("resume")
137 p.add_argument("--run-id")
138 p.add_argument("--repo")
139 p.add_argument("--plan-digest")
141 p = sub.add_parser("claim-fallback")
142 p.add_argument("--run-id", required=True)
143 p.add_argument("--unit-id", required=True)
144 p.add_argument("--caller-mode", choices=("interactive", "headless"), required=True)
146 p = sub.add_parser("complete-fallback")
147 p.add_argument("--run-id", required=True)
148 p.add_argument("--unit-id", required=True)
149 p.add_argument("--accepted-head", required=True)
150 p.add_argument("--evidence-digest", required=True)
151 p.add_argument("--summary", required=True)
153 p = sub.add_parser("cleanup")
154 p.add_argument("--run-id", required=True)
155 p.add_argument("--unit-id", required=True)
156 p.add_argument("--abandon", action="store_true")
157 p.add_argument("--expect-transport")
158 p.add_argument("--expect-job")
160 p = sub.add_parser("integration-release")
161 p.add_argument("--run-id", required=True)
162 p.add_argument("--unit-id", required=True)
163 p.add_argument("--lock-token", required=True)
164 return parser
167COMMANDS = {
168 "init": cmd_init,
169 "checkpoint-plan": cmd_checkpoint_plan,
170 "prepare": cmd_prepare,
171 "authorize-dispatch": cmd_authorize_dispatch,
172 "record-job": cmd_record_job,
173 "sync-job": cmd_sync_job,
174 "terminalize": cmd_terminalize,
175 "integration-acquire": cmd_integration_acquire,
176 "preflight": cmd_preflight,
177 "mark-applied": cmd_mark_applied,
178 "mark-verified": cmd_mark_verified,
179 "mark-committed": cmd_mark_committed,
180 "integrate": cmd_integrate,
181 "verify-run": cmd_verify_run,
182 "wave-advance": cmd_wave_advance,
183 "restore": cmd_restore,
184 "status": cmd_status,
185 "resume": cmd_resume,
186 "claim-fallback": cmd_claim_fallback,
187 "complete-fallback": cmd_complete_fallback,
188 "reap": cmd_reap,
189 "cleanup": cmd_cleanup,
190 "integration-release": cmd_integration_release,
191}
194def main(argv: list[str]) -> int:
195 os.umask(0o077)
196 args = build_parser().parse_args(argv)
197 try:
198 word, body = COMMANDS[args.command](args)
199 print(word)
200 print(json.dumps(body, sort_keys=True, separators=(",", ":")))
201 return 0
202 except TrustFailure as exc:
203 print("UNREADABLE")
204 sys.stderr.write(f"unit-workspace: {exc}\n")
205 return 4
206 except Operational as exc:
207 print(exc.word)
208 if exc.detail:
209 print(json.dumps(exc.detail, sort_keys=True, separators=(",", ":")))
210 sys.stderr.write(f"unit-workspace: {exc}\n")
211 return 1
214if __name__ == "__main__":
215 raise SystemExit(main(sys.argv[1:]))