jackherd 1.26.1 → 1.26.3

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 (51) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +18 -18
  3. package/dist/config.d.ts +1 -0
  4. package/dist/config.js +2 -0
  5. package/herdr-plugin/herdr-plugin.toml +1 -1
  6. package/install.sh +1 -1
  7. package/kit/workflow/skills/orchestrate/references/close-lane.md +8 -8
  8. package/kit/workflow/skills/orchestrate/references/lane-session.md +1 -1
  9. package/package.json +1 -1
  10. package/schemas/jackherd.schema.json +8 -0
  11. package/src/brief/lane-facts.ts +30 -18
  12. package/src/config/schema.ts +2 -0
  13. package/src/context/command.ts +3 -1
  14. package/src/lane/close-check.ts +51 -15
  15. package/src/lane/close-command.ts +41 -8
  16. package/src/lane/close-survey.ts +9 -0
  17. package/src/lane/close.ts +54 -6
  18. package/src/lane/send-options.ts +3 -2
  19. package/src/lane/send.ts +8 -1
  20. package/src/lane/subagent-view.ts +21 -0
  21. package/src/lane-prompt/command.ts +4 -1
  22. package/src/plans/active-tasks.ts +4 -2
  23. package/src/plans/activity-read.ts +3 -2
  24. package/src/plans/command.ts +3 -1
  25. package/src/plans/coordinator-row.ts +7 -2
  26. package/src/plans/ensure-panes.ts +2 -2
  27. package/src/plans/lane-discovery.ts +42 -3
  28. package/src/plans/lane-worktrees.ts +56 -0
  29. package/src/plans/sent-files.ts +10 -5
  30. package/src/plans/settings.ts +12 -1
  31. package/src/plans/snapshot.ts +23 -8
  32. package/src/plans/subagents-read.ts +17 -2
  33. package/src/plans/subagents.ts +3 -2
  34. package/src/plans/unlisted-lanes.ts +13 -0
  35. package/src/resume/command.ts +1 -1
  36. package/src/resume/coordinator-read.ts +12 -12
  37. package/src/resume/decision.ts +3 -0
  38. package/src/resume/record.ts +24 -5
  39. package/src/sync/command.ts +16 -2
  40. package/src/sync/downgrade.ts +9 -0
  41. package/src/sync/if-changed.ts +6 -7
  42. package/src/update/command.ts +17 -0
  43. package/src/update/registry-wait.ts +44 -0
  44. package/src/update/update.ts +23 -0
  45. package/src/version/registry.ts +8 -0
  46. package/src/watch/command.ts +28 -14
  47. package/src/watch/obsolete-proposals.ts +8 -6
  48. package/src/watch/obsolete-records.ts +3 -1
  49. package/src/watch/running-subagents.ts +3 -2
  50. package/src/watch/task-signal-read.ts +4 -1
  51. package/src/watch/unlinked-artifacts-read.ts +3 -1
@@ -1,6 +1,7 @@
1
1
  import { terminalSafe } from '../plan-format/terminal-text'
2
2
  import { CLOSE_REASON, closeReasonOf } from '../plans/close-reason'
3
3
  import { latestPerFile, type SentFileRecord, sentLaneOf } from '../plans/sent-files'
4
+ import type { LaneWorktrees } from '../plans/unlisted-lanes'
4
5
 
5
6
  export const WAITING_CLOSED_EVENT = 'waiting closed'
6
7
 
@@ -49,9 +50,10 @@ export const obsoleteSendsOf = (
49
50
  records: readonly SentFileRecord[],
50
51
  worktreeDirectory: string,
51
52
  gone: ReadonlySet<string>,
53
+ placed: LaneWorktrees = {},
52
54
  ): Closing[] => {
53
55
  const open = records.flatMap((record) => {
54
- const lane = sentLaneOf(record, worktreeDirectory)
56
+ const lane = sentLaneOf(record, worktreeDirectory, placed)
55
57
  return record.closedAt === null ? [{ id: record.id, lane }] : []
56
58
  })
57
59
  const openIds = new Set(open.map(({ id }) => id))
@@ -1,15 +1,16 @@
1
1
  import type { RunningSubagent } from '../plans/subagents'
2
- import { laneDirectoryOf } from '../plans/unlisted-lanes'
2
+ import { type LaneWorktrees, laneOfCwd } from '../plans/unlisted-lanes'
3
3
  import { type LaneNotes, type PhaseCount, progressNotes } from './heartbeat-progress'
4
4
 
5
5
  /** The running subagents of each worktree below `worktreeDirectory`, by lane name; one that works elsewhere is left out. */
6
6
  export const runningSubagentCountsOf = (
7
7
  running: readonly Pick<RunningSubagent, 'cwd'>[],
8
8
  worktreeDirectory: string,
9
+ placed: LaneWorktrees = {},
9
10
  ): Record<string, number> => {
10
11
  const counts: Record<string, number> = {}
11
12
  for (const { cwd } of running) {
12
- const lane = cwd === null ? null : laneDirectoryOf(cwd, worktreeDirectory)
13
+ const lane = cwd === null ? null : laneOfCwd(cwd, worktreeDirectory, placed)
13
14
  if (lane !== null) counts[lane] = (counts[lane] ?? 0) + 1
14
15
  }
15
16
  return counts
@@ -2,12 +2,15 @@ import { join } from 'node:path'
2
2
  import { defaultProjectsDirectory } from '../context/session-log'
3
3
  import { laneOfDirectory } from '../plans/active-tasks'
4
4
  import { readAllSignals } from '../plans/signals-read'
5
+ import type { LaneWorktrees } from '../plans/unlisted-lanes'
5
6
 
6
7
  export type SignalSources = {
7
8
  /** The main checkout, which holds `.jackherd/tasks/`. */
8
9
  root: string
9
10
  /** The lanes' worktree directory, relative to `root`. */
10
11
  worktreeDirectory: string
12
+ /** The lanes placed in worktrees of another name (`PlansSettings.laneWorktrees`). */
13
+ laneWorktrees?: LaneWorktrees
11
14
  now: number
12
15
  /** Where Claude Code keeps its session logs; the user's by default. */
13
16
  projectsDirectory?: string
@@ -24,6 +27,6 @@ export const signalledLanes = (lanes: readonly string[], sources: SignalSources)
24
27
  { projects: sources.projectsDirectory ?? defaultProjectsDirectory(), root: sources.root, worktrees },
25
28
  sources.now,
26
29
  )
27
- const signalled = new Set(signals.flatMap(({ cwd }) => laneOfDirectory(cwd, worktrees) ?? []))
30
+ const signalled = new Set(signals.flatMap(({ cwd }) => laneOfDirectory(cwd, worktrees, sources.laneWorktrees) ?? []))
28
31
  return new Set(lanes.filter((lane) => signalled.has(lane)))
29
32
  }
@@ -35,7 +35,9 @@ export const readUnlinkedArtifactEvents = (
35
35
  const ids = new Set(artifacts.map(({ id }) => id))
36
36
  const worktrees = join(root, settings.worktreeDirectory)
37
37
  const lanes = new Set(
38
- records.filter(({ id }) => ids.has(id)).flatMap((record) => sentLaneOf(record, worktrees) ?? []),
38
+ records
39
+ .filter(({ id }) => ids.has(id))
40
+ .flatMap((record) => sentLaneOf(record, worktrees, settings.laneWorktrees) ?? []),
39
41
  )
40
42
  const checkouts = [root, ...[...lanes].map((lane) => worktreeOf(root, settings, lane))]
41
43
  const texts = checkouts.flatMap((checkout) => markdownTextsUnder(join(checkout, settings.planDirectory)))