agents-relay 2.0.113 → 2.0.115
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.
|
@@ -100,7 +100,7 @@ export class ReconcilerRuntimeBase {
|
|
|
100
100
|
const task = (await this.store.load(event.job_id)).tasks.find(item => item.id === event.task_id);
|
|
101
101
|
const normalized = task?.agentName === 'reviewer' ? normalizeReviewerTerminalEvent(event) : null;
|
|
102
102
|
if (normalized)
|
|
103
|
-
return this.applyReviewEvent(normalized);
|
|
103
|
+
return normalized.type === 'task.failed' ? this.applyTerminalEvent(normalized) : this.applyReviewEvent(normalized);
|
|
104
104
|
}
|
|
105
105
|
if (['task.completed', 'task.failed', 'task.blocked', 'task.cancelled'].includes(event.type)) {
|
|
106
106
|
const result = await this.applyTerminalEvent(event);
|
|
@@ -110,7 +110,9 @@ export class ReconcilerRuntimeBase {
|
|
|
110
110
|
return durable?.state === 'FAILED' && durable.executionHistory?.some(history => history.id === event.data?.executionId)
|
|
111
111
|
? { applied: true, reconcile: true, reason: 'watchdog.failure-fact' } : result;
|
|
112
112
|
}
|
|
113
|
-
if (
|
|
113
|
+
if (event.type === 'review.blocked')
|
|
114
|
+
return this.applyTerminalEvent({ ...event, type: 'task.failed', data: { ...event.data, reason: 'review_evidence_unavailable' } });
|
|
115
|
+
if (['review.started', 'review.approved', 'review.changes_required'].includes(event.type))
|
|
114
116
|
return this.applyReviewEvent(event);
|
|
115
117
|
if (event.type === 'task.interactive_decision')
|
|
116
118
|
return this.applyHostInvocationEvent(event);
|
|
@@ -399,6 +401,8 @@ export class ReconcilerRuntimeBase {
|
|
|
399
401
|
eligible: (_job, task) => {
|
|
400
402
|
if (!['codex', 'chatgpt', 'orchestrator'].includes(task.adapter))
|
|
401
403
|
return false;
|
|
404
|
+
if (event.type === 'task.blocked' && (!trustedInternal || task.agentName !== 'troubleshooter') && task.interactiveInvocation?.status !== 'awaiting_decision')
|
|
405
|
+
return false;
|
|
402
406
|
if (task.agentName === 'reviewer' && event.type === 'task.completed')
|
|
403
407
|
return false;
|
|
404
408
|
if (event.type === 'task.completed' && task.interactiveInvocation?.status !== undefined && task.interactiveInvocation.status !== 'approved')
|
|
@@ -474,7 +478,7 @@ export class ReconcilerRuntimeBase {
|
|
|
474
478
|
if (event.type === 'task.completed')
|
|
475
479
|
await this.deliverContinuation(transition.job, transition.task);
|
|
476
480
|
const reviewWorker = transition.task.agentName === 'reviewer';
|
|
477
|
-
return { applied: true, reconcile: !reviewWorker, reason: reviewWorker ? `${event.type}.review-worker` : event.type, reconcileMode: reviewWorker ? undefined : 'detached' };
|
|
481
|
+
return { applied: true, reconcile: !reviewWorker || event.type === 'task.failed', reason: reviewWorker ? `${event.type}.review-worker` : event.type, reconcileMode: reviewWorker ? undefined : 'detached' };
|
|
478
482
|
}
|
|
479
483
|
terminalWait(taskId, executionId, launchBarrier) {
|
|
480
484
|
let resolve;
|
|
@@ -9,7 +9,7 @@ export function normalizeReviewerTerminalEvent(event) {
|
|
|
9
9
|
const raw = data.verdict;
|
|
10
10
|
const type = raw === 'approved' || raw === 'pass' ? 'review.approved'
|
|
11
11
|
: raw === 'changes-required' || raw === 'changes_required' ? 'review.changes_required'
|
|
12
|
-
: raw === 'blocked' ? '
|
|
12
|
+
: raw === 'blocked' ? 'task.failed' : null;
|
|
13
13
|
if (!type)
|
|
14
14
|
return null;
|
|
15
15
|
const outcome = record(data.outcome);
|
|
@@ -24,6 +24,8 @@ export function normalizeReviewerTerminalEvent(event) {
|
|
|
24
24
|
return null;
|
|
25
25
|
const existingFindings = outcome.blocking_findings ?? outcome.blockingFindings;
|
|
26
26
|
const findings = existingFindings ?? (Array.isArray(data.findings) ? data.findings : undefined);
|
|
27
|
+
if (type === 'task.failed')
|
|
28
|
+
return { ...event, type, message: event.message || 'Reviewer validation unavailable', data: { ...data, reason: 'review_evidence_unavailable' } };
|
|
27
29
|
return { ...event, type, data: { ...data, outcome: {
|
|
28
30
|
...outcome, ...(head ? { head_sha: head } : {}),
|
|
29
31
|
...(findings !== undefined && existingFindings === undefined ? { blocking_findings: findings } : {}),
|
package/package.json
CHANGED
|
@@ -11,19 +11,19 @@ Review exactly the immutable target/version specified by the Review Task. Do not
|
|
|
11
11
|
|
|
12
12
|
## Review Scope
|
|
13
13
|
|
|
14
|
-
Reconstruct all material acceptance requirements from the durable Job objective and Task, then evaluate each with direct evidence. Check correctness, completeness, provenance, quality, regressions, explicit approvals and externally observable outcomes where applicable. Missing evidence is
|
|
14
|
+
Reconstruct all material acceptance requirements from the durable Job objective and Task, then evaluate each with direct evidence. Check correctness, completeness, provenance, quality, regressions, explicit approvals and externally observable outcomes where applicable. Missing evidence is not PASS. If validation cannot complete, report task.failed. Keep review independent of implementation work.
|
|
15
15
|
|
|
16
16
|
## Review Decision
|
|
17
17
|
|
|
18
|
-
Return a concrete approved
|
|
18
|
+
Return a concrete approved or changes-required verdict tied to the declared immutable target, with attributed findings, severity and remediation steps. Do not alter artifacts, generate approvals on behalf of users, or perform publication, merges or external actions. Relay owns the review lifecycle and Task/Job completion.
|
|
19
19
|
|
|
20
20
|
## Unified execution event
|
|
21
21
|
|
|
22
22
|
After completing the review, publish **`task.completed`**, including `data.verdict`
|
|
23
|
-
(`approved
|
|
23
|
+
(`approved` or `changes-required`), the **exact immutable**
|
|
24
24
|
`data.head_sha`, and actionable `data.findings` for changes required. A
|
|
25
25
|
negative verdict is a successful review, not `task.failed`. If review
|
|
26
|
-
execution fails
|
|
26
|
+
execution fails or required validation evidence is unavailable, publish `task.failed`.
|
|
27
27
|
Never emit `review.*` as the agent's terminal event. The event source must
|
|
28
28
|
match the execution identity supplied by Relay. See
|
|
29
29
|
`../contracts/event-contract.md`.
|
|
@@ -16,7 +16,7 @@ Every Implementation, Reviewer, and Troubleshooter execution publishes `task.sta
|
|
|
16
16
|
| Role | `task.completed.data` | Relay action |
|
|
17
17
|
| --- | --- | --- |
|
|
18
18
|
| Implementation | Evidence of output/artifact, validation, and summary as required by the Task | Persist Task success and continue dependencies/review |
|
|
19
|
-
| Reviewer | `verdict` (`approved
|
|
19
|
+
| Reviewer | `verdict` (`approved` or `changes-required`), exact immutable `head_sha`, actionable `findings` as necessary | Validate current immutable review target and apply verdict; defects are a successful Reviewer execution, not `task.failed` |
|
|
20
20
|
| Troubleshooter | Recovery action and durable evidence of verified original Task retry, blocker-Job handoff, or other authorized recovery | Complete recovery Task only; original Task state changes through separately authorized Relay operations |
|
|
21
21
|
|
|
22
22
|
A Reviewer must **not** publish unstructured `task.completed`: missing verdict or immutable head is invalid. Relay normalizes an authenticated structured Reviewer terminal event into its internal Review decision; native `review.*` events may be accepted for backward compatibility.
|
|
@@ -28,3 +28,7 @@ Only a real user action merits escalation. Troubleshooter invokes the Relay esca
|
|
|
28
28
|
When the human responds, the **Troubleshooter Task** is authoritatively unblocked and resumed with its prior context plus the response. Troubleshooter independently verifies resolution, requests an authorized original Task recovery, and only then publishes its own `task.completed`. If unresolved, it continues diagnosis or escalates again; human assertion alone is not technical verification.
|
|
29
29
|
|
|
30
30
|
See [task-recovery-flows.md](task-recovery-flows.md) for unified architecture, overall flow, failure recovery, and post-blocked resumption.
|
|
31
|
+
|
|
32
|
+
Reviewer unavailable evidence is an execution failure (`task.failed`), not a blocked Task. Legacy Reviewer verdict `blocked` is normalized to failure and must dispatch Troubleshooter. Only Relay blocks a Troubleshooter during human escalation.
|
|
33
|
+
|
|
34
|
+
A host-mediated interactive invocation is a separate Relay-controlled wait. It requires an already-bound `interactiveInvocation` with status `awaiting_decision`. It is not permission for a Worker or Reviewer to choose a blocked terminal outcome.
|