fix(bug-verify-sonnet@1): agent self-transitions flow_state, remove dead verdict-tx node
verdict-tx (kind: script) never worked: script nodes are harness-exempt (WF-COMP-6/MN-38) and run in their own empty container, so it could never credentially read /workspace/verdict from the agent's node. Option 3: give the agent node's own composite (planning-sonnet-repo) a cp-service-token/v1 layer, and have the agent PATCH its own item's flow_state (verified|rejected) to the CP directly as its last step, before task_complete. Removes verdict-tx entirely. See agent-runtimes work item 88ecd23e and spec/typed-workflows.md WF-COMP-25 (agent-runtimes commit 8972d266) for the finalize.py precedence fix this depends on (ambiguous pipe-separated output.state must never be auto-PATCHed over the agent's own value). Claude-Session: https://claude.ai/code/session_01U3biMxRhFGkwtf4jVTNjcj
This commit is contained in:
@@ -8,3 +8,8 @@ layers:
|
|||||||
- context: anthropic-cloud-paul-oauth/v1
|
- context: anthropic-cloud-paul-oauth/v1
|
||||||
- context: gitea-ssh/v1
|
- context: gitea-ssh/v1
|
||||||
- context: agent-repo/v1
|
- context: agent-repo/v1
|
||||||
|
# AU-51/AU-51b: this composite backs bug-verify-sonnet@1, whose agent node
|
||||||
|
# self-transitions its own item's flow_state (PATCH /v1/work-items/{id})
|
||||||
|
# as its final step — see work item 88ecd23e ("agent self-transition"
|
||||||
|
# pattern, spec/typed-workflows.md). Needs a CP write credential.
|
||||||
|
- context: cp-service-token/v1
|
||||||
|
|||||||
@@ -14,6 +14,21 @@ scope_budget:
|
|||||||
lines_diff_max: 400
|
lines_diff_max: 400
|
||||||
wall_clock_seconds_max: 1800
|
wall_clock_seconds_max: 1800
|
||||||
nodes:
|
nodes:
|
||||||
|
# NOTE (2026-09-09, work item 88ecd23e): the `verdict-tx` script node that
|
||||||
|
# used to follow this one has been REMOVED. `kind: script` nodes are
|
||||||
|
# harness-exempt (WF-COMP-6 / MN-38) — they run in their own empty
|
||||||
|
# container with no credentialed way to clone the agent's branch or read
|
||||||
|
# /workspace/verdict, so verdict-tx never actually worked (it always ran
|
||||||
|
# against its own empty /workspace). Replaced with the "agent
|
||||||
|
# self-transition" pattern (spec/typed-workflows.md): this node's own
|
||||||
|
# `cp-service-token/v1` layer (via the `planning-sonnet-repo` composite)
|
||||||
|
# gives it CP write credentials, so the agent PATCHes its own item's
|
||||||
|
# flow_state directly as its final step, instead of relying on a second
|
||||||
|
# node to read a hand-off file. finalize_run's output.state auto-advance
|
||||||
|
# is intentionally disabled for this template (its `output.state` is the
|
||||||
|
# pipe-separated "verified|rejected" — finalize.py treats any
|
||||||
|
# pipe-separated output.state as schema-validation-only, never a literal
|
||||||
|
# value to PATCH, so it never clobbers the value set below).
|
||||||
- id: agent
|
- id: agent
|
||||||
kind: agent
|
kind: agent
|
||||||
template: planning-sonnet-repo
|
template: planning-sonnet-repo
|
||||||
@@ -21,6 +36,7 @@ nodes:
|
|||||||
runtime_env:
|
runtime_env:
|
||||||
AGENT_REPO_URL: "git@gitea.oreillyit.nz-ai-enablement:skynet/agent-runtimes-agents.git"
|
AGENT_REPO_URL: "git@gitea.oreillyit.nz-ai-enablement:skynet/agent-runtimes-agents.git"
|
||||||
AGENT_BRANCH: "bug-verify/${item.uuid}"
|
AGENT_BRANCH: "bug-verify/${item.uuid}"
|
||||||
|
CP_URL: "http://controlplane.agent-runtimes.svc.cluster.local:8100"
|
||||||
prompt: |
|
prompt: |
|
||||||
The agent-runtimes project repo is cloned at /workspace/project.
|
The agent-runtimes project repo is cloned at /workspace/project.
|
||||||
Change to that directory before doing any work.
|
Change to that directory before doing any work.
|
||||||
@@ -49,24 +65,37 @@ nodes:
|
|||||||
- `## Verdict` — exactly one of `verified` or `rejected`
|
- `## Verdict` — exactly one of `verified` or `rejected`
|
||||||
- `## Rationale` — why you reached that verdict
|
- `## Rationale` — why you reached that verdict
|
||||||
4. Commit and push the verification artifact on this branch.
|
4. Commit and push the verification artifact on this branch.
|
||||||
5. Write the bare verdict token — exactly `verified` or exactly
|
5. Transition this work item's own flow_state to your verdict by
|
||||||
`rejected`, nothing else, no trailing whitespace or punctuation —
|
PATCHing the control plane directly — you have a scoped CP
|
||||||
to /workspace/verdict. This file is NOT committed to the repo.
|
write credential for exactly this (`CP_SERVICE_TOKEN_FILE`,
|
||||||
(NOTE 2026-09-06: this SHOULD move to scratchpad/verdict,
|
`CP_URL`). Set `flow_state` to exactly `verified` or exactly
|
||||||
committed+pushed, once verdict-tx can clone the branch to read it
|
`rejected` (matching the `## Verdict` you wrote above) — no other
|
||||||
back — see the runtime_env note on the verdict-tx node below.
|
value is accepted. Run:
|
||||||
Left as the working /workspace/verdict contract for now.)
|
|
||||||
6. Call task_complete.
|
```
|
||||||
- id: verdict-tx
|
python3 - <<'PY'
|
||||||
kind: script
|
import json, os, urllib.request
|
||||||
cmd: scripts/workflow/state-tx-verdict
|
|
||||||
depends_on: [agent]
|
VERDICT = "verified" # or "rejected" — must match your ## Verdict
|
||||||
runtime_env:
|
ITEM_UUID = "${item.uuid}"
|
||||||
STATE_TX_ALLOWED_STATES: "verified,rejected"
|
|
||||||
# NOTE (2026-09-06): scratchpad/verdict cross-node wiring is NOT yet
|
token = open(os.environ["CP_SERVICE_TOKEN_FILE"]).read().strip()
|
||||||
# live — script tasks (dispatcher/task_manager.py::_run_script_task)
|
url = os.environ["CP_URL"].rstrip("/") + f"/v1/work-items/{ITEM_UUID}"
|
||||||
# have no credentialed way to clone the agent's branch (the per-task
|
body = json.dumps({
|
||||||
# SSH key is provisioned through the full ESO/account harness
|
"flow_state": VERDICT,
|
||||||
# resolution pipeline, which script tasks deliberately bypass). Left
|
"description": f"bug-verify-sonnet@1: verdict={VERDICT}",
|
||||||
# at the /workspace/verdict default pending that follow-up; see
|
}).encode()
|
||||||
# spec/bugs or the M-something item tracking it.
|
req = urllib.request.Request(url, data=body, method="PATCH", headers={
|
||||||
|
"Authorization": f"Bearer {token}",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Idempotency-Key": f"bug-verify-verdict-{ITEM_UUID}",
|
||||||
|
})
|
||||||
|
with urllib.request.urlopen(req, timeout=30) as resp:
|
||||||
|
print(resp.status, resp.read().decode())
|
||||||
|
PY
|
||||||
|
```
|
||||||
|
|
||||||
|
Replace `VERDICT` with your actual verdict before running. This is
|
||||||
|
the ONLY code you may run outside the investigation itself — do
|
||||||
|
not use this credential for anything else.
|
||||||
|
6. Call task_complete only after the PATCH above returns 200.
|
||||||
|
|||||||
Reference in New Issue
Block a user