@clipboard-health/groundcrew 4.50.3 → 4.50.5
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/README.md +46 -2
- package/dist/cli.js +1 -1
- package/dist/commands/agentLaunchCleanup.d.ts +5 -0
- package/dist/commands/agentLaunchCleanup.d.ts.map +1 -0
- package/dist/commands/agentLaunchCleanup.js +9 -0
- package/dist/commands/openWorkspace.d.ts.map +1 -1
- package/dist/commands/openWorkspace.js +36 -18
- package/dist/commands/resumeWorkspace.d.ts.map +1 -1
- package/dist/commands/resumeWorkspace.js +44 -18
- package/dist/commands/setupWorkspace.d.ts.map +1 -1
- package/dist/commands/setupWorkspace.js +2 -1
- package/dist/commands/status.d.ts +16 -0
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +205 -320
- package/dist/commands/statusCollect.d.ts +96 -0
- package/dist/commands/statusCollect.d.ts.map +1 -0
- package/dist/commands/statusCollect.js +463 -0
- package/dist/lib/atomicJson.d.ts +15 -0
- package/dist/lib/atomicJson.d.ts.map +1 -0
- package/dist/lib/atomicJson.js +32 -0
- package/dist/lib/pullRequests.d.ts.map +1 -1
- package/dist/lib/pullRequests.js +7 -1
- package/dist/lib/runState.d.ts.map +1 -1
- package/dist/lib/runState.js +3 -6
- package/dist/lib/statusJoin.d.ts +41 -0
- package/dist/lib/statusJoin.d.ts.map +1 -0
- package/dist/lib/statusJoin.js +59 -0
- package/dist/lib/statusSnapshot.d.ts +220 -0
- package/dist/lib/statusSnapshot.d.ts.map +1 -0
- package/dist/lib/statusSnapshot.js +178 -0
- package/dist/lib/worktrees.d.ts.map +1 -1
- package/dist/lib/worktrees.js +5 -1
- package/docs/commands.md +10 -1
- package/docs/development.md +1 -1
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -32,7 +32,7 @@ Groundcrew watches assigned tasks, creates isolated worktrees, launches agent CL
|
|
|
32
32
|
|
|
33
33
|
`crew doctor` checks all of these, so you can install as you go.
|
|
34
34
|
|
|
35
|
-
- **Node
|
|
35
|
+
- **Node 24.14.1:** [nvm](https://github.com/nvm-sh/nvm): `nvm install 24.14.1`.
|
|
36
36
|
- **git:** e.g., `brew install git`, `apt install git`.
|
|
37
37
|
- **A terminal multiplexer:** [tmux](https://github.com/tmux/tmux/wiki/Installing) (cross-platform), [cmux](https://cmux.com/) (macOS), or [zellij](https://zellij.dev/).
|
|
38
38
|
- **An agent CLI:** [Claude Code](https://code.claude.com/docs/en/quickstart), [Codex](https://developers.openai.com/codex/quickstart?setup=cli), the [Cursor CLI](https://docs.cursor.com/en/cli/overview) (`cursor-agent`, for the `cursor` and `cursor-grok` presets), and/or [Pi](https://pi.dev/).
|
|
@@ -112,7 +112,7 @@ crew task get <TASK> [--source <name>] [--prompt] # inspect one task or i
|
|
|
112
112
|
crew task create "Title" --source <name> [--agent <name>] # create a source task
|
|
113
113
|
crew task done <TASK> [--allow-dirty] # mark a no-PR task done
|
|
114
114
|
crew task validate [<source>] # validate task content
|
|
115
|
-
crew status [<TASK>]
|
|
115
|
+
crew status [<TASK>] [--json [--local-only]] # inspect current state, or emit it as JSON
|
|
116
116
|
crew run [--watch] # one-shot or --watch forever
|
|
117
117
|
crew start <TASK> # provision + launch one task now
|
|
118
118
|
crew stop <TASK> [--reason <text>] # stop workspace, keep worktree
|
|
@@ -127,6 +127,50 @@ crew completions <bash|zsh|fish> # print a shell completi
|
|
|
127
127
|
|
|
128
128
|
See [command details](./docs/commands.md) for status output, doctor behavior, and the stop/resume workflow.
|
|
129
129
|
|
|
130
|
+
### Status snapshots for external monitors
|
|
131
|
+
|
|
132
|
+
`crew status --json` prints two documents and writes them beside the log file:
|
|
133
|
+
|
|
134
|
+
```text
|
|
135
|
+
<state-dir>/status-local.json # worktrees, run states, sessions, git status
|
|
136
|
+
<state-dir>/status-remote.json # board, pull requests
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
The two are split by cost. The local tier is local subprocess work, so it is
|
|
140
|
+
safe to poll every few seconds. The remote tier is network-bound and
|
|
141
|
+
rate-limited, so poll it near your `pollIntervalMilliseconds`.
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
crew status --json # both tiers
|
|
145
|
+
crew status --json --local-only # local tier only; never touches the network
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
`--local-only` is a guarantee about that invocation, not a computed outcome, so
|
|
149
|
+
a monitor's fast loop cannot stall on a slow board or a `gh` timeout.
|
|
150
|
+
|
|
151
|
+
Three rules a reader must honor:
|
|
152
|
+
|
|
153
|
+
- **Subtract locally.** `status-remote.json` ships board classification without
|
|
154
|
+
the local worktree subtraction. Remove tasks present in the local document
|
|
155
|
+
from `inProgress`, `queueReady`, and `queueBlocked` yourself. Precomputing
|
|
156
|
+
that join would report a just-dispatched task as still queued until the next
|
|
157
|
+
slow poll, which is a false statement rather than stale data.
|
|
158
|
+
- **Join pull requests on the worktree directory.** `pullRequestsByWorktree` is
|
|
159
|
+
keyed by absolute worktree path, not by task, because a task with two
|
|
160
|
+
worktrees has two branches. An empty or missing entry means no pull requests
|
|
161
|
+
were found, or the `gh` lookup for that worktree failed; the two are not
|
|
162
|
+
distinguishable.
|
|
163
|
+
- **Read the right timestamp.** `payload.capturedAt` describes the last
|
|
164
|
+
successful fetch; `lastAttemptAt` describes the most recent try. Read
|
|
165
|
+
`lastAttemptStatus` to answer "is the board healthy", and `capturedAt` to
|
|
166
|
+
answer "how old is this queue". A failed fetch keeps the previous payload, so
|
|
167
|
+
last-known-good data survives an outage while the document still says the
|
|
168
|
+
board is unreachable.
|
|
169
|
+
|
|
170
|
+
Durations are never stored, only start instants, so a reader must derive
|
|
171
|
+
elapsed time itself. A cached duration would show a frozen clock, which reads
|
|
172
|
+
as "the agent stopped working" when it did not.
|
|
173
|
+
|
|
130
174
|
## Configuration
|
|
131
175
|
|
|
132
176
|
Workspace settings and at least one enabled agent are required; everything else has a default.
|
package/dist/cli.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agentLaunchCleanup.d.ts","sourceRoot":"","sources":["../../src/commands/agentLaunchCleanup.ts"],"names":[],"mappings":"AAEA,wBAAgB,4BAA4B,CAAC,UAAU,EAAE;IACvD,OAAO,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IAClC,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,IAAI,CAMP"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { errorMessage, log } from "../lib/util.js";
|
|
2
|
+
export function cleanupAgentLaunchBestEffort(arguments_) {
|
|
3
|
+
try {
|
|
4
|
+
arguments_.cleanup?.();
|
|
5
|
+
}
|
|
6
|
+
catch (error) {
|
|
7
|
+
log(`Agent launch cleanup failed during ${arguments_.context}: ${errorMessage(error)}`);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/openWorkspace.ts"],"names":[],"mappings":"AAKA,OAAO,EAAiC,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"openWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/openWorkspace.ts"],"names":[],"mappings":"AAKA,OAAO,EAAiC,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAiBtF,UAAU,gBAAgB;IACxB,IAAI,EAAE,IAAI,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,WAAW;IACnB,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,gBAAgB,GAAG,WAAW,CAAC;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AA0KD,wBAAsB,aAAa,CACjC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,IAAI,CAAC,CA0Hf;AA4ID,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,oBAAoB,CAE3E;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAIpE"}
|
|
@@ -12,6 +12,7 @@ import { normalizePlainTaskId } from "../lib/taskId.js";
|
|
|
12
12
|
import { debug, errorMessage, log, okMark } from "../lib/util.js";
|
|
13
13
|
import { failIfWorkspaceAlreadyLive } from "../lib/workspaceLiveness.js";
|
|
14
14
|
import { resolveLaunchDir, worktrees } from "../lib/worktrees.js";
|
|
15
|
+
import { cleanupAgentLaunchBestEffort } from "./agentLaunchCleanup.js";
|
|
15
16
|
const OPEN_USAGE = "Usage: crew open <pr> | --branch <name> [--repo <owner/repo>] [--agent <agent>] [--prompt <text> | --prompt-file <path>] [--task <id>] [--dry-run]";
|
|
16
17
|
const PULL_REQUEST_URL_PATTERN = /^https?:\/\/github\.com\/(?<repository>[^/]+\/[^/]+)\/pull\/(?<pr>\d+)/;
|
|
17
18
|
function parsePullRequestReference(reference) {
|
|
@@ -101,7 +102,17 @@ async function resolveTarget(config, options, repository) {
|
|
|
101
102
|
async function rollback(arguments_) {
|
|
102
103
|
log(`Open failed; rolling back worktree ${arguments_.entry.repository}-${arguments_.entry.task}...`);
|
|
103
104
|
try {
|
|
104
|
-
await worktrees.teardown(arguments_.config, [arguments_.entry], { force: true });
|
|
105
|
+
const result = await worktrees.teardown(arguments_.config, [arguments_.entry], { force: true });
|
|
106
|
+
for (const failure of result.failures) {
|
|
107
|
+
log(`Worktree teardown ${failure.step} failed during rollback: ${errorMessage(failure.error)}`);
|
|
108
|
+
}
|
|
109
|
+
const workspaceAbsent = result.workspaceProbe.kind === "ok" &&
|
|
110
|
+
!result.workspaceProbe.names.has(arguments_.entry.task);
|
|
111
|
+
if (arguments_.workspaceOpened &&
|
|
112
|
+
!workspaceAbsent &&
|
|
113
|
+
!result.closed.includes(arguments_.entry.task)) {
|
|
114
|
+
log(`Workspace close was not confirmed during open rollback for ${arguments_.entry.task}. Close it manually in the configured workspace backend.`);
|
|
115
|
+
}
|
|
105
116
|
}
|
|
106
117
|
catch (error) {
|
|
107
118
|
log(`Worktree teardown failed during rollback: ${errorMessage(error)}`);
|
|
@@ -151,6 +162,7 @@ export async function openWorkspace(config, options) {
|
|
|
151
162
|
text: options.promptText ?? "",
|
|
152
163
|
});
|
|
153
164
|
let cleanupAgentLaunch;
|
|
165
|
+
let workspaceOpened = false;
|
|
154
166
|
try {
|
|
155
167
|
const { prepareWorktreeCommand, prepareWorktreeUnsandboxedCommand } = resolveRepositoryPreparationCommands({
|
|
156
168
|
config,
|
|
@@ -191,27 +203,33 @@ export async function openWorkspace(config, options) {
|
|
|
191
203
|
agent,
|
|
192
204
|
color: definition.color,
|
|
193
205
|
});
|
|
206
|
+
workspaceOpened = true;
|
|
207
|
+
recordRunState({
|
|
208
|
+
config,
|
|
209
|
+
state: {
|
|
210
|
+
task: target.task,
|
|
211
|
+
repository,
|
|
212
|
+
agent,
|
|
213
|
+
worktreeDir: created.dir,
|
|
214
|
+
branchName: target.branch,
|
|
215
|
+
workspaceName: target.task,
|
|
216
|
+
state: "running",
|
|
217
|
+
title: target.title,
|
|
218
|
+
adoptedBranch: true,
|
|
219
|
+
...(target.url === undefined ? {} : { url: target.url }),
|
|
220
|
+
},
|
|
221
|
+
});
|
|
194
222
|
}
|
|
195
223
|
catch (error) {
|
|
196
|
-
cleanupAgentLaunch
|
|
197
|
-
await rollback({
|
|
224
|
+
cleanupAgentLaunchBestEffort({ cleanup: cleanupAgentLaunch, context: "open rollback" });
|
|
225
|
+
await rollback({
|
|
226
|
+
config,
|
|
227
|
+
entry: created,
|
|
228
|
+
promptDir: stagedPrompt.directory,
|
|
229
|
+
workspaceOpened,
|
|
230
|
+
});
|
|
198
231
|
throw error;
|
|
199
232
|
}
|
|
200
|
-
recordRunState({
|
|
201
|
-
config,
|
|
202
|
-
state: {
|
|
203
|
-
task: target.task,
|
|
204
|
-
repository,
|
|
205
|
-
agent,
|
|
206
|
-
worktreeDir: created.dir,
|
|
207
|
-
branchName: target.branch,
|
|
208
|
-
workspaceName: target.task,
|
|
209
|
-
state: "running",
|
|
210
|
-
title: target.title,
|
|
211
|
-
adoptedBranch: true,
|
|
212
|
-
...(target.url === undefined ? {} : { url: target.url }),
|
|
213
|
-
},
|
|
214
|
-
});
|
|
215
233
|
log(`${okMark()} "${target.task}" opened on branch ${target.branch} (${agent})`);
|
|
216
234
|
debug(` Worktree: ${launchDir}`);
|
|
217
235
|
if (omitPromptArgument) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resumeWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/resumeWorkspace.ts"],"names":[],"mappings":"AAGA,OAAO,EAAoC,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"resumeWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/resumeWorkspace.ts"],"names":[],"mappings":"AAGA,OAAO,EAAoC,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAwBzF,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAoMD,wBAAsB,eAAe,CACnC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAgIf;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAGtE"}
|
|
@@ -12,7 +12,9 @@ import { taskSourceWritePathsForCompletion } from "../lib/taskSourceFilesystem.j
|
|
|
12
12
|
import { naturalIdFromCanonical, toCanonicalId } from "../lib/taskSource.js";
|
|
13
13
|
import { errorMessage, log } from "../lib/util.js";
|
|
14
14
|
import { failIfWorkspaceAlreadyLive } from "../lib/workspaceLiveness.js";
|
|
15
|
+
import { workspaces } from "../lib/workspaces.js";
|
|
15
16
|
import { resolveLaunchDir, worktrees } from "../lib/worktrees.js";
|
|
17
|
+
import { cleanupAgentLaunchBestEffort } from "./agentLaunchCleanup.js";
|
|
16
18
|
function parseArguments(argv) {
|
|
17
19
|
let fresh = false;
|
|
18
20
|
const positionals = [];
|
|
@@ -192,6 +194,7 @@ export async function resumeWorkspace(config, options) {
|
|
|
192
194
|
});
|
|
193
195
|
const secretsFile = stageBuildSecrets(stagedPrompt.directory);
|
|
194
196
|
let cleanupAgentLaunch;
|
|
197
|
+
let workspaceOpened = false;
|
|
195
198
|
try {
|
|
196
199
|
const taskSourceWritePaths = runner === "safehouse"
|
|
197
200
|
? taskSourceWritePathsForCompletion({
|
|
@@ -235,28 +238,51 @@ export async function resumeWorkspace(config, options) {
|
|
|
235
238
|
agent: context.agent,
|
|
236
239
|
color: definition.color,
|
|
237
240
|
});
|
|
241
|
+
workspaceOpened = true;
|
|
242
|
+
recordRunState({
|
|
243
|
+
config,
|
|
244
|
+
state: {
|
|
245
|
+
task,
|
|
246
|
+
repository: context.repository,
|
|
247
|
+
agent: context.agent,
|
|
248
|
+
worktreeDir: context.worktree.dir,
|
|
249
|
+
branchName: context.worktree.branchName,
|
|
250
|
+
workspaceName: task,
|
|
251
|
+
state: "resumed",
|
|
252
|
+
resumeCount: context.resumeCount + 1,
|
|
253
|
+
completionTaskId: context.completionTaskId,
|
|
254
|
+
...(context.url === undefined ? {} : { url: context.url }),
|
|
255
|
+
...(context.reason === undefined ? {} : { reason: context.reason }),
|
|
256
|
+
},
|
|
257
|
+
});
|
|
238
258
|
}
|
|
239
259
|
catch (error) {
|
|
240
|
-
|
|
241
|
-
|
|
260
|
+
if (workspaceOpened) {
|
|
261
|
+
try {
|
|
262
|
+
const result = await workspaces.close(config, task);
|
|
263
|
+
if (result.kind === "unavailable") {
|
|
264
|
+
const detail = result.error === undefined
|
|
265
|
+
? "workspace backend unavailable"
|
|
266
|
+
: errorMessage(result.error);
|
|
267
|
+
log(`Workspace close was not confirmed during resume rollback for ${task}: ${detail}. Close it manually in the configured workspace backend.`);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
catch (closeError) {
|
|
271
|
+
log(`Workspace close failed during resume rollback for ${task}: ${errorMessage(closeError)}. Close it manually in the configured workspace backend.`);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
cleanupAgentLaunchBestEffort({
|
|
275
|
+
cleanup: cleanupAgentLaunch,
|
|
276
|
+
context: `resume rollback for ${task}`,
|
|
277
|
+
});
|
|
278
|
+
try {
|
|
279
|
+
removeStagedPrompt(stagedPrompt.directory);
|
|
280
|
+
}
|
|
281
|
+
catch (cleanupError) {
|
|
282
|
+
log(`Staged prompt cleanup failed during resume rollback for ${task}: ${errorMessage(cleanupError)}`);
|
|
283
|
+
}
|
|
242
284
|
throw error;
|
|
243
285
|
}
|
|
244
|
-
recordRunState({
|
|
245
|
-
config,
|
|
246
|
-
state: {
|
|
247
|
-
task,
|
|
248
|
-
repository: context.repository,
|
|
249
|
-
agent: context.agent,
|
|
250
|
-
worktreeDir: context.worktree.dir,
|
|
251
|
-
branchName: context.worktree.branchName,
|
|
252
|
-
workspaceName: task,
|
|
253
|
-
state: "resumed",
|
|
254
|
-
resumeCount: context.resumeCount + 1,
|
|
255
|
-
completionTaskId: context.completionTaskId,
|
|
256
|
-
...(context.url === undefined ? {} : { url: context.url }),
|
|
257
|
-
...(context.reason === undefined ? {} : { reason: context.reason }),
|
|
258
|
-
},
|
|
259
|
-
});
|
|
260
286
|
log(`Resumed ${task} in ${context.worktree.dir} (${context.agent})`);
|
|
261
287
|
}
|
|
262
288
|
export async function resumeWorkspaceCli(argv) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setupWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/setupWorkspace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAiBnE,OAAO,EAA0B,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"setupWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/setupWorkspace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAiBnE,OAAO,EAA0B,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAWxF,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,6FAA6F;IAC7F,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAuBD,wBAAsB,cAAc,CAClC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,qBAAqB,EAC9B,UAAU,GAAE,wBAA6B,GACxC,OAAO,CAAC,IAAI,CAAC,CA2Jf;AAiOD,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,OAAO,CAAC,IAAI,CAAC,CAyDf"}
|
|
@@ -13,6 +13,7 @@ import { naturalIdFromCanonical } from "../lib/taskSource.js";
|
|
|
13
13
|
import { debug, errorMessage, log, okMark } from "../lib/util.js";
|
|
14
14
|
import { workspaces } from "../lib/workspaces.js";
|
|
15
15
|
import { resolveLaunchDir, WorktreeAlreadyExistsError, worktrees, } from "../lib/worktrees.js";
|
|
16
|
+
import { cleanupAgentLaunchBestEffort } from "./agentLaunchCleanup.js";
|
|
16
17
|
function stagePrompt(input) {
|
|
17
18
|
return stagePromptFromTemplate({
|
|
18
19
|
config: input.config,
|
|
@@ -166,7 +167,7 @@ export async function setupWorkspace(config, options, runOptions = {}) {
|
|
|
166
167
|
}
|
|
167
168
|
}
|
|
168
169
|
catch (error) {
|
|
169
|
-
cleanupAgentLaunch
|
|
170
|
+
cleanupAgentLaunchBestEffort({ cleanup: cleanupAgentLaunch, context: "setup rollback" });
|
|
170
171
|
await rollbackWorktree({ config, entry: created, promptDir });
|
|
171
172
|
recordFailedToLaunch({ config, options, paths: { worktreeDir, branchName }, error });
|
|
172
173
|
throw error;
|
|
@@ -1,6 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renderers for `crew status`. Three output modes share this file.
|
|
3
|
+
*
|
|
4
|
+
* With no task it renders the inventory: it calls the collectors in
|
|
5
|
+
* statusCollect.ts, joins the two tiers with joinStatus, and prints text.
|
|
6
|
+
* With a task it renders that one task, doing its own I/O rather than using
|
|
7
|
+
* the collectors, because it reads the whole log where they read a tail.
|
|
8
|
+
* With --json it prints and persists the wire documents from statusSnapshot.ts.
|
|
9
|
+
* Text mode persists nothing.
|
|
10
|
+
*
|
|
11
|
+
* @see README.md#status-snapshots-for-external-monitors for the reader contract.
|
|
12
|
+
*/
|
|
1
13
|
import { type ResolvedConfig } from "../lib/config.ts";
|
|
2
14
|
export interface StatusOptions {
|
|
3
15
|
task?: string;
|
|
16
|
+
/** Emit the snapshot documents as JSON and persist them. */
|
|
17
|
+
json?: boolean;
|
|
18
|
+
/** Collect the local tier only. Guarantees this run makes no network call. */
|
|
19
|
+
localOnly?: boolean;
|
|
4
20
|
}
|
|
5
21
|
export declare function status(config: ResolvedConfig, options?: StatusOptions): Promise<void>;
|
|
6
22
|
export declare function statusCli(argv: string[]): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AA0CnE,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,8EAA8E;IAC9E,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AA0hBD,wBAAsB,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAe/F;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAM7D"}
|