@joshuafolkken/kit 1.3041.0 → 1.3044.0

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.
@@ -1054,7 +1054,7 @@ var session_handoff_line = {
1054
1054
 
1055
1055
  // scripts/josh/session-language-cli.ts
1056
1056
  var { DEFAULT_SESSION_LANG, ENV_KEY, resolve_session_lang } = session_language;
1057
- var BOARD_LINE = "A backlogrun is live here: answer a progress question with `pnpm josh run:board --chat`, verbatim in one code block.";
1057
+ var BOARD_LINE = "Live backlogrun: for progress-only questions, run `pnpm josh run:board --chat`; relay output verbatim in one code block. For cause or improvement questions, investigate state, logs and code; cite evidence and uncertainty, even with quoted board lines. For mixed questions, do both.";
1058
1058
  var LIVE_PORTS = {
1059
1059
  repository_directory: run_carry.repository_directory,
1060
1060
  is_running: backlogrun_launch.is_running
package/dist/inputs.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "digest": "60c2b9f0c2baacd3d6c642dfad0127f41a20b289e51feb0de47def5d0dd1fae0",
2
+ "digest": "eda527eb5ac4613c8f26ec5b3ee11d167fbb152a7cc10d250d57365c9ce5e46e",
3
3
  "inputs": [
4
4
  "scripts/build/build-hooks.ts",
5
5
  "scripts/build/build-bin.ts",
@@ -38,20 +38,20 @@
38
38
  "scripts/josh/command-usage.ts",
39
39
  "scripts/josh/josh-gh-usage.ts",
40
40
  "scripts/josh/josh-logic.ts",
41
- "scripts/issue/issue-number-shape.ts",
42
- "scripts/gh/gh-core-rate-limit.ts",
43
- "scripts/gh/gh-request-tally.ts",
44
- "scripts/gh/gh-usage-event.ts",
45
- "scripts/gh/git-gh-exec.ts",
46
41
  "scripts/josh/josh-command-map.ts",
47
42
  "scripts/josh/josh-aliases.ts",
48
43
  "scripts/version/kit-descriptor.ts",
49
- "scripts/josh/run-github-prerequisite.ts",
44
+ "scripts/issue/issue-number-shape.ts",
45
+ "scripts/lib/package-manifest.ts",
50
46
  "scripts/git/git-spawn-sync.ts",
51
47
  "scripts/lib/json-value.ts",
52
- "scripts/lib/package-manifest.ts",
53
48
  "scripts/lib/read-file.ts",
54
49
  "scripts/lib/timeouts.ts",
50
+ "scripts/gh/gh-core-rate-limit.ts",
51
+ "scripts/gh/gh-request-tally.ts",
52
+ "scripts/gh/gh-usage-event.ts",
53
+ "scripts/gh/git-gh-exec.ts",
54
+ "scripts/josh/run-github-prerequisite.ts",
55
55
  "scripts/build/local-bin.ts",
56
56
  "scripts/gate/core-budget.ts",
57
57
  "scripts/hooks/hook-lap.ts",
@@ -63,19 +63,13 @@
63
63
  "scripts/josh/josh-in-process.ts",
64
64
  "scripts/josh/kit-only.ts",
65
65
  "scripts/josh/package-directory.ts",
66
+ "scripts/josh/josh-commands-workflow.ts",
67
+ "scripts/lib/ancestor-directories.ts",
68
+ "scripts/git/git-location-environment.ts",
66
69
  "scripts/gh/gh-usage-log.ts",
67
- "scripts/lib/error-message.ts",
68
- "scripts/run/carry/run-carry.ts",
69
70
  "scripts/gh/git-gh-spawn-width.ts",
70
- "scripts/lib/token-shape.ts",
71
- "scripts/gh/gh-call-kind.ts",
72
- "scripts/lib/bounded-pool.ts",
73
- "scripts/josh/agent-session-environment.ts",
74
- "scripts/gh/git-gh-check.ts",
75
- "scripts/git/git-execa-error.ts",
76
- "scripts/gh/git-gh-retry.ts",
77
- "scripts/gh/git-gh-failure.ts",
78
- "scripts/josh/josh-commands-workflow.ts",
71
+ "scripts/discovery/repo-origin.ts",
72
+ "scripts/lib/pnpm-reach.ts",
79
73
  "scripts/josh/josh-commands-ai.ts",
80
74
  "scripts/josh/josh-commands-clone.ts",
81
75
  "scripts/josh/josh-commands-development.ts",
@@ -84,12 +78,20 @@
84
78
  "scripts/josh/josh-commands-maintenance.ts",
85
79
  "scripts/josh/josh-commands-project.ts",
86
80
  "scripts/josh/josh-commands-versioning.ts",
87
- "scripts/run/ship/run-ship-lap.ts",
88
- "scripts/lib/ancestor-directories.ts",
89
- "scripts/lib/pnpm-reach.ts",
90
- "scripts/git/git-location-environment.ts",
91
81
  "scripts/git/constants.ts",
92
- "scripts/discovery/repo-origin.ts",
82
+ "scripts/lib/error-message.ts",
83
+ "scripts/run/carry/run-carry.ts",
84
+ "scripts/git/git-execa-error.ts",
85
+ "scripts/josh/agent-session-environment.ts",
86
+ "scripts/lib/bounded-pool.ts",
87
+ "scripts/lib/token-shape.ts",
88
+ "scripts/gh/gh-call-kind.ts",
89
+ "scripts/gh/git-gh-check.ts",
90
+ "scripts/gh/git-gh-failure.ts",
91
+ "scripts/gh/git-gh-retry.ts",
92
+ "scripts/run/ship/run-ship-lap.ts",
93
+ "scripts/josh/josh-command-types.ts",
94
+ "ports/index.js",
93
95
  "scripts/gate/machine-capacity.ts",
94
96
  "scripts/josh/platform-temporary.ts",
95
97
  "scripts/josh/process-identity.ts",
@@ -102,66 +104,64 @@
102
104
  "scripts/gate/core-reservation.ts",
103
105
  "scripts/gate/core-wait.ts",
104
106
  "scripts/gate/core-wait-record.ts",
105
- "scripts/josh/josh-command-types.ts",
106
107
  "scripts/gate/core-weights.ts",
107
108
  "scripts/gate/held-mark.ts",
108
- "ports/index.js",
109
- "scripts/josh/durable-state.ts",
109
+ "scripts/lib/atomic-write.ts",
110
+ "scripts/test/unit-run-marker.ts",
111
+ "scripts/gate/core-priority.ts",
112
+ "scripts/lane/lane-paths.ts",
113
+ "scripts/lane/lane-ledger-write.ts",
110
114
  "scripts/run/carry/run-carry-conversation.ts",
111
115
  "scripts/rules/gh-api.ts",
112
116
  "scripts/git/parse-json-array.ts",
113
117
  "scripts/git/repository-lock.ts",
114
118
  "scripts/agent/agent-provider.ts",
115
119
  "scripts/git/git-command.ts",
120
+ "scripts/josh/durable-state.ts",
116
121
  "scripts/run/run-invocation.ts",
117
122
  "scripts/run/carry/run-carry-added.ts",
118
123
  "scripts/run/carry/run-carry-change.ts",
119
124
  "scripts/josh/josh-commands-ship.ts",
120
- "scripts/josh/josh-commands-test-check.ts",
121
- "scripts/lane/lane-ledger-write.ts",
122
- "scripts/lib/atomic-write.ts",
123
- "scripts/test/unit-run-marker.ts",
124
- "scripts/gate/core-priority.ts",
125
- "scripts/lane/lane-paths.ts",
125
+ "scripts/josh/josh-commands-backlog.ts",
126
+ "scripts/josh/josh-commands-document.ts",
127
+ "scripts/josh/josh-commands-epic.ts",
128
+ "scripts/josh/josh-commands-issue.ts",
126
129
  "scripts/josh/josh-commands-review.ts",
130
+ "scripts/josh/josh-commands-run.ts",
131
+ "scripts/josh/josh-commands-test-check.ts",
132
+ "scripts/gate/gate-plan.ts",
133
+ "scripts/josh/josh-commands-agent-hooks.ts",
127
134
  "scripts/init/init-paths.ts",
135
+ "scripts/test/unit-lane-count.ts",
136
+ "scripts/josh/process-owner.ts",
137
+ "scripts/josh/josh-commands-issue-write.ts",
138
+ "scripts/josh/josh-commands-progress.ts",
139
+ "scripts/gate/gate-labels.ts",
140
+ "scripts/lane/lane-state-record.ts",
141
+ "scripts/cost-runtime/own-session.ts",
142
+ "scripts/josh/josh-commands-pause.ts",
143
+ "scripts/josh/josh-commands-prime.ts",
144
+ "scripts/josh/josh-verdict.ts",
145
+ "scripts/gate/gate-checks.ts",
146
+ "scripts/discovery/git-directory.ts",
147
+ "scripts/josh/durable-state-root.ts",
148
+ "scripts/lane/lane-ledger-kind.ts",
128
149
  "scripts/rules/git-argv.ts",
129
150
  "scripts/git/git-common-directory.ts",
130
151
  "scripts/git/git-spawn.ts",
131
- "scripts/lib/cli-flags.ts",
132
152
  "scripts/run/carry/run-carry-streak.ts",
133
- "scripts/lane/lane-ledger-kind.ts",
134
- "scripts/cost-runtime/own-session.ts",
135
153
  "scripts/cost-runtime/cost-transcript.ts",
136
- "scripts/josh/josh-commands-run.ts",
137
- "scripts/josh/josh-commands-document.ts",
138
- "scripts/josh/josh-commands-epic.ts",
139
- "scripts/josh/josh-commands-backlog.ts",
140
- "scripts/test/unit-lane-count.ts",
141
- "scripts/gate/gate-plan.ts",
142
- "scripts/josh/process-owner.ts",
154
+ "scripts/issue/issue-body-keys.ts",
155
+ "scripts/lib/status-icons.ts",
156
+ "scripts/josh/durable-state-migrate.ts",
143
157
  "scripts/git/git-diff-reads.ts",
144
158
  "scripts/git/git-pre-push-hook.ts",
145
159
  "scripts/git/git-push-transport.ts",
146
- "scripts/josh/josh-commands-issue.ts",
147
- "scripts/josh/josh-commands-agent-hooks.ts",
148
- "scripts/josh/durable-state-root.ts",
149
- "scripts/josh/durable-state-migrate.ts",
160
+ "scripts/lib/cli-flags.ts",
161
+ "scripts/josh/session-language.ts",
150
162
  "scripts/git/git-ssh-keepalive.ts",
151
- "scripts/josh/josh-commands-progress.ts",
152
- "scripts/lane/lane-state-record.ts",
153
- "scripts/gate/gate-labels.ts",
154
- "scripts/josh/josh-commands-pause.ts",
155
- "scripts/josh/josh-commands-prime.ts",
156
- "scripts/discovery/git-directory.ts",
157
- "scripts/josh/josh-verdict.ts",
158
- "scripts/gate/gate-checks.ts",
159
- "scripts/josh/josh-commands-issue-write.ts",
160
163
  "scripts/cost-runtime/cost-usage.ts",
161
- "scripts/time-runtime/time-instant.ts",
162
- "scripts/lib/status-icons.ts",
163
- "scripts/issue/issue-body-keys.ts",
164
- "scripts/josh/session-language.ts"
164
+ "scripts/time-runtime/time-instant.ts"
165
165
  ],
166
166
  "outputs": [
167
167
  "josh.js"
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.3041.0",
2
+ "version": "1.3044.0",
3
3
  "name": "@joshuafolkken/kit",
4
4
  "description": "Hand-off kit for Claude Code and Codex: backlogrun takes your GitHub Issues to tested, reviewed, merged PRs — in parallel and unattended — with the rules, hooks and checks that keep the agent on track",
5
5
  "keywords": [
@@ -32,7 +32,7 @@ import { session_language, type Resolution } from './session-language'
32
32
  const { DEFAULT_SESSION_LANG, ENV_KEY, resolve_session_lang } = session_language
33
33
 
34
34
  const BOARD_LINE =
35
- 'A backlogrun is live here: answer a progress question with `pnpm josh run:board --chat`, verbatim in one code block.'
35
+ 'Live backlogrun: for progress-only questions, run `pnpm josh run:board --chat`; relay output verbatim in one code block. For cause or improvement questions, investigate state, logs and code; cite evidence and uncertainty, even with quoted board lines. For mixed questions, do both.'
36
36
 
37
37
  interface LivePorts {
38
38
  // The common git directory the run's records are keyed on; `undefined` outside a repository.
@@ -19,6 +19,7 @@ import type { QuotaHold, QuotaView } from './run-board-render-quota'
19
19
  import { run_board_render_slot } from './run-board-render-slot'
20
20
  import { run_board_render_title } from './run-board-render-title'
21
21
  import type { SeatRead } from './run-board-seat'
22
+ import { run_board_setup } from './run-board-setup'
22
23
  import type { RunActivity } from './run-board-status'
23
24
  import type { LaneUsages, UsageScale } from './run-board-usage'
24
25
  import type { UsualTimes } from './run-board-usual'
@@ -46,7 +47,6 @@ const { padded } = run_board_fresh
46
47
  const aged_fresh = run_board_fresh.aged
47
48
  const UNKNOWN = '-'
48
49
  const BLANK = ' '
49
- const REPO_SEPARATOR = '/'
50
50
  const { GAP, PERCENT_WIDTH } = run_board_machine
51
51
  // A running run whose newest event is older than this is drawn as stale, so a hang stands out; past
52
52
  // twice that it is drawn as alarming.
@@ -165,9 +165,8 @@ const WORKING_MARKS: ReadonlySet<RunMark> = new Set<RunMark>(['running', 'setup'
165
165
  // Nothing running: the run is at work on a stage of its own; else it is waiting on a person when all
166
166
  // the plan has left is what `needs-decision` holds, or idle.
167
167
  function quiet_mark(header: BoardHeader): RunMark {
168
- const { layout } = header
169
-
170
- if (header.activity.setup !== undefined) return 'setup'
168
+ const { activity, layout } = header
169
+ if (run_board_setup.is_working(activity.setup, activity.is_setup_working)) return 'setup'
171
170
 
172
171
  return layout?.queued.length === 0 && run_board_layout.people_of(layout).length > 0
173
172
  ? 'human'
@@ -191,7 +190,7 @@ function run_part(mark: RunMark, name = RUN_NAME): string {
191
190
  // The repository's own name — `kit` of `owner/kit` — under the run's, past the mark's columns, so a
192
191
  // board open beside another repository's is told apart. Blank before a plan names one.
193
192
  function repo_part(header: BoardHeader, mark: RunMark): string {
194
- const name = header.repo?.split(REPO_SEPARATOR).at(-1) ?? ''
193
+ const name = header.repo?.split('/').at(-1) ?? ''
195
194
  const indent = run_board_fit.width_of(RUN_MARKS[mark].glyph) + BLANK.length
196
195
 
197
196
  return `${BLANK.repeat(indent)}${header.repo_link(name, 'home')}`
@@ -59,6 +59,8 @@ interface LocalRead {
59
59
  is_stranded: boolean
60
60
  // The newest operation of each session of the run, read off the end of its log.
61
61
  operations?: SessionOperations | undefined
62
+ // The carry's session owner is still running, apart from the supervisor's own driver.
63
+ is_session_active?: boolean | undefined
62
64
  // The open lanes no child is working in at this read (`lane-spent.ts`); one is drawn stopped once it
63
65
  // has stayed so (`run-board-idle.ts`).
64
66
  idle_lanes?: ReadonlyArray<string> | undefined
@@ -108,6 +110,7 @@ const NO_SPAN: SpanHere = {
108
110
  roots: {},
109
111
  carry: undefined,
110
112
  is_stranded: false,
113
+ is_session_active: false,
111
114
  }
112
115
 
113
116
  interface SpanHere {
@@ -118,6 +121,7 @@ interface SpanHere {
118
121
  roots: ProcessRoots
119
122
  carry: RunCarry | undefined
120
123
  is_stranded: boolean
124
+ is_session_active: boolean
121
125
  }
122
126
 
123
127
  // The main work tree, resolved once: it does not move while the board is open, and resolving it runs a
@@ -159,6 +163,7 @@ async function recorded_span_here(
159
163
  resume: run_board_span.resume_of(read, ended, launch),
160
164
  transcript: read.kind === 'carried' ? read.carry.owner_transcript : undefined,
161
165
  roots: run_board_roots.roots_of(repository, read, same_process),
166
+ is_session_active: run_board_roots.session_is_active(repository, read, same_process),
162
167
  carry: read.kind === 'carried' ? read.carry : undefined,
163
168
  is_stranded: run_stranded_detect.is_stranded_at(repository, stranded_ports),
164
169
  }
@@ -341,7 +346,7 @@ function span_fields(
341
346
  // snapshot, so it agrees with the usage columns.
342
347
  async function read_local(table?: TableRead): Promise<LocalRead | undefined> {
343
348
  const repository = await run_carry.repository_directory()
344
- const { span, resume, transcript, roots, carry, is_stranded } =
349
+ const { span, resume, transcript, roots, carry, is_stranded, is_session_active } =
345
350
  repository === undefined ? NO_SPAN : await span_here(repository, table)
346
351
 
347
352
  if (repository === undefined || span === undefined) return undefined
@@ -361,6 +366,7 @@ async function read_local(table?: TableRead): Promise<LocalRead | undefined> {
361
366
  roots,
362
367
  carry,
363
368
  is_stranded,
369
+ is_session_active,
364
370
  operations: run_board_operation_read.read(sources_of(repository, lanes, transcript)),
365
371
  ...(await lane_room_of(lanes, lane_read.lane_states, table)),
366
372
  ...ledger_here(repository),
@@ -1,7 +1,7 @@
1
1
  import { process_identity } from '#scripts/josh/process-identity'
2
2
  import { lane_process_table, type TableRead } from '#scripts/lane/lane-process-table'
3
3
  import type { CarryRead } from '#scripts/run/carry/run-carry'
4
- import { run_wake } from '#scripts/run/wake/run-wake'
4
+ import { run_wake, type RunWake } from '#scripts/run/wake/run-wake'
5
5
  import type { ProcessRoots } from './run-board-process-groups'
6
6
 
7
7
  // The run's own processes the 💻 section names: the supervisor from its wake stamp and the parent
@@ -38,6 +38,29 @@ function roots_of(
38
38
  return { supervisor: supervisor_of(repository, is_same), parent: parent_of(read, is_same) }
39
39
  }
40
40
 
41
+ // A handed-back budget or the supervisor's own driver is no judgment session. Codex's pid-less
42
+ // carry uses the launch pid already recorded by the wake supervisor instead.
43
+ function is_session_owner(read: CarryRead): boolean {
44
+ return read.kind === 'carried' && read.carry.is_handed_off !== true
45
+ }
46
+
47
+ function live_session_pid(
48
+ pid: number | undefined,
49
+ start: string | undefined,
50
+ wake: RunWake | undefined,
51
+ is_same: SameProcess,
52
+ ): boolean {
53
+ return pid !== undefined && pid !== wake?.pid && is_same(pid, start) !== false
54
+ }
55
+
56
+ function session_is_active(repository: string, read: CarryRead, is_same: SameProcess): boolean {
57
+ if (read.kind !== 'carried' || !is_session_owner(read)) return false
58
+ const wake = run_wake.read_wake(run_wake.wake_path(repository))
59
+ const pid = read.carry.owner_pid ?? wake?.woke_pid
60
+
61
+ return live_session_pid(pid, read.carry.owner_start, wake, is_same)
62
+ }
63
+
41
64
  // `is_same_process` with each start time answered from the redraw's own `ps` snapshot, so the board's
42
65
  // read runs no `ps` of its own per pid (joshuafolkken/kit#4263). Without a snapshot no start is known,
43
66
  // and a recorded start reads as "cannot tell".
@@ -48,7 +71,7 @@ async function same_in(table: TableRead | undefined): Promise<SameProcess> {
48
71
  return (pid, start) => process_identity.is_same_process(pid, start, read)
49
72
  }
50
73
 
51
- const run_board_roots = { roots_of, same_in }
74
+ const run_board_roots = { roots_of, same_in, session_is_active }
52
75
 
53
76
  export { run_board_roots }
54
77
  export type { SameProcess }
@@ -21,19 +21,25 @@ interface SetupRead {
21
21
 
22
22
  const NO_SETUP: SetupRead = { setup: undefined, setup_ms: undefined }
23
23
 
24
+ // Only these stages depend on the judgment session owning the carry.
25
+ const SESSION_STAGES: ReadonlySet<string> = new Set([STAGE.JUDGING, STAGE.SESSION])
26
+
24
27
  // The stages of a hand-back to a session, and of the retrospective unit the driver waits on at a drain
25
28
  // (joshuafolkken/kit#6745). Only the run's next stage ends one, whatever the session or the unit writes
26
29
  // to the stream meanwhile.
27
- const SESSION_STAGES: ReadonlySet<string> = new Set([
28
- STAGE.JUDGING,
29
- STAGE.SESSION,
30
- STAGE.RETROSPECTIVE,
31
- ])
30
+ const RETAINED_STAGES: ReadonlySet<string> = new Set([...SESSION_STAGES, STAGE.RETROSPECTIVE])
32
31
 
33
32
  function is_setup(event: RunEvent): boolean {
34
33
  return event.kind === KIND.SETUP
35
34
  }
36
35
 
36
+ // Session stages describe the last hand-off even after its owner has returned the budget.
37
+ function is_working(setup: string | undefined, is_session_active: boolean | undefined): boolean {
38
+ if (setup === undefined) return false
39
+
40
+ return !SESSION_STAGES.has(setup) || is_session_active !== false
41
+ }
42
+
37
43
  // A launch that returned without a child (`run_event_setup.no_child`): it ends its own lane's stage,
38
44
  // and prepares nothing a person waits on.
39
45
  function is_refusal(event: RunEvent): boolean {
@@ -65,7 +71,7 @@ function is_opening(events: ReadonlyArray<RunEvent>, stage: RunEvent): boolean {
65
71
  // Whether the run is at `stage` now: at any stage while it is starting; after that only at one it is
66
72
  // itself working through.
67
73
  function is_standing(events: ReadonlyArray<RunEvent>, stage: RunEvent): boolean {
68
- if (!has_started(events) || SESSION_STAGES.has(stage.text)) return true
74
+ if (!has_started(events) || RETAINED_STAGES.has(stage.text)) return true
69
75
 
70
76
  return is_opening(events, stage)
71
77
  }
@@ -119,7 +125,7 @@ function lane_stage(events: ReadonlyArray<RunEvent>, issue: number): LaneStage |
119
125
  return { text: step.text, at_ms: Date.parse(step.at) }
120
126
  }
121
127
 
122
- const run_board_setup = { is_refusal, lane_stage, read }
128
+ const run_board_setup = { is_refusal, is_working, lane_stage, read }
123
129
 
124
130
  export { run_board_setup }
125
131
  export type { LaneStage, SetupRead }
@@ -82,6 +82,8 @@ interface LatestEvent {
82
82
  // The run as a whole, read off the same stream. The setup half is `run-board-setup.ts`'s, absent
83
83
  // where a stream carries no stage.
84
84
  interface RunActivity extends Partial<SetupRead> {
85
+ // Runtime evidence for the stage, independent of its retained description.
86
+ is_setup_working?: boolean | undefined
85
87
  last_event_ms: number | undefined
86
88
  // The newest thing the run did — its newest position, or its newest event where it has none yet —
87
89
  // in the event's own words, and when.
@@ -14,6 +14,7 @@ import { run_board_reason, type ReasonRead } from './run-board-reason'
14
14
  import { run_board_released } from './run-board-released'
15
15
  import { run_board_render } from './run-board-render'
16
16
  import { run_board_seat, type SeatRead } from './run-board-seat'
17
+ import { run_board_setup } from './run-board-setup'
17
18
  import type { Known } from './run-board-snapshot'
18
19
  import { run_board_spin, type Spun } from './run-board-spin'
19
20
  import { run_board_state, type BoardPorts, type BoardState, type Pace } from './run-board-state'
@@ -82,10 +83,15 @@ function titles_of(state: BoardState): Titles {
82
83
 
83
84
  // A run `run:carry --end` closed and one nobody drives any more are both drawn as stopped.
84
85
  function activity_here(local: LocalRead): RunActivity {
85
- return run_board_status.activity_of(
86
+ const activity = run_board_status.activity_of(
86
87
  local.events,
87
88
  local.ended_ms !== undefined || local.is_stranded,
88
89
  )
90
+
91
+ return {
92
+ ...activity,
93
+ is_setup_working: run_board_setup.is_working(activity.setup, local.is_session_active),
94
+ }
89
95
  }
90
96
 
91
97
  // The already-read supervisor or parent drives retries until the run stops or becomes stranded.