@markjaquith/agency 3.10.0 → 3.10.1

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/commands/act.ts +66 -23
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markjaquith/agency",
3
- "version": "3.10.0",
3
+ "version": "3.10.1",
4
4
  "description": "Manage agentic work across repositories with durable workbases",
5
5
  "keywords": [
6
6
  "agents",
@@ -161,6 +161,32 @@ const shellCommand = (argv: readonly string[]) =>
161
161
  )
162
162
  .join(" ")
163
163
  const available = (action: ActAction) => !action.blockedReason
164
+ const checkoutState = (inspection: {
165
+ readonly checkouts: readonly {
166
+ readonly exists: boolean
167
+ readonly path: string
168
+ readonly registeredPath: string | null
169
+ readonly dirty: boolean | null
170
+ }[]
171
+ readonly conflicts: readonly {
172
+ readonly kind: string
173
+ readonly message: string
174
+ }[]
175
+ }): ActCheckoutState => ({
176
+ paths: inspection.checkouts.flatMap((checkout) =>
177
+ checkout.exists
178
+ ? [checkout.path]
179
+ : checkout.registeredPath
180
+ ? [checkout.registeredPath]
181
+ : [],
182
+ ),
183
+ conflicts: inspection.conflicts
184
+ .filter((conflict) => conflict.kind !== "stale-registration")
185
+ .map((conflict) => conflict.message),
186
+ dirty: inspection.checkouts.some(
187
+ (checkout) => checkout.exists && checkout.dirty !== false,
188
+ ),
189
+ })
164
190
  const entitySummary = (node: ActEntity) => ({
165
191
  kind: node.kind,
166
192
  id: node.id,
@@ -329,32 +355,31 @@ const actStep = (
329
355
  include: ["workspace"],
330
356
  })
331
357
  const checkoutStates = new Map<string, ActCheckoutState>()
332
- const materialized = graph.nodes.some(
333
- (node) => node.kind === "execution-unit" && node.workspace?.materialized,
334
- )
335
- for (const inspection of materialized
336
- ? yield* worktrees.list(root, { materializedOnly: true })
337
- : []) {
358
+ for (const node of graph.nodes) {
359
+ if (node.kind !== "execution-unit" || !node.workspace?.materialized)
360
+ continue
338
361
  const id =
339
- inspection.owner.kind === "phase"
340
- ? `phase:${inspection.owner.taskId}/${inspection.owner.phaseId}`
341
- : `task:${inspection.owner.taskId}`
362
+ "phaseId" in node.data
363
+ ? `phase:${node.data.taskId}/${node.data.phaseId}`
364
+ : `task:${node.data.taskId}`
342
365
  checkoutStates.set(id, {
343
- paths: inspection.checkouts.flatMap((checkout) =>
344
- checkout.exists
345
- ? [checkout.path]
346
- : checkout.registeredPath
347
- ? [checkout.registeredPath]
348
- : [],
349
- ),
350
- conflicts: inspection.conflicts
351
- .filter((conflict) => conflict.kind !== "stale-registration")
352
- .map((conflict) => conflict.message),
353
- dirty: inspection.checkouts.some(
354
- (checkout) => checkout.exists && checkout.dirty !== false,
355
- ),
366
+ paths: [node.workspace.checkoutPath],
367
+ conflicts: [],
368
+ dirty: false,
356
369
  })
357
370
  }
371
+ if (options.json && checkoutStates.size > 0) {
372
+ checkoutStates.clear()
373
+ for (const inspection of yield* worktrees.list(root, {
374
+ materializedOnly: true,
375
+ })) {
376
+ const id =
377
+ inspection.owner.kind === "phase"
378
+ ? `phase:${inspection.owner.taskId}/${inspection.owner.phaseId}`
379
+ : `task:${inspection.owner.taskId}`
380
+ checkoutStates.set(id, checkoutState(inspection))
381
+ }
382
+ }
358
383
  const nodes = graph.nodes.filter(
359
384
  (node): node is ActEntity =>
360
385
  node.kind === "epic" || node.kind === "task" || node.kind === "phase",
@@ -580,7 +605,7 @@ const actStep = (
580
605
  state.item = selected.id
581
606
  session.activateTab("workstream")
582
607
  }
583
- const actions = selected ? catalog.get(selected.id)! : globals
608
+ let actions = selected ? catalog.get(selected.id)! : globals
584
609
  if (!actionId) {
585
610
  state.view = "item-menu"
586
611
  const menuActions = actions.filter(
@@ -595,6 +620,24 @@ const actStep = (
595
620
  )
596
621
  state.view = "flow"
597
622
  }
623
+ if (
624
+ selected &&
625
+ selected.kind !== "epic" &&
626
+ actionId === "worktree-remove" &&
627
+ !options.json
628
+ ) {
629
+ const inspection = yield* worktrees.inspect(
630
+ selected.kind === "phase"
631
+ ? selected.key.slice(0, selected.key.lastIndexOf("/"))
632
+ : selected.key,
633
+ selected.kind === "phase"
634
+ ? selected.key.slice(selected.key.lastIndexOf("/") + 1)
635
+ : undefined,
636
+ root,
637
+ )
638
+ checkoutStates.set(selected.id, checkoutState(inspection))
639
+ actions = actActions(graph.nodes, nativeOptions, runWork, selected)
640
+ }
598
641
  const action = actions.find((action) => action.id === actionId)
599
642
  if (!action || action.blockedReason)
600
643
  return yield* Effect.fail(