@arbiterforge/ca-pi 0.14.10 → 0.14.12
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 +7 -2
- package/package.json +1 -1
- package/plugins/ca-pi/CHANGELOG.md +28 -0
- package/plugins/ca-pi/SKILLS.md +2 -2
- package/plugins/ca-pi/SPRINT.md +47 -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 +1686 -0
- package/plugins/ca-pi/hooks/_artifactlib.py +14 -4
- 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/_sprintapprovallib.py +302 -0
- package/plugins/ca-pi/hooks/artifact-authority-hook.py +72 -0
- package/plugins/ca-pi/hooks/artifact-authority.py +80 -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/includes/artifacts.md +99 -12
- 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/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/README.md
CHANGED
|
@@ -10,7 +10,7 @@ project context. You decide. codeArbiter enforces.
|
|
|
10
10
|
<img alt="Claude Code plugin" src="https://img.shields.io/badge/Claude_Code-plugin-d97757">
|
|
11
11
|
<img alt="Codex plugin" src="https://img.shields.io/badge/OpenAI_Codex-plugin-10a37f">
|
|
12
12
|
<img alt="Pi Feature Forge preview" src="https://img.shields.io/badge/ca--pi-Feature_Forge_preview-d97757">
|
|
13
|
-
<img alt="version 2.21.
|
|
13
|
+
<img alt="version 2.21.12" src="https://img.shields.io/badge/version-2.21.12-2b7489">
|
|
14
14
|
<img alt="core lanes" src="https://img.shields.io/badge/core_lanes-18-555">
|
|
15
15
|
<img alt="skills" src="https://img.shields.io/badge/skills-23-555">
|
|
16
16
|
<img alt="agents" src="https://img.shields.io/badge/agents-19-555">
|
|
@@ -124,10 +124,15 @@ Current packaging and shared-core parity are continuously verified, while that h
|
|
|
124
124
|
stays labeled rather than being promoted to evidence for a newer adapter:
|
|
125
125
|
|
|
126
126
|
```text
|
|
127
|
-
codex plugin marketplace add arbiterForge/codeArbiter
|
|
127
|
+
codex plugin marketplace add arbiterForge/codeArbiter --ref ca-codex-marketplace
|
|
128
128
|
codex plugin add ca-codex@codearbiter
|
|
129
129
|
```
|
|
130
130
|
|
|
131
|
+
The `ca-codex-marketplace` branch is the promoted catalog. Each entry pins the
|
|
132
|
+
exact immutable Git commit assembled from the same qualified member set as the
|
|
133
|
+
release archive; `main` remains the development source tree and is not a
|
|
134
|
+
substitute for the promoted binary-bearing distribution.
|
|
135
|
+
|
|
131
136
|
Open `/hooks`, review and trust the `ca-codex` handlers, then start a fresh task. Run `$ca-init` and
|
|
132
137
|
`$ca-doctor`.
|
|
133
138
|
|
package/package.json
CHANGED
|
@@ -4,6 +4,34 @@ All notable changes to `ca-pi` are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.14.12] - 2026-09-23
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
- Add one-reply initial HTML sprint approval and explicitly delegated SMARTS
|
|
13
|
+
task-method revisions, with native atomic recovery and unchanged acceptance gates.
|
|
14
|
+
- Generate commit and new-skill public entries from the complete owning
|
|
15
|
+
procedures, retaining their private routine paths and exact gates.
|
|
16
|
+
- Preserve the caller's coherent sprint scope and required spec-to-plan
|
|
17
|
+
continuation without manufacturing method-selection approval questions.
|
|
18
|
+
- Distinguish initial artifact approval from existing delegation and require
|
|
19
|
+
the current qualified host-owned authority path; no new host support is implied.
|
|
20
|
+
- Keep complete authored HTML checkpoint membership across resume and review,
|
|
21
|
+
without adding attended execution pauses to autonomous sprint work.
|
|
22
|
+
|
|
23
|
+
## [0.14.11] - 2026-09-23
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- Package the shared closed artifact-authority and reconciliation kernel while
|
|
28
|
+
retaining fail-closed behavior for host observation seams that Pi does not
|
|
29
|
+
implement.
|
|
30
|
+
- Preserve typed workspace identity and durable reconciliation retry/cancel
|
|
31
|
+
behavior in the shared kernel without claiming unsupported Pi host authority.
|
|
32
|
+
- Reject unproven partial-commit and changed-parent recovery in the shared
|
|
33
|
+
kernel without claiming unsupported Pi host authority.
|
|
34
|
+
|
|
7
35
|
## [0.14.10] - 2026-09-22
|
|
8
36
|
|
|
9
37
|
### Fixed
|
package/plugins/ca-pi/SKILLS.md
CHANGED
|
@@ -58,7 +58,7 @@ skill is invoked — never bulk-read this directory.
|
|
|
58
58
|
|
|
59
59
|
| Skill | Purpose |
|
|
60
60
|
|---|---|
|
|
61
|
-
| `/ca-commit` |
|
|
61
|
+
| `/ca-commit` | 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. |
|
|
62
62
|
| `/ca-pr` | Open a pull request the only sanctioned way — clear every BLOCK-level review finding, then stage the PR. Never a direct write to the default branch. |
|
|
63
63
|
| `/ca-release` | Cut a release the only sanctioned way — derive the target's declared version policy from the commit log, roll its changelog, compose an annotated tag, and optionally publish its exact declared assets. Takes the declared target's name as its only argument, or --dry-run to preview one with no write. The only path to a version tag. |
|
|
64
64
|
|
|
@@ -107,7 +107,7 @@ skill is invoked — never bulk-read this directory.
|
|
|
107
107
|
|
|
108
108
|
| Skill | Purpose |
|
|
109
109
|
|---|---|
|
|
110
|
-
| `/ca-new-skill` |
|
|
110
|
+
| `/ca-new-skill` | 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. |
|
|
111
111
|
|
|
112
112
|
### Help
|
|
113
113
|
|
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:
|
|
@@ -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": "3fb697a6656fa88b6d6e3e7eadf4784be6d5f107582162879d22b6a59ea7221a",
|
|
10
10
|
"native_tested": true
|
|
11
11
|
},
|
|
12
12
|
"darwin/arm64": {
|
|
13
13
|
"file": "ca-artifact-darwin-arm64",
|
|
14
|
-
"sha256": "
|
|
14
|
+
"sha256": "19eee315a7ea89c9433679fe2aaa4329e43863f9aadba6806bdf8bc604f56af8",
|
|
15
15
|
"native_tested": true
|
|
16
16
|
},
|
|
17
17
|
"linux/amd64": {
|
|
18
18
|
"file": "ca-artifact-linux-amd64",
|
|
19
|
-
"sha256": "
|
|
19
|
+
"sha256": "104063987dddfacb23164a3e2989a6207127527065ed629d60620ab54918c8e0",
|
|
20
20
|
"native_tested": true
|
|
21
21
|
},
|
|
22
22
|
"linux/arm64": {
|
|
23
23
|
"file": "ca-artifact-linux-arm64",
|
|
24
|
-
"sha256": "
|
|
24
|
+
"sha256": "ff31ec48cc24317675084bf4f62865ca59ea35a64632fbf7bdd983e4d13a7f80",
|
|
25
25
|
"native_tested": true
|
|
26
26
|
},
|
|
27
27
|
"windows/amd64": {
|
|
28
28
|
"file": "ca-artifact-windows-amd64.exe",
|
|
29
|
-
"sha256": "
|
|
29
|
+
"sha256": "5cfb75794adccb8d48841184fa4696617dc7b70b4dbf75eb565c21f261512de1",
|
|
30
30
|
"native_tested": true
|
|
31
31
|
},
|
|
32
32
|
"windows/arm64": {
|
|
33
33
|
"file": "ca-artifact-windows-arm64.exe",
|
|
34
|
-
"sha256": "
|
|
34
|
+
"sha256": "b9a966ea1c1991e8d44bb8fde327dcd27ab75dcb2f370998139e60a0707f4baf",
|
|
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)
|