@clipboard-health/groundcrew 4.0.1 → 4.0.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.
- package/README.md +70 -80
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +64 -28
- package/dist/commands/doctor.d.ts +1 -6
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +24 -37
- package/dist/commands/interruptWorkspace.d.ts.map +1 -1
- package/dist/commands/interruptWorkspace.js +4 -4
- package/dist/commands/setupRepos.d.ts.map +1 -1
- package/dist/commands/setupRepos.js +2 -13
- package/dist/commands/status.d.ts +7 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +178 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/lib/util.d.ts +14 -2
- package/dist/lib/util.d.ts.map +1 -1
- package/dist/lib/util.js +39 -2
- package/package.json +1 -1
- package/dist/commands/ticketCheck.d.ts +0 -22
- package/dist/commands/ticketCheck.d.ts.map +0 -1
- package/dist/commands/ticketCheck.js +0 -23
- package/dist/commands/ticketDoctor.d.ts +0 -223
- package/dist/commands/ticketDoctor.d.ts.map +0 -1
- package/dist/commands/ticketDoctor.js +0 -1134
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { fetchRawLinearIssue } from "../lib/boardSource.js";
|
|
3
|
+
import { loadConfig } from "../lib/config.js";
|
|
4
|
+
import { readRunState } from "../lib/runState.js";
|
|
5
|
+
import { errorMessage, getLinearClient, withLogOutputSuppressed, writeOutput, } from "../lib/util.js";
|
|
6
|
+
import { workspaces } from "../lib/workspaces.js";
|
|
7
|
+
import { worktrees } from "../lib/worktrees.js";
|
|
8
|
+
const RECENT_LOG_LINE_COUNT = 10;
|
|
9
|
+
function escapeRegExp(value) {
|
|
10
|
+
return value.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw `\$&`);
|
|
11
|
+
}
|
|
12
|
+
function ticketLinePattern(ticket) {
|
|
13
|
+
return new RegExp(`(^|[^a-z0-9])${escapeRegExp(ticket)}([^a-z0-9]|$)`, "i");
|
|
14
|
+
}
|
|
15
|
+
function parseArguments(argv) {
|
|
16
|
+
const [ticket, ...extras] = argv;
|
|
17
|
+
if (extras.length > 0 || ticket?.length === 0 || ticket?.startsWith("-") === true) {
|
|
18
|
+
throw new Error("Usage: crew status [<ticket>]");
|
|
19
|
+
}
|
|
20
|
+
return ticket === undefined ? {} : { ticket: ticket.toLowerCase() };
|
|
21
|
+
}
|
|
22
|
+
function writeSection(title) {
|
|
23
|
+
writeOutput();
|
|
24
|
+
writeOutput(title);
|
|
25
|
+
writeOutput("-".repeat(title.length));
|
|
26
|
+
}
|
|
27
|
+
function writeConfigSnapshot(config) {
|
|
28
|
+
writeSection("Config snapshot");
|
|
29
|
+
writeOutput(`projectDir: ${config.workspace.projectDir}`);
|
|
30
|
+
writeOutput(`repositories: ${config.workspace.knownRepositories.join(", ")}`);
|
|
31
|
+
writeOutput(`git: remote=${config.git.remote}; defaultBranch=${config.git.defaultBranch}`);
|
|
32
|
+
writeOutput(`workspaceKind: ${config.workspaceKind}`);
|
|
33
|
+
writeOutput(`local.runner: ${config.local.runner}`);
|
|
34
|
+
writeOutput(`models: default=${config.models.default}; enabled=${Object.keys(config.models.definitions).join(", ")}`);
|
|
35
|
+
writeOutput(`logFile: ${config.logging.file}`);
|
|
36
|
+
}
|
|
37
|
+
function formatDirtiness(dirtiness) {
|
|
38
|
+
if (dirtiness.kind === "dirty") {
|
|
39
|
+
return `dirty (${dirtiness.modified} modified, ${dirtiness.untracked} untracked)`;
|
|
40
|
+
}
|
|
41
|
+
return dirtiness.kind;
|
|
42
|
+
}
|
|
43
|
+
async function writeTicketWorktrees(config, ticket) {
|
|
44
|
+
writeSection("Worktree state");
|
|
45
|
+
const entries = worktrees.findByTicket(config, ticket);
|
|
46
|
+
if (entries.length === 0) {
|
|
47
|
+
writeOutput("(none)");
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
for (const entry of entries) {
|
|
51
|
+
// oxlint-disable-next-line no-await-in-loop -- status output is easier to read in worktree order.
|
|
52
|
+
const dirtiness = await worktrees.probeWorkingTree({ worktreeDir: entry.dir });
|
|
53
|
+
writeOutput(`- ${entry.repository} ${entry.kind}`);
|
|
54
|
+
writeOutput(` ticket: ${entry.ticket}`);
|
|
55
|
+
writeOutput(` branch: ${entry.branchName}`);
|
|
56
|
+
writeOutput(` dir: ${entry.dir}`);
|
|
57
|
+
writeOutput(` git: ${formatDirtiness(dirtiness)}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function workspaceProbeUnavailableLine(probe) {
|
|
61
|
+
return probe.error === undefined
|
|
62
|
+
? "Workspace probe unavailable"
|
|
63
|
+
: `Workspace probe unavailable: ${errorMessage(probe.error)}`;
|
|
64
|
+
}
|
|
65
|
+
function writeTicketWorkspace(probe, ticket) {
|
|
66
|
+
writeSection("Workspace probe");
|
|
67
|
+
if (probe.kind === "unavailable") {
|
|
68
|
+
writeOutput(workspaceProbeUnavailableLine(probe));
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
writeOutput(`live: ${probe.names.has(ticket) ? "yes" : "no"}`);
|
|
72
|
+
}
|
|
73
|
+
function formatRunState(state) {
|
|
74
|
+
if (state === undefined) {
|
|
75
|
+
return "(none)";
|
|
76
|
+
}
|
|
77
|
+
const summary = `${state.state}; model=${state.model}; updated=${state.updatedAt}; resumes=${state.resumeCount}`;
|
|
78
|
+
const detail = state.reason ?? state.detail;
|
|
79
|
+
return detail === undefined ? summary : `${summary}; ${detail}`;
|
|
80
|
+
}
|
|
81
|
+
function recentTicketLogLines(config, ticket) {
|
|
82
|
+
let raw;
|
|
83
|
+
try {
|
|
84
|
+
raw = readFileSync(config.logging.file, "utf8");
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
89
|
+
const pattern = ticketLinePattern(ticket);
|
|
90
|
+
return raw
|
|
91
|
+
.split("\n")
|
|
92
|
+
.filter((line) => pattern.test(line))
|
|
93
|
+
.slice(-RECENT_LOG_LINE_COUNT);
|
|
94
|
+
}
|
|
95
|
+
async function linearStatus(ticket) {
|
|
96
|
+
try {
|
|
97
|
+
const issue = await fetchRawLinearIssue({ client: getLinearClient(), ticket });
|
|
98
|
+
return `${issue.stateName} (state.type=${issue.stateType ?? "unknown"}) — ${issue.title}`;
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
return `unavailable: ${errorMessage(error)}`;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
async function writeTicketStatus(config, rawTicket) {
|
|
105
|
+
const ticket = rawTicket.toLowerCase();
|
|
106
|
+
const displayTicket = ticket.toUpperCase();
|
|
107
|
+
writeOutput(`groundcrew status ${displayTicket}`);
|
|
108
|
+
writeOutput("=".repeat(`groundcrew status ${displayTicket}`.length));
|
|
109
|
+
writeOutput(`ticket: ${ticket}`);
|
|
110
|
+
writeConfigSnapshot(config);
|
|
111
|
+
await writeTicketWorktrees(config, ticket);
|
|
112
|
+
const workspaceProbe = await withLogOutputSuppressed(async () => await workspaces.probe(config));
|
|
113
|
+
writeTicketWorkspace(workspaceProbe, ticket);
|
|
114
|
+
writeSection("Run state");
|
|
115
|
+
writeOutput(formatRunState(readRunState(config, ticket)));
|
|
116
|
+
writeSection("Recent logs");
|
|
117
|
+
const logLines = recentTicketLogLines(config, ticket);
|
|
118
|
+
writeOutput(logLines.length === 0 ? "(none)" : logLines.join("\n"));
|
|
119
|
+
writeSection("Last Linear status");
|
|
120
|
+
writeOutput(await linearStatus(ticket));
|
|
121
|
+
}
|
|
122
|
+
function workspacePresence(probe, ticket) {
|
|
123
|
+
if (probe.kind === "unavailable") {
|
|
124
|
+
return "unknown";
|
|
125
|
+
}
|
|
126
|
+
return probe.names.has(ticket) ? "yes" : "no";
|
|
127
|
+
}
|
|
128
|
+
function writeInventoryWorktrees(config, probe) {
|
|
129
|
+
writeSection("Worktrees");
|
|
130
|
+
const entries = worktrees
|
|
131
|
+
.list(config)
|
|
132
|
+
.toSorted((left, right) => left.ticket.localeCompare(right.ticket));
|
|
133
|
+
if (entries.length === 0) {
|
|
134
|
+
writeOutput("(none)");
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const runStates = new Map();
|
|
138
|
+
for (const entry of entries) {
|
|
139
|
+
if (!runStates.has(entry.ticket)) {
|
|
140
|
+
runStates.set(entry.ticket, readRunState(config, entry.ticket));
|
|
141
|
+
}
|
|
142
|
+
const runState = runStates.get(entry.ticket);
|
|
143
|
+
writeOutput(`${entry.ticket} ${entry.repository} ${entry.kind} workspace=${workspacePresence(probe, entry.ticket)} run=${runState?.state ?? "none"}`);
|
|
144
|
+
writeOutput(` ${entry.branchName} ${entry.dir}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function writeInventoryWorkspaces(probe) {
|
|
148
|
+
writeSection("Live workspaces");
|
|
149
|
+
if (probe.kind === "unavailable") {
|
|
150
|
+
writeOutput(workspaceProbeUnavailableLine(probe));
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const names = [...probe.names].toSorted();
|
|
154
|
+
writeOutput(names.length === 0 ? "(none)" : names.join("\n"));
|
|
155
|
+
}
|
|
156
|
+
async function writeInventoryStatus(config) {
|
|
157
|
+
writeOutput("groundcrew status");
|
|
158
|
+
writeOutput("=================");
|
|
159
|
+
const probe = await withLogOutputSuppressed(async () => await workspaces.probe(config));
|
|
160
|
+
writeInventoryWorktrees(config, probe);
|
|
161
|
+
writeInventoryWorkspaces(probe);
|
|
162
|
+
}
|
|
163
|
+
export async function status(config, options = {}) {
|
|
164
|
+
const ticket = options.ticket?.trim();
|
|
165
|
+
if (ticket === undefined) {
|
|
166
|
+
await writeInventoryStatus(config);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (ticket.length === 0 || ticket.startsWith("-")) {
|
|
170
|
+
throw new Error("ticket must be a non-empty value");
|
|
171
|
+
}
|
|
172
|
+
await writeTicketStatus(config, ticket);
|
|
173
|
+
}
|
|
174
|
+
export async function statusCli(argv) {
|
|
175
|
+
const options = parseArguments(argv);
|
|
176
|
+
const config = await loadConfig();
|
|
177
|
+
await status(config, options);
|
|
178
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export { interruptWorkspace, type InterruptWorkspaceOptions, } from "./commands/
|
|
|
5
5
|
export { orchestrate, type OrchestratorOptions } from "./commands/orchestrator.ts";
|
|
6
6
|
export { resumeWorkspace, type ResumeWorkspaceOptions } from "./commands/resumeWorkspace.ts";
|
|
7
7
|
export { setupWorkspace, type SetupWorkspaceOptions } from "./commands/setupWorkspace.ts";
|
|
8
|
+
export { status, type StatusOptions } from "./commands/status.ts";
|
|
8
9
|
export type { Config, ModelDefinition, ResolvedConfig, SourceConfig } from "./lib/config.ts";
|
|
9
10
|
export { loadConfig } from "./lib/config.ts";
|
|
10
11
|
export { readRunState, recordRunState, removeRunState, runStateDirectory, runStatePath, updateRunState, type RunLifecycleState, type RunState, } from "./lib/runState.ts";
|
|
@@ -15,6 +16,4 @@ export { buildSources, buildSourcesWith } from "./lib/buildSources.ts";
|
|
|
15
16
|
export type { AdapterContext, AdapterDefinition } from "./lib/adapterDefinition.ts";
|
|
16
17
|
export { adapterRegistry, type AdapterLoader, buildRegistry, buildSourceConfigSchema, listAdapterDirectories, } from "./lib/adapters/registry.ts";
|
|
17
18
|
export { AmbiguousTicketError, type Blocker as CanonicalBlocker, type BoardState as CanonicalBoardState, type CanonicalStatus, type GroundcrewIssue as CanonicalGroundcrewIssue, type Issue as CanonicalIssue, isGroundcrewIssue as isCanonicalGroundcrewIssue, type TicketSource, } from "./lib/ticketSource.ts";
|
|
18
|
-
export type { TicketCheck } from "./commands/ticketCheck.ts";
|
|
19
|
-
export { ticketDoctor, type TicketDoctorDependencies, type TicketDoctorResult, type TicketDoctorVerdict, } from "./commands/ticketDoctor.ts";
|
|
20
19
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,gBAAgB,EAAE,KAAK,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAChG,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EACL,kBAAkB,EAClB,KAAK,yBAAyB,GAC/B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,KAAK,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACnF,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAC7F,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAC1F,YAAY,EAAE,MAAM,EAAE,eAAe,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC7F,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EACL,YAAY,EACZ,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,KAAK,iBAAiB,EACtB,KAAK,QAAQ,GACd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,sBAAsB,EACtB,yBAAyB,EACzB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,WAAW,EACX,mBAAmB,EACnB,0BAA0B,EAC1B,wBAAwB,EACxB,eAAe,EACf,oBAAoB,EACpB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,oBAAoB,GAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,eAAe,EAAE,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,EAAE,KAAK,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACvE,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACpF,OAAO,EACL,eAAe,EACf,KAAK,aAAa,EAClB,aAAa,EACb,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,oBAAoB,EACpB,KAAK,OAAO,IAAI,gBAAgB,EAChC,KAAK,UAAU,IAAI,mBAAmB,EACtC,KAAK,eAAe,EACpB,KAAK,eAAe,IAAI,wBAAwB,EAChD,KAAK,KAAK,IAAI,cAAc,EAC5B,iBAAiB,IAAI,0BAA0B,EAC/C,KAAK,YAAY,GAClB,MAAM,uBAAuB,CAAC
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,gBAAgB,EAAE,KAAK,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAChG,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EACL,kBAAkB,EAClB,KAAK,yBAAyB,GAC/B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,KAAK,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACnF,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAC7F,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAC1F,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAClE,YAAY,EAAE,MAAM,EAAE,eAAe,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC7F,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EACL,YAAY,EACZ,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,KAAK,iBAAiB,EACtB,KAAK,QAAQ,GACd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,sBAAsB,EACtB,yBAAyB,EACzB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,WAAW,EACX,mBAAmB,EACnB,0BAA0B,EAC1B,wBAAwB,EACxB,eAAe,EACf,oBAAoB,EACpB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,oBAAoB,GAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,eAAe,EAAE,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,EAAE,KAAK,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACvE,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACpF,OAAO,EACL,eAAe,EACf,KAAK,aAAa,EAClB,aAAa,EACb,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,oBAAoB,EACpB,KAAK,OAAO,IAAI,gBAAgB,EAChC,KAAK,UAAU,IAAI,mBAAmB,EACtC,KAAK,eAAe,EACpB,KAAK,eAAe,IAAI,wBAAwB,EAChD,KAAK,KAAK,IAAI,cAAc,EAC5B,iBAAiB,IAAI,0BAA0B,EAC/C,KAAK,YAAY,GAClB,MAAM,uBAAuB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export { interruptWorkspace, } from "./commands/interruptWorkspace.js";
|
|
|
5
5
|
export { orchestrate } from "./commands/orchestrator.js";
|
|
6
6
|
export { resumeWorkspace } from "./commands/resumeWorkspace.js";
|
|
7
7
|
export { setupWorkspace } from "./commands/setupWorkspace.js";
|
|
8
|
+
export { status } from "./commands/status.js";
|
|
8
9
|
export { loadConfig } from "./lib/config.js";
|
|
9
10
|
export { readRunState, recordRunState, removeRunState, runStateDirectory, runStatePath, updateRunState, } from "./lib/runState.js";
|
|
10
11
|
export { fetchBlockersForTicket, fetchInProgressIssueCount, fetchRawLinearIssue, fetchResolvedIssue, isIssueInProgress, isIssueTodo, isTerminalStateType, isTerminalStatusForBlocker, isTerminalStatusForIssue, resolveModelFor, resolveRepositoryFor, } from "./lib/boardSource.js";
|
|
@@ -13,4 +14,4 @@ export { createBoard } from "./lib/board.js";
|
|
|
13
14
|
export { buildSources, buildSourcesWith } from "./lib/buildSources.js";
|
|
14
15
|
export { adapterRegistry, buildRegistry, buildSourceConfigSchema, listAdapterDirectories, } from "./lib/adapters/registry.js";
|
|
15
16
|
export { AmbiguousTicketError, isGroundcrewIssue as isCanonicalGroundcrewIssue, } from "./lib/ticketSource.js";
|
|
16
|
-
|
|
17
|
+
// RepositoryResolutionError is exported via boardSource.ts above (single canonical location).
|
package/dist/lib/util.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export declare function sleep(ms: number, signal?: AbortSignal): Promise<void>;
|
|
|
3
3
|
export declare function writeOutput(message?: string): void;
|
|
4
4
|
export declare function writeError(message: string): void;
|
|
5
5
|
export declare function setLogFile(path: string | undefined): void;
|
|
6
|
+
export declare function withLogOutputSuppressed<T>(operation: () => Promise<T>): Promise<T>;
|
|
6
7
|
export declare function log(message: string): void;
|
|
7
8
|
type LogEventFieldValue = boolean | number | string | readonly string[] | undefined;
|
|
8
9
|
export declare function logEvent(event: string, fields: Record<string, LogEventFieldValue>): void;
|
|
@@ -18,8 +19,8 @@ export declare function getLinearClient(): LinearClient;
|
|
|
18
19
|
/**
|
|
19
20
|
* Returns a zero-arg getter that lazily constructs (and caches) a Linear
|
|
20
21
|
* client on first call. Used by CLI entry points that may not need the
|
|
21
|
-
* client at all
|
|
22
|
-
*
|
|
22
|
+
* client at all, so we avoid blowing up on a missing API key when no Linear
|
|
23
|
+
* call is actually made. The factory is taken as a
|
|
23
24
|
* parameter (rather than calling `getLinearClient` directly) so callers can
|
|
24
25
|
* pass their own module-level import of `getLinearClient` — that binding
|
|
25
26
|
* respects `vi.mock` intercepts, whereas an intra-module reference would
|
|
@@ -33,6 +34,17 @@ export declare function lazyLinearClient(factory: () => LinearClient): () => Lin
|
|
|
33
34
|
* each subcommand's arg parser stays DRY.
|
|
34
35
|
*/
|
|
35
36
|
export declare function readTicketArgument(argv: string[], index: number, command: string): string;
|
|
37
|
+
export interface DryRunPositionals {
|
|
38
|
+
dryRun: boolean;
|
|
39
|
+
positionals: string[];
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Parses an argv that accepts an optional `--dry-run` flag plus free
|
|
43
|
+
* positionals, rejecting any other dash-prefixed token. Shared by the
|
|
44
|
+
* subcommands whose only flag is `--dry-run` so each parser stays DRY; pass the
|
|
45
|
+
* command's `usage` string for the "Unknown option" error.
|
|
46
|
+
*/
|
|
47
|
+
export declare function parseDryRunPositionals(argv: string[], usage: string): DryRunPositionals;
|
|
36
48
|
export declare function errorMessage(error: unknown): string;
|
|
37
49
|
export {};
|
|
38
50
|
//# sourceMappingURL=util.d.ts.map
|
package/dist/lib/util.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/lib/util.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,wBAAsB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAoB3E;AAED,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAIlD;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAGhD;
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/lib/util.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,wBAAsB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAoB3E;AAED,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAIlD;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAGhD;AAQD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAEzD;AAED,wBAAsB,uBAAuB,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAOxF;AAkBD,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAQzC;AAED,KAAK,kBAAkB,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;AAUpF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,GAAG,IAAI,CAcxF;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGxE;AAED,QAAA,MAAM,sBAAsB,YAAI,2BAA2B,EAAE,gBAAgB,CAAU,CAAC;AAExF,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzE,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,kBAAkB,CAAC;CAC5B;AAED,wBAAgB,mBAAmB,IAAI,oBAAoB,GAAG,SAAS,CAQtE;AAED,wBAAgB,eAAe,IAAI,YAAY,CAQ9C;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,YAAY,GAAG,MAAM,YAAY,CAMhF;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAMzF;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,iBAAiB,CAcvF;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAcnD"}
|
package/dist/lib/util.js
CHANGED
|
@@ -35,9 +35,19 @@ export function writeError(message) {
|
|
|
35
35
|
// so tests don't write to the host filesystem; the CLI arms it after
|
|
36
36
|
// loadConfig() resolves `logging.file`.
|
|
37
37
|
let logFilePath;
|
|
38
|
+
let suppressedLogDepth = 0;
|
|
38
39
|
export function setLogFile(path) {
|
|
39
40
|
logFilePath = path;
|
|
40
41
|
}
|
|
42
|
+
export async function withLogOutputSuppressed(operation) {
|
|
43
|
+
suppressedLogDepth += 1;
|
|
44
|
+
try {
|
|
45
|
+
return await operation();
|
|
46
|
+
}
|
|
47
|
+
finally {
|
|
48
|
+
suppressedLogDepth -= 1;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
41
51
|
function appendLogLine(line) {
|
|
42
52
|
if (logFilePath === undefined) {
|
|
43
53
|
return;
|
|
@@ -55,6 +65,9 @@ function appendLogLine(line) {
|
|
|
55
65
|
}
|
|
56
66
|
}
|
|
57
67
|
export function log(message) {
|
|
68
|
+
if (suppressedLogDepth > 0) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
58
71
|
const timestamp = new Date().toLocaleTimeString();
|
|
59
72
|
const line = `[${timestamp}] ${message}`;
|
|
60
73
|
writeOutput(line);
|
|
@@ -68,6 +81,9 @@ function formatLogEventFieldValue(value) {
|
|
|
68
81
|
return JSON.stringify(raw);
|
|
69
82
|
}
|
|
70
83
|
export function logEvent(event, fields) {
|
|
84
|
+
if (suppressedLogDepth > 0) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
71
87
|
const parts = [`event=${formatLogEventFieldValue(event)}`];
|
|
72
88
|
for (const [key, value] of Object.entries(fields)) {
|
|
73
89
|
if (value === undefined) {
|
|
@@ -103,8 +119,8 @@ export function getLinearClient() {
|
|
|
103
119
|
/**
|
|
104
120
|
* Returns a zero-arg getter that lazily constructs (and caches) a Linear
|
|
105
121
|
* client on first call. Used by CLI entry points that may not need the
|
|
106
|
-
* client at all
|
|
107
|
-
*
|
|
122
|
+
* client at all, so we avoid blowing up on a missing API key when no Linear
|
|
123
|
+
* call is actually made. The factory is taken as a
|
|
108
124
|
* parameter (rather than calling `getLinearClient` directly) so callers can
|
|
109
125
|
* pass their own module-level import of `getLinearClient` — that binding
|
|
110
126
|
* respects `vi.mock` intercepts, whereas an intra-module reference would
|
|
@@ -130,6 +146,27 @@ export function readTicketArgument(argv, index, command) {
|
|
|
130
146
|
}
|
|
131
147
|
return value;
|
|
132
148
|
}
|
|
149
|
+
/**
|
|
150
|
+
* Parses an argv that accepts an optional `--dry-run` flag plus free
|
|
151
|
+
* positionals, rejecting any other dash-prefixed token. Shared by the
|
|
152
|
+
* subcommands whose only flag is `--dry-run` so each parser stays DRY; pass the
|
|
153
|
+
* command's `usage` string for the "Unknown option" error.
|
|
154
|
+
*/
|
|
155
|
+
export function parseDryRunPositionals(argv, usage) {
|
|
156
|
+
let dryRun = false;
|
|
157
|
+
const positionals = [];
|
|
158
|
+
for (const argument of argv) {
|
|
159
|
+
if (argument === "--dry-run") {
|
|
160
|
+
dryRun = true;
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
if (argument.startsWith("-")) {
|
|
164
|
+
throw new Error(`Unknown option: ${argument}\nUsage: ${usage}`);
|
|
165
|
+
}
|
|
166
|
+
positionals.push(argument);
|
|
167
|
+
}
|
|
168
|
+
return { dryRun, positionals };
|
|
169
|
+
}
|
|
133
170
|
export function errorMessage(error) {
|
|
134
171
|
if (error instanceof Error) {
|
|
135
172
|
return error.message;
|
package/package.json
CHANGED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
export interface TicketCheck {
|
|
2
|
-
name: string;
|
|
3
|
-
status: "ok" | "fail" | "skipped";
|
|
4
|
-
detail?: string;
|
|
5
|
-
failureSummary?: string;
|
|
6
|
-
}
|
|
7
|
-
export interface Section {
|
|
8
|
-
name: string;
|
|
9
|
-
checks: TicketCheck[];
|
|
10
|
-
/** When present and `checks` is empty, the section renders as `(skipped — <skipReason>)`. */
|
|
11
|
-
skipReason?: string;
|
|
12
|
-
}
|
|
13
|
-
interface RenderInput {
|
|
14
|
-
command: string;
|
|
15
|
-
argument: string;
|
|
16
|
-
title?: string;
|
|
17
|
-
sections: Section[];
|
|
18
|
-
verdict: string;
|
|
19
|
-
}
|
|
20
|
-
export declare function renderTicketCheckResult(input: RenderInput): string[];
|
|
21
|
-
export {};
|
|
22
|
-
//# sourceMappingURL=ticketCheck.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ticketCheck.d.ts","sourceRoot":"","sources":["../../src/commands/ticketCheck.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,6FAA6F;IAC7F,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,WAAW;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAqBD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,EAAE,CAMpE"}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
const STATUS_TAG = {
|
|
2
|
-
ok: "[ok]",
|
|
3
|
-
fail: "[--]",
|
|
4
|
-
skipped: "[? ]",
|
|
5
|
-
};
|
|
6
|
-
function formatCheck(check) {
|
|
7
|
-
const tag = STATUS_TAG[check.status];
|
|
8
|
-
const detail = check.detail === undefined ? "" : ` (${check.detail})`;
|
|
9
|
-
return ` ${tag} ${check.name}${detail}`;
|
|
10
|
-
}
|
|
11
|
-
function sectionLines(section) {
|
|
12
|
-
if (section.checks.length === 0 && section.skipReason !== undefined) {
|
|
13
|
-
return [section.name, ` (skipped — ${section.skipReason})`];
|
|
14
|
-
}
|
|
15
|
-
return [section.name, ...section.checks.map(formatCheck)];
|
|
16
|
-
}
|
|
17
|
-
export function renderTicketCheckResult(input) {
|
|
18
|
-
const titlePart = input.title === undefined ? "" : ` (${input.title})`;
|
|
19
|
-
const header = `groundcrew ${input.command} ${input.argument}${titlePart}`;
|
|
20
|
-
const bar = "─".repeat(header.length);
|
|
21
|
-
const body = input.sections.flatMap((section) => ["", ...sectionLines(section)]);
|
|
22
|
-
return [header, bar, ...body, "", input.verdict];
|
|
23
|
-
}
|
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
import { type Blocker, type RawLinearIssue } from "../lib/boardSource.ts";
|
|
2
|
-
import { type ResolvedConfig } from "../lib/config.ts";
|
|
3
|
-
import { type RunState } from "../lib/runState.ts";
|
|
4
|
-
import { type UsageByModel } from "../lib/usage.ts";
|
|
5
|
-
import { type WorkspaceAccessHint, type WorkspaceProbe } from "../lib/workspaces.ts";
|
|
6
|
-
import { type WorktreeDirtiness, type WorktreeEntry } from "../lib/worktrees.ts";
|
|
7
|
-
import { type TicketCheck } from "./ticketCheck.ts";
|
|
8
|
-
export type TicketDoctorVerdict = {
|
|
9
|
-
kind: "pr-open";
|
|
10
|
-
number: number;
|
|
11
|
-
url: string;
|
|
12
|
-
} | {
|
|
13
|
-
kind: "pr-merged";
|
|
14
|
-
number: number;
|
|
15
|
-
url: string;
|
|
16
|
-
} | {
|
|
17
|
-
kind: "interrupted";
|
|
18
|
-
reason: string;
|
|
19
|
-
nextStep: string;
|
|
20
|
-
} | {
|
|
21
|
-
kind: "failed-launch";
|
|
22
|
-
reason: string;
|
|
23
|
-
nextStep: string;
|
|
24
|
-
} | {
|
|
25
|
-
kind: "in-flight";
|
|
26
|
-
reason: string;
|
|
27
|
-
} | {
|
|
28
|
-
kind: "recoverable";
|
|
29
|
-
reason: string;
|
|
30
|
-
nextStep: string;
|
|
31
|
-
} | {
|
|
32
|
-
kind: "would-dispatch";
|
|
33
|
-
} | {
|
|
34
|
-
kind: "ineligible";
|
|
35
|
-
reason: string;
|
|
36
|
-
} | {
|
|
37
|
-
kind: "unresolvable";
|
|
38
|
-
reason: string;
|
|
39
|
-
} | {
|
|
40
|
-
kind: "lost";
|
|
41
|
-
reason: string;
|
|
42
|
-
};
|
|
43
|
-
export type LinearStatusProbe = {
|
|
44
|
-
kind: "terminal";
|
|
45
|
-
stateName: string;
|
|
46
|
-
} | {
|
|
47
|
-
kind: "non-terminal";
|
|
48
|
-
stateName: string;
|
|
49
|
-
} | {
|
|
50
|
-
kind: "skipped";
|
|
51
|
-
} | {
|
|
52
|
-
kind: "unresolvable";
|
|
53
|
-
reason: string;
|
|
54
|
-
};
|
|
55
|
-
export type WorktreeProbe = {
|
|
56
|
-
kind: "present-clean";
|
|
57
|
-
} | {
|
|
58
|
-
kind: "present-dirty";
|
|
59
|
-
modified: number;
|
|
60
|
-
untracked: number;
|
|
61
|
-
} | {
|
|
62
|
-
kind: "present-unknown-dirtiness";
|
|
63
|
-
reason: string;
|
|
64
|
-
} | {
|
|
65
|
-
kind: "absent";
|
|
66
|
-
};
|
|
67
|
-
export type LocalBranchProbe = {
|
|
68
|
-
kind: "present";
|
|
69
|
-
ahead: number;
|
|
70
|
-
behind: number;
|
|
71
|
-
defaultBranch?: string;
|
|
72
|
-
} | {
|
|
73
|
-
kind: "absent";
|
|
74
|
-
} | {
|
|
75
|
-
kind: "unknown";
|
|
76
|
-
reason: string;
|
|
77
|
-
};
|
|
78
|
-
export type RemoteBranchProbe = {
|
|
79
|
-
kind: "present";
|
|
80
|
-
} | {
|
|
81
|
-
kind: "absent";
|
|
82
|
-
} | {
|
|
83
|
-
kind: "unknown";
|
|
84
|
-
reason: string;
|
|
85
|
-
};
|
|
86
|
-
export type PullRequestProbe = {
|
|
87
|
-
kind: "open";
|
|
88
|
-
number: number;
|
|
89
|
-
url: string;
|
|
90
|
-
} | {
|
|
91
|
-
kind: "merged";
|
|
92
|
-
number: number;
|
|
93
|
-
url: string;
|
|
94
|
-
} | {
|
|
95
|
-
kind: "absent";
|
|
96
|
-
} | {
|
|
97
|
-
kind: "gh-missing";
|
|
98
|
-
} | {
|
|
99
|
-
kind: "unknown";
|
|
100
|
-
reason: string;
|
|
101
|
-
};
|
|
102
|
-
export interface DecideVerdictInput {
|
|
103
|
-
linear: LinearStatusProbe;
|
|
104
|
-
worktree: WorktreeProbe;
|
|
105
|
-
localBranch: LocalBranchProbe;
|
|
106
|
-
remoteBranch: RemoteBranchProbe;
|
|
107
|
-
pullRequest: PullRequestProbe;
|
|
108
|
-
branch: string;
|
|
109
|
-
worktreeDir: string | undefined;
|
|
110
|
-
workspaceName: string | undefined;
|
|
111
|
-
runState: RunState | undefined;
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* Returns a post-dispatch verdict if the probe bundle matches one of the
|
|
115
|
-
* "ticket has moved past dispatch" cases. Returns `undefined` otherwise,
|
|
116
|
-
* signalling that the caller should fall through to the pre-dispatch path.
|
|
117
|
-
*
|
|
118
|
-
* Precedence: PR verdicts always win. Failed launches report before ordinary
|
|
119
|
-
* local recovery. Interrupted runs report concrete recoverable git work first
|
|
120
|
-
* when it exists, then fall back to `interrupted`. Ordinary post-dispatch cases
|
|
121
|
-
* report in-flight before recoverable. Inside `recoverable`, dirty worktree
|
|
122
|
-
* beats clean-with-un-pushed-local beats remote-only beats stranded local.
|
|
123
|
-
*/
|
|
124
|
-
export declare function decidePostDispatchVerdict(input: DecideVerdictInput): TicketDoctorVerdict | undefined;
|
|
125
|
-
export interface TicketDoctorDependencies {
|
|
126
|
-
config: ResolvedConfig;
|
|
127
|
-
ticket: string;
|
|
128
|
-
/**
|
|
129
|
-
* Injected to keep `ticketDoctor` pure and easy to unit-test. `undefined`
|
|
130
|
-
* means the caller passed `--no-linear` — the Linear-backed pre-dispatch
|
|
131
|
-
* checks (status, label, repo, eligibility) are all skipped.
|
|
132
|
-
*/
|
|
133
|
-
fetchRawIssue: ((input: {
|
|
134
|
-
ticket: string;
|
|
135
|
-
}) => Promise<RawLinearIssue>) | undefined;
|
|
136
|
-
fetchBlockersFor: (input: {
|
|
137
|
-
ticket: string;
|
|
138
|
-
uuid: string;
|
|
139
|
-
}) => Promise<readonly Blocker[]>;
|
|
140
|
-
fetchUsage: () => Promise<UsageByModel>;
|
|
141
|
-
countInProgress: () => Promise<number>;
|
|
142
|
-
findWorktree: (ticket: string) => WorktreeEntry | undefined;
|
|
143
|
-
probeWorkspaces: () => Promise<WorkspaceProbe>;
|
|
144
|
-
workspaceAccessHint: (name: string) => Promise<WorkspaceAccessHint | undefined>;
|
|
145
|
-
probeWorkingTree: (input: {
|
|
146
|
-
worktreeDir: string;
|
|
147
|
-
}) => Promise<WorktreeDirtiness>;
|
|
148
|
-
/**
|
|
149
|
-
* Resolves the default branch for `repoDir` (e.g. "master" vs "main") from
|
|
150
|
-
* the local clone's `refs/remotes/<remote>/HEAD`, falling back to
|
|
151
|
-
* `config.git.defaultBranch`. Injected so probeLocalBranchSection can pass a
|
|
152
|
-
* per-repo branch into `probeLocalBranch` without each probe needing to
|
|
153
|
-
* shell out to git itself.
|
|
154
|
-
*/
|
|
155
|
-
resolveDefaultBranch: (input: {
|
|
156
|
-
repoDir: string;
|
|
157
|
-
}) => Promise<string>;
|
|
158
|
-
probeLocalBranch: (input: {
|
|
159
|
-
repoDir: string;
|
|
160
|
-
branch: string;
|
|
161
|
-
remote: string;
|
|
162
|
-
defaultBranch: string;
|
|
163
|
-
}) => Promise<LocalBranchProbe>;
|
|
164
|
-
probeRemoteBranch: (input: {
|
|
165
|
-
repoDir: string;
|
|
166
|
-
branch: string;
|
|
167
|
-
remote: string;
|
|
168
|
-
doFetch: boolean;
|
|
169
|
-
}) => Promise<RemoteBranchProbe>;
|
|
170
|
-
probePullRequest: (input: {
|
|
171
|
-
repoDir: string;
|
|
172
|
-
branch: string;
|
|
173
|
-
}) => Promise<PullRequestProbe>;
|
|
174
|
-
readRunState: (ticket: string) => RunState | undefined;
|
|
175
|
-
doFetch: boolean;
|
|
176
|
-
}
|
|
177
|
-
export interface TicketDoctorResult {
|
|
178
|
-
ticket: string;
|
|
179
|
-
title?: string;
|
|
180
|
-
resolution: TicketCheck[];
|
|
181
|
-
eligibility: TicketCheck[];
|
|
182
|
-
runState: TicketCheck[];
|
|
183
|
-
worktree: TicketCheck[];
|
|
184
|
-
workspace: TicketCheck[];
|
|
185
|
-
localBranch: TicketCheck[];
|
|
186
|
-
remoteBranch: TicketCheck[];
|
|
187
|
-
pullRequest: TicketCheck[];
|
|
188
|
-
skipReasons: {
|
|
189
|
-
resolution: string;
|
|
190
|
-
eligibility: string;
|
|
191
|
-
worktree: string;
|
|
192
|
-
runState: string;
|
|
193
|
-
workspace: string;
|
|
194
|
-
localBranch: string;
|
|
195
|
-
remoteBranch: string;
|
|
196
|
-
pullRequest: string;
|
|
197
|
-
};
|
|
198
|
-
verdict: TicketDoctorVerdict;
|
|
199
|
-
}
|
|
200
|
-
/**
|
|
201
|
-
* Pure-with-async orchestrator that gathers all sections plus the verdict.
|
|
202
|
-
* All I/O happens via injected probes — the function itself does no
|
|
203
|
-
* filesystem, network, or stdout work.
|
|
204
|
-
*/
|
|
205
|
-
export declare function ticketDoctor(dependencies: TicketDoctorDependencies): Promise<TicketDoctorResult>;
|
|
206
|
-
interface TicketDoctorArguments {
|
|
207
|
-
ticket: string;
|
|
208
|
-
doLinear: boolean;
|
|
209
|
-
doFetch: boolean;
|
|
210
|
-
}
|
|
211
|
-
/**
|
|
212
|
-
* Parses optional `--no-linear` and `--no-fetch` flags that follow
|
|
213
|
-
* `crew doctor --ticket <id>`. The ticket id is consumed by `cli.ts` before
|
|
214
|
-
* this point.
|
|
215
|
-
*/
|
|
216
|
-
export declare function parseTicketDoctorFlags(argv: string[]): {
|
|
217
|
-
doLinear: boolean;
|
|
218
|
-
doFetch: boolean;
|
|
219
|
-
};
|
|
220
|
-
export declare function renderTicketDoctorResult(result: TicketDoctorResult): string[];
|
|
221
|
-
export declare function runTicketDoctor(parsed: TicketDoctorArguments): Promise<boolean>;
|
|
222
|
-
export {};
|
|
223
|
-
//# sourceMappingURL=ticketDoctor.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ticketDoctor.d.ts","sourceRoot":"","sources":["../../src/commands/ticketDoctor.ts"],"names":[],"mappings":"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"}
|