agents-relay 1.0.173 → 1.0.175

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/dist/planner.js CHANGED
@@ -5,6 +5,15 @@ import { dirname, join } from 'node:path';
5
5
  import { storySizeTimeoutMs, taskOverallTimeoutMs } from './types.js';
6
6
  import { executionContextPrompt } from './execution-context.js';
7
7
  import { parseAgentGraph } from './agent-graph.js';
8
+ /** Business-task ownership only; planner rounds remain provenance records. */
9
+ export function semanticTaskTree(tasks) {
10
+ const work = tasks.filter(task => task.kind !== 'planner');
11
+ const ids = new Set(work.map(task => task.id));
12
+ return {
13
+ roots: work.filter(task => !task.parentTaskId || !ids.has(task.parentTaskId)).map(task => task.id),
14
+ tasks: work.map(task => ({ id: task.id, parent_task_id: task.parentTaskId, state: task.state, dependencies: [...task.dependencies], planning_decision_id: task.planningDecisionId, planning_round: task.planningRound, review: task.review })),
15
+ };
16
+ }
8
17
  function plannerTrigger(job, manual = false) {
9
18
  if (manual)
10
19
  return { source: 'manual' };
@@ -329,6 +338,7 @@ export function plannerInput(context) {
329
338
  previous_planner_task_id: context.previousPlannerTaskId,
330
339
  plan_trigger: context.trigger,
331
340
  legacy_change_cycle: context.job.changeCycle,
341
+ semantic_task_tree: semanticTaskTree(context.tasks),
332
342
  project: project ? { name: project.name, path: project.path } : undefined,
333
343
  visible_agents: visibleAgents ?? [],
334
344
  tasks: context.tasks.map(task => ({
@@ -109,8 +109,10 @@ export class Reconciler extends ReconcilerReviewBase {
109
109
  const previousState = job.state;
110
110
  const prState = await this.store.pullRequestState?.() ?? 'OPEN';
111
111
  const headSha = prState === 'OPEN' ? await this.currentHeadSha(job) : null;
112
- if (headSha)
112
+ if (headSha && job.headSha !== headSha) {
113
113
  job.headSha = headSha;
114
+ await this.store.saveJob(job);
115
+ }
114
116
  await this.invalidateStaleReview(job, headSha);
115
117
  const now = (this.options.now ?? new Date()).getTime();
116
118
  if (prState !== 'OPEN') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agents-relay",
3
- "version": "1.0.173",
3
+ "version": "1.0.175",
4
4
  "description": "Durable async agent jobs coordinated through GitHub pull requests",
5
5
  "type": "module",
6
6
  "bin": {
@@ -101,7 +101,7 @@ Direct orchestrator-created Tasks do not require a Plan. The orchestrator may cr
101
101
 
102
102
  For explicit `plan` and autonomous continuation, Relay invokes the same planner agent as a pure decision function. The planner receives durable Job/Task state, previous planner rounds, and resolved execution context, then returns structured `{ objective_status, assessment, next_tasks }` output. The planner does not call Relay CLI and does not persist Tasks itself.
103
103
 
104
- Each successful planner invocation is one real `plan-N` planning round. Relay persists that planner result, then creates the returned Tasks with lineage back to that planning round. Historical `planner-N` records remain readable. Only planner execution creates planner rounds; Relay never manufactures synthetic `plan-*` records for direct Task creation. In the dashboard, planner rounds are organizational/grouping nodes for the Tasks they produced.
104
+ Each successful planner invocation is one real `plan-N` planning round. Relay persists that planner result, then creates returned work Tasks with provenance back to that planning round. `parentTaskId` expresses semantic ownership among work Tasks; it is not inherited from the Plan and must never point to a `plan-N` record. `dependencies` independently express execution prerequisites. Historical `planner-N` records remain readable. Only planner execution creates planner rounds; Relay never manufactures synthetic `plan-*` records for direct Task creation. In the dashboard, planner rounds remain provenance/grouping metadata, not semantic parents.
105
105
 
106
106
  A zero-task autonomous Job remains idle. After a direct orchestrator-created initial batch completes, Relay may start the first real planner round. Fixed Jobs do not automatically create planner rounds.
107
107
 
@@ -34,6 +34,17 @@ Keep sibling Tasks at a comparable abstraction level. Do not mix a whole product
34
34
 
35
35
  The graph is the explanation for the decomposition: every emitted Task should map to a meaningful boundary in the graph, and important graph boundaries should not be omitted accidentally.
36
36
 
37
+ ### Semantic ownership vs execution flow
38
+
39
+ The planning graph and the durable Task tree are two different views:
40
+
41
+ - The graph and `dependencies` express execution flow and prerequisites.
42
+ - `parentTaskId` expresses semantic ownership of an artifact or milestone.
43
+ - A later planning round must inspect the existing Task tree and attach work to the existing artifact it changes. Do not turn a later round into a new root merely because its work follows an earlier Task.
44
+ - `plan-N` records are planning provenance, not business milestones, and must never be used as `parentTaskId`.
45
+
46
+ For example, produce `architecture-v2` as a root milestone, then place `architecture-review`, `architecture-revision-1`, and `architecture-rereview-1` under it. The revision may depend on the review, and the re-review may depend on the revision; those dependencies do not determine their semantic parent. An independent `graph-runtime-v2` milestone remains a root sibling. A troubleshooter belongs under the failed Task (or its artifact subtree), and specialist review work stays under its review/artifact context.
47
+
37
48
  ### Examples
38
49
 
39
50
  Prefer:
@@ -69,6 +80,7 @@ Do not create separate Tasks merely for "analyze", "format", "call tool", "check
69
80
  - When a Task depends on mutable repository or product state, distinguish a frozen evidence target from the current execution head. A SHA may freeze that Task's own review/source evidence, but do not copy an upstream SHA into a dependent release, deploy, publication, or other follow-on Task unless the objective explicitly requires that same frozen target. After dependencies complete, downstream Tasks must resolve and verify the current durable Job/PR head before acting.
70
81
  - When fresh UI, browser, store, runtime, or visual evidence is material to the Task outcome, say so explicitly in the Task input and require evidence from the real current state. Existing screenshots, prepared assets, or prior observations are not substitutes for fresh evidence unless the objective explicitly allows reuse.
71
82
  - When a Job needs multi-perspective review, use the visible `review-chair` agent or an Agent Graph to select specialist roles dynamically. Keep specialist Tasks as independent siblings against the same immutable target/version, and leave worker/model/provider routing to Relay.
83
+ - Treat `parentTaskId` as semantic ownership, not execution order. Select an existing non-planner Task as the parent when a later-round revision, re-review, specialist review, or troubleshooting Task belongs to that artifact/milestone; a terminal parent remains valid historical ownership. Use `dependencies` independently for prerequisites, including cross-parent dependencies. Never use a `plan-N` Task as a parent, and never invent a synthetic parent merely to group a planning round.
72
84
  - A Task describes what an agent must accomplish; never emit a shell command as a worker Task.
73
85
  - Use dependencies only for Task IDs inside the current Job, and only when execution order actually matters. Never encode cross-Job or cross-repository dependencies in `dependencies`.
74
86
  - When the current Job is a prerequisite for another durable Job/Task, emit that dependent in top-level `unblocks`. The current blocker Job owns this authoritative reverse relation. Dependent-side `blockedBy` is optional observability metadata and is not the source of truth. Use `resolutionMode: "merge"` when blocker PR merge is sufficient; use `"verified"` when publication, deployment, runtime health, human approval, or another post-merge fact must be verified.
@@ -22,6 +22,34 @@ For a newly created PR (`job create --head`), standalone objective Markdown is r
22
22
  Any task producer — orchestrator, planner, or nested task-producing agent — must follow this contract.
23
23
  Task producers choose semantic task properties such as objective, dependencies, worker requirements, priority, and `storySize`. They do not normally choose an adapter, provider/model, or raw timeout milliseconds.
24
24
 
25
+ ### Planning graph and semantic Task tree
26
+
27
+ The planning graph expresses execution flow. The Task tree expresses semantic
28
+ ownership. `dependencies` answer which durable outcomes must succeed before a
29
+ Task can run; `parentTaskId` answers which durable artifact, milestone, or
30
+ parent outcome the Task belongs to. These are independent relationships and
31
+ must not be inferred from one another.
32
+
33
+ For a multi-round artifact workflow, keep the business tree compact and
34
+ milestone-oriented:
35
+
36
+ ```text
37
+ Job
38
+ ├── Architecture v2
39
+ │ ├── Review
40
+ │ ├── Revision 1
41
+ │ └── Re-review 1
42
+ └── Graph Runtime v2
43
+ ```
44
+
45
+ The revision may depend on Review and Re-review may depend on Revision 1, but
46
+ both remain semantically owned by Architecture v2. A later Planner round must
47
+ inspect existing Tasks and attach review, change, validation-rerun, release
48
+ correction, or recovery work to the existing artifact subtree. An independent
49
+ milestone is a root sibling. `plan-N` records are planning provenance/history,
50
+ never semantic parents. Existing terminal Tasks are historical evidence and
51
+ must not be rewritten merely to improve the tree.
52
+
25
53
  ### Task input vs result
26
54
 
27
55
  A Task input records **what is known and what has already been decided before execution**. A Task result records **what execution discovered and what was actually done**.
@@ -98,6 +126,33 @@ For the ChatGPT Browser Worker guardian, for example, the Job defines `pass ->
98
126
 
99
127
  ### Optional Review Chair Tasks
100
128
 
129
+ ### Semantic Task tree and planning provenance
130
+
131
+ The planning graph, semantic Task tree, and dependency graph are separate:
132
+
133
+ ```text
134
+ plan-2 (planning provenance only)
135
+ ├─ revision (parentTaskId: milestone, dependencies: [review])
136
+ └─ re-review (parentTaskId: milestone, dependencies: [revision])
137
+ independent-milestone (parentTaskId: null, dependencies: [revision])
138
+ ```
139
+
140
+ `parentTaskId` answers which durable artifact or milestone owns this work. It
141
+ may point to an existing terminal work Task when a later planning round
142
+ continues that artifact, or to another work Task in the same batch. It must
143
+ never point to a `plan-N`/historical `planner-N` record and must not be used
144
+ just to group a round. `dependencies` answer what must finish first and may
145
+ cross semantic subtrees. Reviews, changes-required revisions, re-reviews,
146
+ specialist reviews, and troubleshooter recovery belong under the relevant
147
+ artifact/milestone; independent milestones remain roots. Planning provenance
148
+ is retained separately in `planningDecisionId` and `planningRound`, and
149
+ historical terminal Tasks are immutable.
150
+
151
+ Incorrect: make every generated Task a child of the current `plan-N`, or use
152
+ `parentTaskId` as a substitute for a dependency. Correct: attach a re-review
153
+ to the original milestone, set its dependency to the revision Task, and leave
154
+ the original milestone's terminal record unchanged.
155
+
101
156
  Projects may use the shared `review-chair` agent as a normal Task or Agent
102
157
  Graph node. The chair discovers specialist agent roles from the resolved
103
158
  visible-agent catalog, records selection reasons, and creates sibling durable