@arbiterforge/ca-pi 0.14.10 → 0.14.16
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.
- package/README.md +33 -9
- package/package.json +2 -1
- package/plugins/ca-pi/CHANGELOG.md +67 -0
- package/plugins/ca-pi/LICENSE +661 -0
- package/plugins/ca-pi/SKILLS.md +2 -2
- package/plugins/ca-pi/SPRINT.md +47 -0
- package/plugins/ca-pi/THIRD_PARTY_NOTICES.md +40 -0
- package/plugins/ca-pi/generated/command-catalog.json +2 -2
- package/plugins/ca-pi/helpers/artifacts/ca-artifact-darwin-amd64 +0 -0
- package/plugins/ca-pi/helpers/artifacts/ca-artifact-darwin-arm64 +0 -0
- package/plugins/ca-pi/helpers/artifacts/ca-artifact-linux-amd64 +0 -0
- package/plugins/ca-pi/helpers/artifacts/ca-artifact-linux-arm64 +0 -0
- package/plugins/ca-pi/helpers/artifacts/ca-artifact-windows-amd64.exe +0 -0
- package/plugins/ca-pi/helpers/artifacts/ca-artifact-windows-arm64.exe +0 -0
- package/plugins/ca-pi/helpers/artifacts/release.json +6 -6
- package/plugins/ca-pi/hooks/_approvallib.py +58 -22
- package/plugins/ca-pi/hooks/_artifactauthoritylib.py +2135 -0
- package/plugins/ca-pi/hooks/_artifactlib.py +164 -7
- package/plugins/ca-pi/hooks/_artifactpromptlib.py +177 -0
- package/plugins/ca-pi/hooks/_host.py +1 -1
- package/plugins/ca-pi/hooks/_overrideappendlib.py +5 -1
- package/plugins/ca-pi/hooks/_prerequisitelib.py +44 -22
- package/plugins/ca-pi/hooks/_reconciliationlib.py +472 -0
- package/plugins/ca-pi/hooks/_releaselib.py +345 -111
- package/plugins/ca-pi/hooks/_sprintapprovallib.py +302 -0
- package/plugins/ca-pi/hooks/artifact-authority-hook.py +127 -0
- package/plugins/ca-pi/hooks/artifact-authority.py +102 -0
- package/plugins/ca-pi/hooks/artifact-reconcile.py +57 -0
- package/plugins/ca-pi/hooks/hostapi.py +1 -1
- package/plugins/ca-pi/hooks/prompt-submit.py +20 -3
- package/plugins/ca-pi/hooks/releasehash.py +36 -23
- package/plugins/ca-pi/includes/artifacts.md +120 -13
- package/plugins/ca-pi/includes/sprint-authority.md +69 -0
- package/plugins/ca-pi/package.json +1 -1
- package/plugins/ca-pi/routines/INDEX.md +7 -4
- package/plugins/ca-pi/routines/brainstorming/SKILL.md +97 -29
- package/plugins/ca-pi/routines/commit-gate/SKILL.md +7 -1
- package/plugins/ca-pi/routines/executing-plans/SKILL.md +32 -15
- package/plugins/ca-pi/routines/release/SKILL.md +220 -70
- package/plugins/ca-pi/routines/skill-author/SKILL.md +26 -5
- package/plugins/ca-pi/routines/writing-plans/SKILL.md +22 -10
- package/plugins/ca-pi/skills/ca-commit/SKILL.md +170 -16
- package/plugins/ca-pi/skills/ca-new-skill/SKILL.md +116 -21
- package/plugins/ca-pi/skills/ca-release/SKILL.md +6 -4
package/plugins/ca-pi/SPRINT.md
CHANGED
|
@@ -73,6 +73,33 @@ explicit "decide it this way" steers here. STOP for explicit user approval of th
|
|
|
73
73
|
plan before autonomy begins. A blocking `[CONFIRM-NN]` is resolved here, with the user — never carried
|
|
74
74
|
into autonomous execution unresolved.
|
|
75
75
|
|
|
76
|
+
### Initial HTML approval sequence
|
|
77
|
+
|
|
78
|
+
Prepare one review packet containing the ready spec, ready draft plan, adversarial findings and
|
|
79
|
+
explicit delegation terms. The installed private pair adapter in
|
|
80
|
+
`<plugin-root>/includes/artifacts.md` owns the combined one-reply transaction:
|
|
81
|
+
|
|
82
|
+
1. Finish the spec as a ready draft. Let `writing-plans` use `_preflight_plan_authoring` with
|
|
83
|
+
`draft_for_pair: true` only for this full-lane initial sprint. Populate the same-slug plan as
|
|
84
|
+
`draft_preview`, validate both, and review their complete criteria, paths, tests and checkpoints.
|
|
85
|
+
Neither draft has execution authority. Do not separately approve or `plan-bind` this pair.
|
|
86
|
+
2. Arm both exact identities with `arm-sprint`. Include `--delegate-methods` only when the presented
|
|
87
|
+
terms explicitly ask the user to delegate existing task-method revisions. Present the exact returned reply;
|
|
88
|
+
it names both artifacts and `delegate-methods` or `approve-only`, not an ambiguous generic yes.
|
|
89
|
+
3. The existing qualified host observes that single reply. `sprint-approve` validates both frozen
|
|
90
|
+
definitions and commits approval plus plan binding in one recoverable native transaction.
|
|
91
|
+
Verify both current approved identities before execution. No execution before both approvals.
|
|
92
|
+
|
|
93
|
+
One reply approves the reviewed pair, not future unbounded work. `delegate-methods` does not grant
|
|
94
|
+
initial self-approval, product decisions, prerequisite satisfaction, new files, verification changes,
|
|
95
|
+
commit/push, provider/spending/disclosure/publication authority, or any security bypass. Keep
|
|
96
|
+
no per-feature interviews and no attended execution pauses. A declined, changed or unsupported pair
|
|
97
|
+
retains drafts; capability absence is not permission to invent a legacy shadow or receipt.
|
|
98
|
+
If an observed reply was interrupted, `resume-sprint` replays its stored transaction without asking
|
|
99
|
+
for the same reply again. An armed request with no observed reply cannot be resumed as approval.
|
|
100
|
+
The existing sequential single-artifact path remains available for `/feature` and older workflows;
|
|
101
|
+
Markdown retains its original approval contract.
|
|
102
|
+
|
|
76
103
|
**Recorded-intent read — BEFORE spec approval, fail-soft (ADR-0025):** consult
|
|
77
104
|
`decisions/decision-log.md`, the accepted-ADR index, the `plans/` artifacts' section headings, and
|
|
78
105
|
`open-questions.md`'s deferred sections — index-first, bodies only when the index names them
|
|
@@ -128,6 +155,26 @@ ambiguity, a trade-off, a non-obvious option — DECIDE rather than stop:
|
|
|
128
155
|
before `· confidence:`. The `low`-confidence
|
|
129
156
|
entries are exactly what the user reviews in the morning; nothing is hidden behind autonomy.
|
|
130
157
|
|
|
158
|
+
### Typed SMARTS method authority
|
|
159
|
+
|
|
160
|
+
After the pair's explicit `delegate-methods` approval, use the private `smarts-apply` producer for a
|
|
161
|
+
material change to an existing task's method steps. First perform SMARTS Step 0 and the existing
|
|
162
|
+
project/ADR/scope checks. Submit the actual options, six-lens comparison, selected option, strength
|
|
163
|
+
and rationale with the exact plan revision/model hash and the retained initial `grant_receipt`.
|
|
164
|
+
Use the private request shape and adapter in `<plugin-root>/includes/artifacts.md`; a pasted matrix
|
|
165
|
+
or an append-only log is not itself authority. A single evidenced option is allowed; an in-scope tie
|
|
166
|
+
uses the existing priorities rather than another user interview. Do not manufacture alternatives.
|
|
167
|
+
|
|
168
|
+
The producer retains all protected plan fields and requires the original user-approved scope. It can
|
|
169
|
+
change only existing task `steps`; paths, tests, criteria, dependencies, prerequisites, rollback and
|
|
170
|
+
checkpoint membership cannot expand. It quiesces affected writers by refusing `IN_PROGRESS` and
|
|
171
|
+
invalidates affected checkpoint/dependency proof before another attempt, without clearing `BLOCKED`
|
|
172
|
+
members or their recorded reasons. A blocked method revision
|
|
173
|
+
therefore resumes through fresh `eligible`, context tickets, verification and review, never auto-pass.
|
|
174
|
+
The original log still records material reasoning and source citations. No result implies accepted
|
|
175
|
+
work or independently proves the truth of model judgment. Changes outside the granted boundary use
|
|
176
|
+
their actual authority owner; this producer does not satisfy prerequisites or waive security stops.
|
|
177
|
+
|
|
131
178
|
### Hard gates — true stops, even mid-sprint
|
|
132
179
|
|
|
133
180
|
NEVER auto-decided. Halt and surface to the user:
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Third-party notices
|
|
2
|
+
|
|
3
|
+
## Go runtime and standard library
|
|
4
|
+
|
|
5
|
+
The packaged `ca-artifact` executable is built with Go and includes Go runtime
|
|
6
|
+
and standard-library code. The following notice is from the Go 1.27.1 toolchain
|
|
7
|
+
used by the native build. Upstream: https://go.dev/LICENSE.
|
|
8
|
+
|
|
9
|
+
This runtime notice does not determine the provenance of the separately authored
|
|
10
|
+
workflow skills. Their historical provenance review remains a separate task.
|
|
11
|
+
|
|
12
|
+
```text
|
|
13
|
+
Copyright 2009 The Go Authors.
|
|
14
|
+
|
|
15
|
+
Redistribution and use in source and binary forms, with or without
|
|
16
|
+
modification, are permitted provided that the following conditions are
|
|
17
|
+
met:
|
|
18
|
+
|
|
19
|
+
* Redistributions of source code must retain the above copyright
|
|
20
|
+
notice, this list of conditions and the following disclaimer.
|
|
21
|
+
* Redistributions in binary form must reproduce the above
|
|
22
|
+
copyright notice, this list of conditions and the following disclaimer
|
|
23
|
+
in the documentation and/or other materials provided with the
|
|
24
|
+
distribution.
|
|
25
|
+
* Neither the name of Google LLC nor the names of its
|
|
26
|
+
contributors may be used to endorse or promote products derived from
|
|
27
|
+
this software without specific prior written permission.
|
|
28
|
+
|
|
29
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
30
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
31
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
32
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
33
|
+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
34
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
35
|
+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
36
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
37
|
+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
38
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
39
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
40
|
+
```
|
|
@@ -125,7 +125,7 @@
|
|
|
125
125
|
},
|
|
126
126
|
"commit": {
|
|
127
127
|
"name": "commit",
|
|
128
|
-
"description": "
|
|
128
|
+
"description": "Create a verified local Git commit when committing changes is requested. Not for explaining commit history, drafting a message only, or postponing a commit. Applies every commit gate and never implies a push or PR.",
|
|
129
129
|
"skillPath": "skills/ca-commit/SKILL.md",
|
|
130
130
|
"visibility": "core",
|
|
131
131
|
"workflow": "ship",
|
|
@@ -227,7 +227,7 @@
|
|
|
227
227
|
},
|
|
228
228
|
"new-skill": {
|
|
229
229
|
"name": "new-skill",
|
|
230
|
-
"description": "
|
|
230
|
+
"description": "Assess a request for a new reusable codeArbiter skill, prove the uncovered gap, agree scope, author and integrate it. Questions and one-off tasks do not authorize adding a skill.",
|
|
231
231
|
"skillPath": "skills/ca-new-skill/SKILL.md",
|
|
232
232
|
"visibility": "advanced",
|
|
233
233
|
"workflow": "extend",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -6,32 +6,32 @@
|
|
|
6
6
|
"binaries": {
|
|
7
7
|
"darwin/amd64": {
|
|
8
8
|
"file": "ca-artifact-darwin-amd64",
|
|
9
|
-
"sha256": "
|
|
9
|
+
"sha256": "8e2a1f3026d5d9a8de36f3f748a7140ecf1ef8e768022aaa8745884e09551f9a",
|
|
10
10
|
"native_tested": true
|
|
11
11
|
},
|
|
12
12
|
"darwin/arm64": {
|
|
13
13
|
"file": "ca-artifact-darwin-arm64",
|
|
14
|
-
"sha256": "
|
|
14
|
+
"sha256": "cce4b1cd751ada483bffd2de53bd14cdfda50f5d7392b49ba3f020b58fc59da4",
|
|
15
15
|
"native_tested": true
|
|
16
16
|
},
|
|
17
17
|
"linux/amd64": {
|
|
18
18
|
"file": "ca-artifact-linux-amd64",
|
|
19
|
-
"sha256": "
|
|
19
|
+
"sha256": "7637fe233e8731f4f15ff36b2e80714edd7e6fd96117b41f911d0c8f46639615",
|
|
20
20
|
"native_tested": true
|
|
21
21
|
},
|
|
22
22
|
"linux/arm64": {
|
|
23
23
|
"file": "ca-artifact-linux-arm64",
|
|
24
|
-
"sha256": "
|
|
24
|
+
"sha256": "daa4ed9f1f577c59afd0250701959718f501799c204df01a92f00876c088f619",
|
|
25
25
|
"native_tested": true
|
|
26
26
|
},
|
|
27
27
|
"windows/amd64": {
|
|
28
28
|
"file": "ca-artifact-windows-amd64.exe",
|
|
29
|
-
"sha256": "
|
|
29
|
+
"sha256": "16a3a26c5c606fe77703cbc9ae69414cbbe93f2c50dda9301eb9784e2e842206",
|
|
30
30
|
"native_tested": true
|
|
31
31
|
},
|
|
32
32
|
"windows/arm64": {
|
|
33
33
|
"file": "ca-artifact-windows-arm64.exe",
|
|
34
|
-
"sha256": "
|
|
34
|
+
"sha256": "f64155cd951be94039ea85d4420b2d3bad75ebcb14e68aeb15be8ccf9ec1f690",
|
|
35
35
|
"native_tested": true
|
|
36
36
|
}
|
|
37
37
|
}
|
|
@@ -15,6 +15,8 @@ import sys
|
|
|
15
15
|
from typing import Any
|
|
16
16
|
|
|
17
17
|
import _artifactlib
|
|
18
|
+
import _artifactauthoritylib
|
|
19
|
+
import _artifactpromptlib
|
|
18
20
|
|
|
19
21
|
|
|
20
22
|
PENDING = Path(".codearbiter/.markers/pending-user-approval.json")
|
|
@@ -150,6 +152,13 @@ def arm_user_approval(
|
|
|
150
152
|
raise ApprovalError(
|
|
151
153
|
"PENDING_APPROVAL", "resolve or clear the existing approval request first"
|
|
152
154
|
) from exc
|
|
155
|
+
try:
|
|
156
|
+
_artifactpromptlib.register(
|
|
157
|
+
root, "approval", artifact_id, f"approve {artifact_id} {token}"
|
|
158
|
+
)
|
|
159
|
+
except _artifactpromptlib.PromptRouteError:
|
|
160
|
+
(root / PENDING).unlink()
|
|
161
|
+
raise
|
|
153
162
|
return {
|
|
154
163
|
"artifact_id": artifact_id,
|
|
155
164
|
"reply": f"approve {artifact_id} {token}",
|
|
@@ -182,6 +191,9 @@ def _load_pending(root: Path) -> dict[str, Any] | None:
|
|
|
182
191
|
return None
|
|
183
192
|
except (OSError, UnicodeError, ValueError) as exc:
|
|
184
193
|
raise ApprovalError("INVALID_PENDING_APPROVAL", "pending approval is unreadable") from exc
|
|
194
|
+
if isinstance(value, dict) and value.get("format") == "codearbiter.pending-user-approval/0.2.0":
|
|
195
|
+
import _sprintapprovallib
|
|
196
|
+
return _sprintapprovallib.validate_pending(value)
|
|
185
197
|
expected = {
|
|
186
198
|
"format", "artifact_id", "kind", "revision", "model_sha256",
|
|
187
199
|
"normative_sha256", "token_sha256",
|
|
@@ -216,7 +228,11 @@ def cancel_user_approval(root: str | Path, artifact_id: str) -> dict[str, Any]:
|
|
|
216
228
|
"PENDING_APPROVAL_MISMATCH",
|
|
217
229
|
"the pending approval request belongs to another artifact",
|
|
218
230
|
)
|
|
231
|
+
if pending["format"] == "codearbiter.pending-user-approval/0.2.0":
|
|
232
|
+
import _sprintapprovallib
|
|
233
|
+
return _sprintapprovallib.cancel(root, pending)
|
|
219
234
|
(root / PENDING).unlink()
|
|
235
|
+
_artifactpromptlib.unregister(root, "approval", artifact_id)
|
|
220
236
|
return {"artifact_id": artifact_id, "cancelled": True}
|
|
221
237
|
|
|
222
238
|
|
|
@@ -232,6 +248,9 @@ def consume_user_approval(
|
|
|
232
248
|
pending = _load_pending(root)
|
|
233
249
|
if pending is None or not isinstance(prompt, str):
|
|
234
250
|
return {"matched": False, "approved": False}
|
|
251
|
+
if pending["format"] == "codearbiter.pending-user-approval/0.2.0":
|
|
252
|
+
import _sprintapprovallib
|
|
253
|
+
return _sprintapprovallib.consume(root, client, pending, prompt, host=host, session_id=session_id)
|
|
235
254
|
parts = prompt.split(" ")
|
|
236
255
|
if len(parts) != 3 or parts[0] != "approve" or parts[1] != pending["artifact_id"]:
|
|
237
256
|
return {"matched": False, "approved": False}
|
|
@@ -250,7 +269,6 @@ def consume_user_approval(
|
|
|
250
269
|
_ready(client, current)
|
|
251
270
|
|
|
252
271
|
event = {
|
|
253
|
-
"format": "codearbiter.workflow-event/0.1.0",
|
|
254
272
|
"kind": "approval",
|
|
255
273
|
"authority_kind": "user_workflow",
|
|
256
274
|
"subject": {
|
|
@@ -264,20 +282,12 @@ def consume_user_approval(
|
|
|
264
282
|
"payload": {},
|
|
265
283
|
"source_text": prompt,
|
|
266
284
|
}
|
|
267
|
-
event_bytes = _canonical(event)
|
|
268
|
-
digest = hashlib.sha256(event_bytes).hexdigest()
|
|
269
|
-
source_rel = SOURCE_DIR / f"{digest}.json"
|
|
270
|
-
source = root / source_rel
|
|
271
285
|
try:
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
captured = client.call(
|
|
278
|
-
"capture",
|
|
279
|
-
{"source_ref": source_rel.as_posix(), "source_sha256": digest},
|
|
280
|
-
)
|
|
286
|
+
captured = _artifactauthoritylib.capture_user_prompt(
|
|
287
|
+
root, client, event, host=host, session_id=session_id,
|
|
288
|
+
)
|
|
289
|
+
except _artifactauthoritylib.AuthorityError as exc:
|
|
290
|
+
raise ApprovalError("INVALID_AUTHORITY_SOURCE", str(exc)) from exc
|
|
281
291
|
receipt = captured.get("receipt")
|
|
282
292
|
if not isinstance(receipt, str) or not receipt:
|
|
283
293
|
raise ApprovalError("INVALID_RECEIPT", "capture returned no receipt")
|
|
@@ -285,7 +295,7 @@ def consume_user_approval(
|
|
|
285
295
|
"approve",
|
|
286
296
|
{
|
|
287
297
|
"artifact_id": current["artifact_id"],
|
|
288
|
-
"operation_id": f"host-user-approval-{
|
|
298
|
+
"operation_id": f"host-user-approval-{hashlib.sha256(_canonical(event)).hexdigest()[:24]}",
|
|
289
299
|
"expected": {
|
|
290
300
|
"revision": current["revision"],
|
|
291
301
|
"model_sha256": current["model_sha256"],
|
|
@@ -294,11 +304,12 @@ def consume_user_approval(
|
|
|
294
304
|
},
|
|
295
305
|
)
|
|
296
306
|
(root / PENDING).unlink()
|
|
307
|
+
_artifactpromptlib.unregister(root, "approval", current["artifact_id"])
|
|
297
308
|
return {
|
|
298
309
|
"matched": True,
|
|
299
310
|
"approved": True,
|
|
300
311
|
"artifact_id": current["artifact_id"],
|
|
301
|
-
"authority_source":
|
|
312
|
+
"authority_source": captured["authority_source"],
|
|
302
313
|
"receipt": receipt,
|
|
303
314
|
"revision": approved.get("revision"),
|
|
304
315
|
}
|
|
@@ -306,17 +317,20 @@ def consume_user_approval(
|
|
|
306
317
|
|
|
307
318
|
def consume_from_hook(*, root: str | Path, plugin_root: str | Path, prompt: str,
|
|
308
319
|
host: str, session_id: str) -> str:
|
|
309
|
-
if not (Path(root) / PENDING).exists():
|
|
310
|
-
return ""
|
|
311
320
|
try:
|
|
321
|
+
routed = _artifactpromptlib.resolve("approval", prompt)
|
|
322
|
+
root = routed or Path(root)
|
|
323
|
+
if not (Path(root) / PENDING).exists():
|
|
324
|
+
return ""
|
|
312
325
|
client = _artifactlib.ArtifactClient(
|
|
313
326
|
root, Path(plugin_root) / "helpers" / "artifacts"
|
|
314
327
|
)
|
|
315
328
|
result = consume_user_approval(
|
|
316
329
|
root, client, prompt, host=host, session_id=session_id
|
|
317
330
|
)
|
|
318
|
-
except (ApprovalError, _artifactlib.ArtifactError,
|
|
319
|
-
|
|
331
|
+
except (ApprovalError, _artifactlib.ArtifactError,
|
|
332
|
+
_artifactpromptlib.PromptRouteError, OSError) as exc:
|
|
333
|
+
if isinstance(prompt, str) and prompt.startswith(("approve ", "approve-sprint ")):
|
|
320
334
|
return f"codeArbiter: approval capture failed: {exc}"
|
|
321
335
|
return ""
|
|
322
336
|
if not result.get("approved"):
|
|
@@ -336,6 +350,17 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
336
350
|
cancel = sub.add_parser("cancel")
|
|
337
351
|
cancel.add_argument("--root", required=True)
|
|
338
352
|
cancel.add_argument("--artifact-id", required=True)
|
|
353
|
+
pair = sub.add_parser("arm-sprint")
|
|
354
|
+
pair.add_argument("--root", required=True)
|
|
355
|
+
pair.add_argument("--spec-id", required=True)
|
|
356
|
+
pair.add_argument("--plan-id", required=True)
|
|
357
|
+
pair.add_argument("--delegate-methods", action="store_true")
|
|
358
|
+
resume = sub.add_parser("resume-sprint")
|
|
359
|
+
resume.add_argument("--root", required=True)
|
|
360
|
+
resume.add_argument("--plan-id", required=True)
|
|
361
|
+
smarts = sub.add_parser("smarts")
|
|
362
|
+
smarts.add_argument("--root", required=True)
|
|
363
|
+
smarts.add_argument("--request-file", required=True)
|
|
339
364
|
args = parser.parse_args(argv)
|
|
340
365
|
if args.command == "cancel":
|
|
341
366
|
print(json.dumps(cancel_user_approval(args.root, args.artifact_id)))
|
|
@@ -343,13 +368,24 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
343
368
|
client = _artifactlib.ArtifactClient(
|
|
344
369
|
args.root, _artifactlib.helper_installation(__file__)
|
|
345
370
|
)
|
|
346
|
-
|
|
371
|
+
if args.command == "smarts":
|
|
372
|
+
import _sprintapprovallib
|
|
373
|
+
print(json.dumps(_sprintapprovallib.apply_decision(client, args.request_file)))
|
|
374
|
+
return 0
|
|
375
|
+
if args.command in {"arm-sprint", "resume-sprint"}:
|
|
376
|
+
import _sprintapprovallib
|
|
377
|
+
result = (_sprintapprovallib.arm(args.root, client, args.spec_id, args.plan_id, delegate_methods=args.delegate_methods)
|
|
378
|
+
if args.command == "arm-sprint" else _sprintapprovallib.resume(args.root, client, args.plan_id))
|
|
379
|
+
else:
|
|
380
|
+
result = arm_user_approval(args.root, client, args.artifact_id)
|
|
381
|
+
print(json.dumps(result))
|
|
347
382
|
return 0
|
|
348
383
|
|
|
349
384
|
|
|
350
385
|
if __name__ == "__main__":
|
|
351
386
|
try:
|
|
352
387
|
raise SystemExit(main())
|
|
353
|
-
except (ApprovalError, _artifactlib.ArtifactError
|
|
388
|
+
except (ApprovalError, _artifactlib.ArtifactError,
|
|
389
|
+
_artifactpromptlib.PromptRouteError) as exc:
|
|
354
390
|
sys.stderr.write(str(exc) + "\n")
|
|
355
391
|
raise SystemExit(1)
|