@markjaquith/agency 2.71.13 → 2.71.15

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markjaquith/agency",
3
- "version": "2.71.13",
3
+ "version": "2.71.15",
4
4
  "description": "Manage agentic work across repositories with durable workbases",
5
5
  "keywords": [
6
6
  "agents",
@@ -66,7 +66,9 @@
66
66
  "preuninstall": "bun scripts/install-pi-extension.ts uninstall",
67
67
  "benchmark:act": "bun scripts/benchmark-act.ts",
68
68
  "benchmark:pr": "bun scripts/benchmark-pr.ts",
69
+ "benchmark:release": "bun scripts/benchmark-release.ts",
69
70
  "benchmark:status": "bun scripts/benchmark-status.ts",
71
+ "benchmark:next": "bun scripts/benchmark-next.ts",
70
72
  "benchmark:init": "bun scripts/benchmark-init.ts",
71
73
  "benchmark:workbase": "bun scripts/benchmark-workbase.ts",
72
74
  "benchmark:doctor": "bun scripts/benchmark-doctor.ts",
@@ -265,7 +265,6 @@ describe("claim service", () => {
265
265
  )
266
266
  expect(inspected.data).toMatchObject({ branch: "phase/target" })
267
267
  })
268
-
269
268
  test("serializes concurrent claims and allows expired ownership replacement", async () => {
270
269
  const initial = await inspect()
271
270
  const attempts = await Promise.allSettled([
@@ -339,7 +339,8 @@ export class GraphService extends Effect.Service<GraphService>()(
339
339
  })
340
340
 
341
341
  const validation =
342
- options.validation ?? (yield* workbase.validate(root))
342
+ options.validation ??
343
+ (yield* workbase.validate(root, { includeDocuments: true }))
343
344
  const validationIssuesByPath = Map.groupBy(
344
345
  validation.issues,
345
346
  (issue) => issue.path,
@@ -65,24 +65,19 @@ const isWorkTarget = (node: GraphNode) =>
65
65
 
66
66
  const itemFor = (
67
67
  node: ExecutionNode,
68
- graph: AgencyGraph,
68
+ tasks: ReadonlyMap<string, Extract<GraphNode, { readonly kind: "task" }>>,
69
+ executionsByTask: ReadonlyMap<string, readonly ExecutionNode[]>,
69
70
  rank: number,
70
71
  ): NextItem => {
71
- const task = graph.nodes.find(
72
- (candidate) =>
73
- candidate.kind === "task" && candidate.key === node.data.taskId,
74
- )
72
+ const task = tasks.get(node.data.taskId)
75
73
  const epicId =
76
74
  task?.kind === "task" && typeof task.data.epic === "string"
77
75
  ? task.data.epic
78
76
  : undefined
79
77
  const dependentIds = new Set(node.dependents)
80
78
  if ("phaseId" in node.data && node.data.phaseId) {
81
- const siblings = graph.nodes.filter(
82
- (candidate): candidate is ExecutionNode =>
83
- candidate.kind === "execution-unit" &&
84
- candidate.data.taskId === node.data.taskId &&
85
- candidate.id !== node.id,
79
+ const siblings = (executionsByTask.get(node.data.taskId) ?? []).filter(
80
+ (candidate) => candidate.id !== node.id,
86
81
  )
87
82
  if (siblings.every((sibling) => sibling.status === "done")) {
88
83
  for (const dependent of task?.dependents ?? [])
@@ -113,16 +108,27 @@ const itemFor = (
113
108
  }
114
109
  }
115
110
 
116
- const rankedItems = (graph: AgencyGraph) =>
117
- graph.nodes
118
- .filter((node): node is ExecutionNode => node.kind === "execution-unit")
119
- .map((node) => itemFor(node, graph, 0))
111
+ const rankedItems = (graph: AgencyGraph) => {
112
+ const tasks = new Map<string, Extract<GraphNode, { readonly kind: "task" }>>()
113
+ const executionsByTask = new Map<string, ExecutionNode[]>()
114
+ const executions: ExecutionNode[] = []
115
+ for (const node of graph.nodes) {
116
+ if (node.kind === "task") tasks.set(node.key, node)
117
+ if (node.kind !== "execution-unit") continue
118
+ executions.push(node)
119
+ const siblings = executionsByTask.get(node.data.taskId)
120
+ if (siblings) siblings.push(node)
121
+ else executionsByTask.set(node.data.taskId, [node])
122
+ }
123
+ return executions
124
+ .map((node) => itemFor(node, tasks, executionsByTask, 0))
120
125
  .sort(
121
126
  (left, right) =>
122
127
  right.priority.dependentCount - left.priority.dependentCount ||
123
128
  left.key.localeCompare(right.key),
124
129
  )
125
130
  .map((item, index) => ({ ...item, rank: index + 1 }))
131
+ }
126
132
 
127
133
  const guardMessage = (
128
134
  action: "work" | "pr",