agents-relay 1.0.102 → 1.0.104

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.
@@ -0,0 +1,45 @@
1
+ import { tryTransitionTaskEvent } from '../scheduler.js';
2
+ /**
3
+ * Runtime primitive for applying one canonical Task-graph event to fresh durable state.
4
+ *
5
+ * This class owns serialization and persistence only. It does not decide lifecycle
6
+ * legality: the canonical Mermaid Task graph does that through tryTransitionTaskEvent.
7
+ */
8
+ export class DurableTaskTransitionRuntime {
9
+ store;
10
+ locks = new Map();
11
+ constructor(store) {
12
+ this.store = store;
13
+ }
14
+ async apply(jobId, taskId, event, options = {}) {
15
+ return this.withLock(`${jobId}/${taskId}`, async () => {
16
+ const job = await this.store.load(jobId);
17
+ const task = job.tasks.find(item => item.id === taskId);
18
+ if (!task || (options.eligible && !options.eligible(job, task)))
19
+ return null;
20
+ const from = task.state;
21
+ const decision = tryTransitionTaskEvent(task, event, options.facts?.(job, task) ?? {});
22
+ if (!decision.accepted || !decision.target)
23
+ return { job, task, from, decision };
24
+ await options.mutate?.(job, task, decision);
25
+ await this.store.saveTask(task);
26
+ return { job, task, from, decision };
27
+ });
28
+ }
29
+ async withLock(key, work) {
30
+ const previous = this.locks.get(key);
31
+ let release;
32
+ const current = new Promise(resolve => { release = resolve; });
33
+ this.locks.set(key, current);
34
+ if (previous)
35
+ await previous;
36
+ try {
37
+ return await work();
38
+ }
39
+ finally {
40
+ release();
41
+ if (this.locks.get(key) === current)
42
+ this.locks.delete(key);
43
+ }
44
+ }
45
+ }
@@ -37,3 +37,10 @@ export function applyJobWorkflowDecision(job, decision, timestamp = new Date().t
37
37
  job.state = decision.target;
38
38
  job.updatedAt = timestamp;
39
39
  }
40
+ /** Historical repair for records that stored derived runtime status as Job lifecycle. */
41
+ export function applyHistoricalJobCompatibilityRepair(job, target, timestamp = new Date().toISOString()) {
42
+ if (target !== 'COMPLETED' && target !== 'CANCELLED')
43
+ throw new Error(`Invalid historical Job repair target ${target}`);
44
+ job.state = target;
45
+ job.updatedAt = timestamp;
46
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agents-relay",
3
- "version": "1.0.102",
3
+ "version": "1.0.104",
4
4
  "description": "Durable async agent jobs coordinated through GitHub pull requests",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,24 @@
1
+ ---
2
+ name: implementation
3
+ description: Implement the assigned Agents Relay task in the managed checkout and verify the durable result.
4
+ capabilities: [implementation, local_repo, iterative_tools]
5
+ runtime: codex
6
+ delegation: [relay-child-task]
7
+ restrictions: [preserve-user-changes, no-unrelated-refactors]
8
+ ---
9
+
10
+ # Implementation Agent
11
+
12
+ Implement the assigned Task in the current managed checkout. Treat the durable
13
+ Job objective and Task input retrieved from GitHub as authoritative. Inspect the
14
+ existing design before editing, keep the change narrowly scoped, and preserve
15
+ unrelated user work.
16
+
17
+ Follow the shared Agents Relay and events-bus contracts. Publish the required
18
+ canonical `task.started` event before doing work, then exactly one terminal task
19
+ event after the declared output is durable. Use the exact execution source
20
+ identity supplied by Relay for every lifecycle event.
21
+
22
+ Run the most relevant tests and checks for the change. Do not claim completion
23
+ without durable implementation evidence, validation results, and a concise
24
+ summary of changed files and remaining risks.
@@ -58,6 +58,8 @@ Do not create separate Tasks merely for "analyze", "format", "call tool", "check
58
58
  ## Rules
59
59
 
60
60
  - Treat durable Job/Task state as authoritative.
61
+ - Discover visible agents from the resolved execution context before selecting an agent. Choose an existing visible agent only when it is appropriate for the Task; otherwise leave `agentName` unset. Agent discovery is runtime/context-specific, not a hardcoded global list.
62
+ - Build `agentGraph` nodes only from agents in the discovered visible-agent catalog. Every named graph agent must be visible in the resolved planning/execution context.
61
63
  - Never invent completed work or evidence.
62
64
  - First decide whether the objective is already satisfied.
63
65
  - If satisfied, return `objective_status: "satisfied"` and `next_tasks: []`.
@@ -14,20 +14,26 @@ stateDiagram-v2
14
14
  QUEUED --> BLOCKED: block
15
15
  QUEUED --> FAILED: fail
16
16
  QUEUED --> FAILED: effect.launchTask.failed
17
+ QUEUED --> FAILED: watchdog.failed
18
+ QUEUED --> FAILED: worker.delivery_failed
19
+ QUEUED --> FAILED: worker.start_ack_failed
17
20
  QUEUED --> CANCELLED: cancel
18
21
 
19
22
  RUNNING --> BLOCKED: task.blocked
20
23
  RUNNING --> SUCCEEDED: task.completed / mutation.clearError,mutation.clearFailureReason
21
24
  RUNNING --> FAILED: task.failed
25
+ RUNNING --> FAILED: watchdog.failed
22
26
  RUNNING --> CANCELLED: task.cancelled
23
27
 
24
28
  BLOCKED --> QUEUED: retry / mutation.clearError,mutation.clearFailureReason
25
29
  BLOCKED --> CANCELLED: cancel
26
30
 
27
31
  FAILED --> QUEUED: retry / mutation.clearError,mutation.clearFailureReason
28
- FAILED --> RUNNING: reconcile.started / mutation.clearError,mutation.clearFailureReason
29
- FAILED --> SUCCEEDED: reconcile.completed / mutation.clearError,mutation.clearFailureReason
30
- FAILED --> BLOCKED: reconcile.blocked
32
+ FAILED --> RUNNING: task.started [recoverableExecution] / mutation.clearError,mutation.clearFailureReason
33
+ FAILED --> SUCCEEDED: task.completed [recoverableExecution] / mutation.clearError,mutation.clearFailureReason
34
+ FAILED --> BLOCKED: task.blocked [recoverableExecution]
35
+ FAILED --> FAILED: task.failed [recoverableExecution]
36
+ FAILED --> CANCELLED: task.cancelled [recoverableExecution]
31
37
  FAILED --> CANCELLED: cancel
32
38
 
33
39
  SUCCEEDED --> [*]