@dadado/agent-kit-cli 6.1.0 → 6.2.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.
- package/dashboard/README.md +3 -1
- package/dashboard/dashboard-data.mjs +13 -2
- package/dashboard/dashboard.html +95 -2
- package/dashboard/lib/gate-exit-tickets.d.mts +45 -0
- package/dashboard/lib/gate-exit-tickets.mjs +233 -0
- package/dashboard/lib/semantic-model.d.mts +21 -0
- package/dashboard/lib/semantic-model.mjs +47 -0
- package/dist/{add-YTCDLPUS.js → add-Y2426TGU.js} +3 -3
- package/dist/{chunk-PCCQUWE5.js → chunk-3LLXDHIU.js} +1 -1
- package/dist/{chunk-YP4OOK4T.js → chunk-BEKQ6PVD.js} +2 -2
- package/dist/{chunk-3DGTPONS.js → chunk-C2SJDYAM.js} +1 -1
- package/dist/{chunk-C26I6HTO.js → chunk-C4Q77GGJ.js} +0 -1
- package/dist/{chunk-DRND2KYV.js → chunk-CER2APV2.js} +1 -1
- package/dist/{chunk-BBVBYQJO.js → chunk-CWDXNBEU.js} +2 -2
- package/dist/{chunk-U5F6RJN4.js → chunk-GO3K752H.js} +4 -1
- package/dist/chunk-GUQYNUV4.js +61 -0
- package/dist/{chunk-TMFOLRU2.js → chunk-IR7FFPUU.js} +8 -8
- package/dist/{chunk-ESNAFDYT.js → chunk-JEI6HACW.js} +44 -1
- package/dist/chunk-KVY425NM.js +519 -0
- package/dist/{chunk-WUWRGOUV.js → chunk-L5V3W3DY.js} +13 -1
- package/dist/chunk-MO63KZBP.js +516 -0
- package/dist/chunk-MUTTNRX4.js +53 -0
- package/dist/{chunk-DBPNGZNH.js → chunk-NSSXSZLL.js} +13 -2
- package/dist/chunk-QTBTKEXK.js +77 -0
- package/dist/{chunk-PPKX55GI.js → chunk-SPYIP76F.js} +1 -1
- package/dist/{chunk-DBXDV5O7.js → chunk-TGNFGMPV.js} +2 -2
- package/dist/{chunk-2FQX2O4I.js → chunk-TW4BF5OE.js} +2 -2
- package/dist/{chunk-GN4SAZF2.js → chunk-VO73OL5V.js} +2 -2
- package/dist/{chunk-VTOUQAVR.js → chunk-X45O2AIE.js} +9 -1
- package/dist/{chunk-HFUH3HVS.js → chunk-XDCCYBCJ.js} +7 -1
- package/dist/{chunk-TPCCSWK6.js → chunk-YRFSTHR5.js} +30 -526
- package/dist/{chunk-3XKVQS2K.js → chunk-Z7ABX5QI.js} +13 -9
- package/dist/{contribute-A7NCWTUM.js → contribute-TVST3CJO.js} +4 -4
- package/dist/countdown-QXJD6TDB.js +479 -0
- package/dist/{dashboard-YSNUGBFY.js → dashboard-YNCFISNO.js} +1 -1
- package/dist/{dashboard-broadcast-M4CMW7RX.js → dashboard-broadcast-NK7PU72L.js} +3 -2
- package/dist/{diff-4MDU5SLE.js → diff-MECE5RZB.js} +5 -5
- package/dist/{doctor-SS6Y2T6H.js → doctor-VLZNXJNA.js} +9 -9
- package/dist/ground-control-NMYYIVCV.js +434 -0
- package/dist/{handoff-MK5JG3J5.js → handoff-5AGE2D3T.js} +3 -2
- package/dist/{hook-D2WHBKRN.js → hook-XCZWX462.js} +7 -6
- package/dist/index.js +33 -23
- package/dist/{init-GVVBA2BM.js → init-HKMRU2V4.js} +12 -12
- package/dist/{install-R4HPI7VK.js → install-X2J6KWZ5.js} +12 -12
- package/dist/{mission-control-LJACEVVN.js → mission-control-MHQU73XC.js} +2 -2
- package/dist/{plan-index-V7T5MKL6.js → plan-index-BNLUU6T5.js} +3 -2
- package/dist/{run-YV6XTFZY.js → run-R66G276Q.js} +63 -15
- package/dist/{run-plan-KT443FO6.js → run-plan-24Z5K4P3.js} +17 -10
- package/dist/{scan-K6TQGV4S.js → scan-UX4HARMJ.js} +1 -1
- package/dist/{setup-global-AT4DD3MG.js → setup-global-ADJFMOZX.js} +6 -6
- package/dist/{status-MPJHI5RP.js → status-UB6NL3Q3.js} +8 -8
- package/dist/{update-P62637ZI.js → update-PFBFY7GT.js} +9 -9
- package/package.json +1 -1
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
import {
|
|
2
|
+
blobId,
|
|
3
|
+
isTicketMerged
|
|
4
|
+
} from "./chunk-QTBTKEXK.js";
|
|
5
|
+
import {
|
|
6
|
+
GATE_EXIT_BRANCH_PREFIX,
|
|
7
|
+
GATE_EXIT_MARKER_RELPATH,
|
|
8
|
+
defaultExec,
|
|
9
|
+
findAuthenticatedForge,
|
|
10
|
+
gateExitBranch,
|
|
11
|
+
gateExitNotePath,
|
|
12
|
+
gateExitRedactions,
|
|
13
|
+
isGateExitStamp,
|
|
14
|
+
isSafeBaseRef,
|
|
15
|
+
listGateExitBranches,
|
|
16
|
+
readGateExitMarker,
|
|
17
|
+
resolveGateExitRefs,
|
|
18
|
+
writeGateExitMarker
|
|
19
|
+
} from "./chunk-KVY425NM.js";
|
|
20
|
+
import "./chunk-MUTTNRX4.js";
|
|
21
|
+
import {
|
|
22
|
+
redactSecrets
|
|
23
|
+
} from "./chunk-JEI6HACW.js";
|
|
24
|
+
import {
|
|
25
|
+
findOnPath
|
|
26
|
+
} from "./chunk-WGLPZXNU.js";
|
|
27
|
+
import "./chunk-MAPOQEA2.js";
|
|
28
|
+
import "./chunk-QTON2GQX.js";
|
|
29
|
+
import {
|
|
30
|
+
logger
|
|
31
|
+
} from "./chunk-ZB43YMHW.js";
|
|
32
|
+
|
|
33
|
+
// src/commands/ground-control.ts
|
|
34
|
+
import path from "path";
|
|
35
|
+
import { defineCommand } from "citty";
|
|
36
|
+
var GROUND_CONTROL_EXIT = {
|
|
37
|
+
ok: 0,
|
|
38
|
+
usage: 1,
|
|
39
|
+
/** `accept` on a branch that is not merged into the base yet. */
|
|
40
|
+
waiting: 2,
|
|
41
|
+
/** A git or forge step failed; the ticket is kept. */
|
|
42
|
+
failed: 3
|
|
43
|
+
};
|
|
44
|
+
async function openContext(cwd, env, exec) {
|
|
45
|
+
const root = path.resolve(cwd);
|
|
46
|
+
const git = (args) => exec("git", args, { cwd: root, env });
|
|
47
|
+
const top = await git(["rev-parse", "--show-toplevel"]);
|
|
48
|
+
if (top.code !== 0) return "not a git repository";
|
|
49
|
+
const origin = await git(["remote", "get-url", "origin"]);
|
|
50
|
+
const originUrl = origin.code === 0 ? origin.stdout.trim() : "";
|
|
51
|
+
return { root, env, exec, git, hasOrigin: originUrl.length > 0, originUrl };
|
|
52
|
+
}
|
|
53
|
+
async function fetchOrigin(ctx) {
|
|
54
|
+
if (!ctx.hasOrigin) return null;
|
|
55
|
+
const fetched = await ctx.git(["fetch", "--prune", "--quiet", "origin"]);
|
|
56
|
+
return fetched.code === 0 ? null : `git fetch --prune origin failed (${fetched.stderr.trim().split("\n")[0] ?? ""})`;
|
|
57
|
+
}
|
|
58
|
+
function stampOfBranch(short) {
|
|
59
|
+
const i = short.lastIndexOf(GATE_EXIT_BRANCH_PREFIX);
|
|
60
|
+
if (i < 0) return null;
|
|
61
|
+
const stamp = short.slice(i + GATE_EXIT_BRANCH_PREFIX.length);
|
|
62
|
+
return isGateExitStamp(stamp) ? stamp : null;
|
|
63
|
+
}
|
|
64
|
+
async function refExists(git, ref) {
|
|
65
|
+
return (await git(["rev-parse", "--verify", "--quiet", `${ref}^{commit}`])).code === 0;
|
|
66
|
+
}
|
|
67
|
+
async function readHeadline(git, ref, stamp) {
|
|
68
|
+
const shown = await git(["show", `${ref}:${gateExitNotePath(stamp)}`]);
|
|
69
|
+
if (shown.code !== 0) return null;
|
|
70
|
+
const first = shown.stdout.split("\n")[0]?.trim() ?? "";
|
|
71
|
+
return first || null;
|
|
72
|
+
}
|
|
73
|
+
async function locateBranch(ctx, stamp) {
|
|
74
|
+
const branch = gateExitBranch(stamp);
|
|
75
|
+
const remote = ctx.hasOrigin ? `refs/remotes/origin/${branch}` : null;
|
|
76
|
+
const local = `refs/heads/${branch}`;
|
|
77
|
+
return {
|
|
78
|
+
remote: remote && await refExists(ctx.git, remote) ? remote : null,
|
|
79
|
+
local: await refExists(ctx.git, local) ? local : null
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
async function baseRefsFor(ctx, entry) {
|
|
83
|
+
const requested = entry?.base && isSafeBaseRef(entry.base) ? entry.base : void 0;
|
|
84
|
+
return resolveGateExitRefs(ctx.git, ctx.hasOrigin, requested);
|
|
85
|
+
}
|
|
86
|
+
function shortRef(ref) {
|
|
87
|
+
return ref.replace(/^refs\/remotes\//, "").replace(/^refs\/heads\//, "");
|
|
88
|
+
}
|
|
89
|
+
async function groundControlStatus(input) {
|
|
90
|
+
const env = input.env ?? process.env;
|
|
91
|
+
const ctx = await openContext(input.cwd, env, input.exec ?? defaultExec);
|
|
92
|
+
if (typeof ctx === "string") return ctx;
|
|
93
|
+
const warnings = [];
|
|
94
|
+
const fetchError = await fetchOrigin(ctx);
|
|
95
|
+
if (fetchError) warnings.push(`${fetchError}; showing the last fetched state`);
|
|
96
|
+
const marker = await readGateExitMarker(ctx.root);
|
|
97
|
+
const entries = marker.kind === "ok" ? marker.marker.pending : [];
|
|
98
|
+
const refs = await resolveGateExitRefs(ctx.git, ctx.hasOrigin);
|
|
99
|
+
const listed = await listGateExitBranches(ctx.git, refs);
|
|
100
|
+
const local = ctx.hasOrigin ? await listGateExitBranches(ctx.git, {
|
|
101
|
+
...refs,
|
|
102
|
+
scope: `refs/heads/${GATE_EXIT_BRANCH_PREFIX}`
|
|
103
|
+
}) : { ok: true, branches: [] };
|
|
104
|
+
const stamps = new Set(entries.map((e) => e.stamp));
|
|
105
|
+
for (const short of [...listed.branches, ...local.branches]) {
|
|
106
|
+
const stamp = stampOfBranch(short);
|
|
107
|
+
if (stamp) stamps.add(stamp);
|
|
108
|
+
}
|
|
109
|
+
const tickets = [];
|
|
110
|
+
for (const stamp of [...stamps].sort()) {
|
|
111
|
+
const entry = entries.find((e) => e.stamp === stamp);
|
|
112
|
+
const where = await locateBranch(ctx, stamp);
|
|
113
|
+
const branchRef = where.remote ?? where.local;
|
|
114
|
+
const ticketRefs = await baseRefsFor(ctx, entry);
|
|
115
|
+
let branchState = "none";
|
|
116
|
+
if (branchRef) {
|
|
117
|
+
branchState = await isTicketMerged(ctx.git, branchRef, ticketRefs.baseRef, stamp) ? "merged" : "unmerged";
|
|
118
|
+
}
|
|
119
|
+
if (!entry && branchState === "merged") continue;
|
|
120
|
+
const headline = (branchRef ? await readHeadline(ctx.git, branchRef, stamp) : null) ?? await readHeadline(ctx.git, ticketRefs.baseRef, stamp);
|
|
121
|
+
tickets.push({
|
|
122
|
+
stamp,
|
|
123
|
+
headline,
|
|
124
|
+
askId: entry?.askId ?? null,
|
|
125
|
+
labels: entry?.labels ?? [],
|
|
126
|
+
trigger: entry?.trigger ?? null,
|
|
127
|
+
openedAt: entry?.openedAt ?? null,
|
|
128
|
+
url: entry?.url ?? null,
|
|
129
|
+
branch: branchRef ? shortRef(branchRef) : null,
|
|
130
|
+
branchState,
|
|
131
|
+
inMarker: Boolean(entry)
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
marker: marker.kind,
|
|
136
|
+
...marker.kind === "invalid" ? { markerDetail: marker.detail } : {},
|
|
137
|
+
base: refs.base,
|
|
138
|
+
tickets,
|
|
139
|
+
skipped: marker.kind === "ok" ? marker.marker.skipped : [],
|
|
140
|
+
warnings
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
function formatGroundControlStatus(status) {
|
|
144
|
+
const lines = [];
|
|
145
|
+
const n = status.tickets.length;
|
|
146
|
+
lines.push(
|
|
147
|
+
n === 0 ? "Ground Control: no pending operator ticket." : `Ground Control: ${n} pending operator ticket${n === 1 ? "" : "s"} (base ${status.base}).`
|
|
148
|
+
);
|
|
149
|
+
for (const t of status.tickets) {
|
|
150
|
+
lines.push("");
|
|
151
|
+
lines.push(`- ${t.stamp}: ${t.headline?.replace(/^#\s*/, "") ?? "(note not readable)"}`);
|
|
152
|
+
if (t.askId) {
|
|
153
|
+
lines.push(
|
|
154
|
+
` Ask id: ${t.askId}${t.labels.length ? ` | labels: ${t.labels.join(" / ")}` : ""}`
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
const branch = t.branchState === "none" ? "no gate-exit branch" : `${t.branch} (${t.branchState === "merged" ? "merged; accept to close the ticket" : "not merged"})`;
|
|
158
|
+
lines.push(` Branch: ${branch}${t.url ? ` | review: ${t.url}` : ""}`);
|
|
159
|
+
if (!t.inMarker)
|
|
160
|
+
lines.push(
|
|
161
|
+
` Not in ${GATE_EXIT_MARKER_RELPATH} (Countdown refuses until it is merged or discarded)`
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
lines.push("");
|
|
165
|
+
if (status.marker === "invalid") {
|
|
166
|
+
lines.push(
|
|
167
|
+
`Marker: ${GATE_EXIT_MARKER_RELPATH} is unreadable (${status.markerDetail ?? "?"}).`
|
|
168
|
+
);
|
|
169
|
+
} else if (status.marker === "absent") {
|
|
170
|
+
lines.push(`Marker: ${GATE_EXIT_MARKER_RELPATH} absent.`);
|
|
171
|
+
} else {
|
|
172
|
+
const pending = status.tickets.filter((t) => t.inMarker).length;
|
|
173
|
+
lines.push(
|
|
174
|
+
`Marker: ${GATE_EXIT_MARKER_RELPATH}, ${pending} pending entr${pending === 1 ? "y" : "ies"}.`
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
if (status.skipped.length > 0) {
|
|
178
|
+
lines.push(`Skipped runs: ${status.skipped.length} (latest: ${status.skipped.at(-1)}).`);
|
|
179
|
+
}
|
|
180
|
+
for (const w of status.warnings) lines.push(`Warning: ${w}`);
|
|
181
|
+
if (n > 0) {
|
|
182
|
+
lines.push(
|
|
183
|
+
"Next: read the note, then `agent-kit ground-control accept <stamp>` once merged, or `discard <stamp>`."
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
return `${lines.join("\n")}
|
|
187
|
+
`;
|
|
188
|
+
}
|
|
189
|
+
async function clearEntry(root, stamp) {
|
|
190
|
+
const marker = await readGateExitMarker(root);
|
|
191
|
+
if (marker.kind === "absent") return null;
|
|
192
|
+
if (marker.kind === "invalid") {
|
|
193
|
+
return `${GATE_EXIT_MARKER_RELPATH} is unreadable (${marker.detail}); left as is`;
|
|
194
|
+
}
|
|
195
|
+
const pending = marker.marker.pending.filter((e) => e.stamp !== stamp);
|
|
196
|
+
if (pending.length === marker.marker.pending.length) return null;
|
|
197
|
+
const next = { ...marker.marker, pending };
|
|
198
|
+
try {
|
|
199
|
+
await writeGateExitMarker(root, next);
|
|
200
|
+
return null;
|
|
201
|
+
} catch (err) {
|
|
202
|
+
return `could not write ${GATE_EXIT_MARKER_RELPATH}: ${String(err)}`;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
async function prepareTriage(input) {
|
|
206
|
+
if (!isGateExitStamp(input.stamp)) {
|
|
207
|
+
return {
|
|
208
|
+
ok: false,
|
|
209
|
+
result: {
|
|
210
|
+
exitCode: GROUND_CONTROL_EXIT.usage,
|
|
211
|
+
error: `invalid stamp: expected YYYYMMDDTHHMMSSZ (as \`agent-kit ground-control status\` prints it)`
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
const env = input.env ?? process.env;
|
|
216
|
+
const redactions = gateExitRedactions(env);
|
|
217
|
+
const log = (line) => input.log?.(redactSecrets(line, redactions));
|
|
218
|
+
const ctx = await openContext(input.cwd, env, input.exec ?? defaultExec);
|
|
219
|
+
if (typeof ctx === "string") {
|
|
220
|
+
return { ok: false, result: { exitCode: GROUND_CONTROL_EXIT.usage, error: ctx } };
|
|
221
|
+
}
|
|
222
|
+
const marker = await readGateExitMarker(ctx.root);
|
|
223
|
+
if (marker.kind === "invalid") {
|
|
224
|
+
return {
|
|
225
|
+
ok: false,
|
|
226
|
+
result: {
|
|
227
|
+
exitCode: GROUND_CONTROL_EXIT.failed,
|
|
228
|
+
error: `${GATE_EXIT_MARKER_RELPATH} is unreadable (${marker.detail}); fix or remove it by hand`
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
const fetchError = await fetchOrigin(ctx);
|
|
233
|
+
if (fetchError) {
|
|
234
|
+
return {
|
|
235
|
+
ok: false,
|
|
236
|
+
result: { exitCode: GROUND_CONTROL_EXIT.failed, error: `${fetchError}; nothing changed` }
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
const entry = marker.kind === "ok" ? marker.marker.pending.find((e) => e.stamp === input.stamp) : void 0;
|
|
240
|
+
return { ok: true, ctx, entry, log };
|
|
241
|
+
}
|
|
242
|
+
async function deleteBranch(ctx, stamp, where, log) {
|
|
243
|
+
const branch = gateExitBranch(stamp);
|
|
244
|
+
let ok = true;
|
|
245
|
+
if (where.remote) {
|
|
246
|
+
const pushed = await ctx.git(["push", "--quiet", "origin", "--delete", `refs/heads/${branch}`]);
|
|
247
|
+
if (pushed.code === 0) log(`deleted origin/${branch}`);
|
|
248
|
+
else {
|
|
249
|
+
ok = false;
|
|
250
|
+
log(`could not delete origin/${branch}: ${pushed.stderr.trim().split("\n")[0] ?? ""}`);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
if (where.local) {
|
|
254
|
+
const removed = await ctx.git(["branch", "-D", "--", branch]);
|
|
255
|
+
if (removed.code === 0) log(`deleted local ${branch}`);
|
|
256
|
+
else {
|
|
257
|
+
ok = false;
|
|
258
|
+
log(`could not delete local ${branch}: ${removed.stderr.trim().split("\n")[0] ?? ""}`);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return ok;
|
|
262
|
+
}
|
|
263
|
+
async function acceptTicket(input) {
|
|
264
|
+
const prep = await prepareTriage(input);
|
|
265
|
+
if (!prep.ok) return prep.result;
|
|
266
|
+
const { ctx, entry, log } = prep;
|
|
267
|
+
const stamp = input.stamp;
|
|
268
|
+
const refs = await baseRefsFor(ctx, entry);
|
|
269
|
+
const where = await locateBranch(ctx, stamp);
|
|
270
|
+
const branchRef = where.remote ?? where.local;
|
|
271
|
+
if (branchRef) {
|
|
272
|
+
if (!await isTicketMerged(ctx.git, branchRef, refs.baseRef, stamp)) {
|
|
273
|
+
log(`${shortRef(branchRef)} is not merged into ${refs.base} yet; waiting on the merge`);
|
|
274
|
+
return { exitCode: GROUND_CONTROL_EXIT.waiting };
|
|
275
|
+
}
|
|
276
|
+
if (!await deleteBranch(ctx, stamp, where, log)) {
|
|
277
|
+
return { exitCode: GROUND_CONTROL_EXIT.failed, error: "branch not deleted; ticket kept" };
|
|
278
|
+
}
|
|
279
|
+
} else {
|
|
280
|
+
const noteOnBase = await blobId(ctx.git, `${refs.baseRef}:${gateExitNotePath(stamp)}`);
|
|
281
|
+
if (!entry) {
|
|
282
|
+
return {
|
|
283
|
+
exitCode: GROUND_CONTROL_EXIT.usage,
|
|
284
|
+
error: `no ticket ${stamp}: not in ${GATE_EXIT_MARKER_RELPATH} and no gate-exit branch`
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
if (!noteOnBase && entry.branch) {
|
|
288
|
+
log(
|
|
289
|
+
`${entry.branch} is gone and its note is not on ${refs.base}; use \`agent-kit ground-control discard ${stamp}\``
|
|
290
|
+
);
|
|
291
|
+
return { exitCode: GROUND_CONTROL_EXIT.waiting };
|
|
292
|
+
}
|
|
293
|
+
log(
|
|
294
|
+
noteOnBase ? `the note of ${stamp} is on ${refs.base} (branch already deleted)` : `ticket ${stamp} never landed a branch; nothing to merge`
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
const markerError = await clearEntry(ctx.root, stamp);
|
|
298
|
+
if (markerError) return { exitCode: GROUND_CONTROL_EXIT.failed, error: markerError };
|
|
299
|
+
log(`accepted ${stamp}; ticket cleared`);
|
|
300
|
+
return { exitCode: GROUND_CONTROL_EXIT.ok };
|
|
301
|
+
}
|
|
302
|
+
async function discardTicket(input) {
|
|
303
|
+
const prep = await prepareTriage(input);
|
|
304
|
+
if (!prep.ok) return prep.result;
|
|
305
|
+
const { ctx, entry, log } = prep;
|
|
306
|
+
const stamp = input.stamp;
|
|
307
|
+
const branch = gateExitBranch(stamp);
|
|
308
|
+
const where = await locateBranch(ctx, stamp);
|
|
309
|
+
if (!entry && !where.remote && !where.local) {
|
|
310
|
+
return {
|
|
311
|
+
exitCode: GROUND_CONTROL_EXIT.usage,
|
|
312
|
+
error: `no ticket ${stamp}: not in ${GATE_EXIT_MARKER_RELPATH} and no gate-exit branch`
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
if (where.remote) {
|
|
316
|
+
const which = input.which ?? ((bin) => findOnPath(bin, { env: ctx.env }));
|
|
317
|
+
const forge = await findAuthenticatedForge({
|
|
318
|
+
originUrl: ctx.originUrl,
|
|
319
|
+
cwd: ctx.root,
|
|
320
|
+
exec: ctx.exec,
|
|
321
|
+
which,
|
|
322
|
+
env: ctx.env,
|
|
323
|
+
log
|
|
324
|
+
});
|
|
325
|
+
if (forge) {
|
|
326
|
+
const closed = forge.forge === "gh" ? await ctx.exec(
|
|
327
|
+
forge.bin,
|
|
328
|
+
["pr", "close", branch, "--comment", "Discarded with agent-kit ground-control."],
|
|
329
|
+
{ cwd: ctx.root, env: ctx.env }
|
|
330
|
+
) : await ctx.exec(forge.bin, ["mr", "close", branch], { cwd: ctx.root, env: ctx.env });
|
|
331
|
+
log(
|
|
332
|
+
closed.code === 0 ? `${forge.forge === "gh" ? "PR" : "MR"} for ${branch} closed` : `${forge.forge} could not close the review for ${branch} (${closed.stderr.trim().split("\n")[0] ?? ""}); deleting the branch closes it on most forges`
|
|
333
|
+
);
|
|
334
|
+
} else {
|
|
335
|
+
log("no authenticated gh/glab; the review closes when its branch is deleted");
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
if (!await deleteBranch(ctx, stamp, where, log)) {
|
|
339
|
+
return { exitCode: GROUND_CONTROL_EXIT.failed, error: "branch not deleted; ticket kept" };
|
|
340
|
+
}
|
|
341
|
+
const markerError = await clearEntry(ctx.root, stamp);
|
|
342
|
+
if (markerError) return { exitCode: GROUND_CONTROL_EXIT.failed, error: markerError };
|
|
343
|
+
log(`discarded ${stamp}; ticket cleared`);
|
|
344
|
+
return { exitCode: GROUND_CONTROL_EXIT.ok };
|
|
345
|
+
}
|
|
346
|
+
var cwdArg = {
|
|
347
|
+
type: "string",
|
|
348
|
+
description: "Project root (default: current directory)",
|
|
349
|
+
default: process.cwd()
|
|
350
|
+
};
|
|
351
|
+
var stampArg = {
|
|
352
|
+
type: "positional",
|
|
353
|
+
description: "Gate-exit stamp (YYYYMMDDTHHMMSSZ, as `status` prints it)",
|
|
354
|
+
required: true
|
|
355
|
+
};
|
|
356
|
+
function groundControlErrorText(error, env = process.env) {
|
|
357
|
+
return redactSecrets(error, gateExitRedactions(env));
|
|
358
|
+
}
|
|
359
|
+
function report(result) {
|
|
360
|
+
if (result.error) logger.error(groundControlErrorText(result.error));
|
|
361
|
+
process.exitCode = result.exitCode;
|
|
362
|
+
}
|
|
363
|
+
var groundControlCommand = defineCommand({
|
|
364
|
+
meta: {
|
|
365
|
+
name: "ground-control",
|
|
366
|
+
description: "Ground Control: triage gate exits. status lists pending operator tickets; accept <stamp> clears a merged one; discard <stamp> closes and deletes it. Never merges, never git-prod."
|
|
367
|
+
},
|
|
368
|
+
subCommands: {
|
|
369
|
+
status: defineCommand({
|
|
370
|
+
meta: {
|
|
371
|
+
name: "status",
|
|
372
|
+
description: "List pending operator tickets, gate-exit branches and skipped runs"
|
|
373
|
+
},
|
|
374
|
+
args: {
|
|
375
|
+
cwd: cwdArg,
|
|
376
|
+
json: { type: "boolean", description: "Print JSON", default: false }
|
|
377
|
+
},
|
|
378
|
+
async run({ args }) {
|
|
379
|
+
const status = await groundControlStatus({ cwd: String(args.cwd) });
|
|
380
|
+
if (typeof status === "string") {
|
|
381
|
+
logger.error(groundControlErrorText(status));
|
|
382
|
+
process.exitCode = GROUND_CONTROL_EXIT.usage;
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
const env = process.env;
|
|
386
|
+
const text = args.json ? `${JSON.stringify(status, null, 2)}
|
|
387
|
+
` : formatGroundControlStatus(status);
|
|
388
|
+
process.stdout.write(redactSecrets(text, gateExitRedactions(env)));
|
|
389
|
+
}
|
|
390
|
+
}),
|
|
391
|
+
accept: defineCommand({
|
|
392
|
+
meta: {
|
|
393
|
+
name: "accept",
|
|
394
|
+
description: "Clear a ticket whose gate-exit branch is merged into the base, deleting the branch (exit 2 while unmerged)"
|
|
395
|
+
},
|
|
396
|
+
args: { stamp: stampArg, cwd: cwdArg },
|
|
397
|
+
async run({ args }) {
|
|
398
|
+
report(
|
|
399
|
+
await acceptTicket({
|
|
400
|
+
cwd: String(args.cwd),
|
|
401
|
+
stamp: String(args.stamp),
|
|
402
|
+
log: (line) => logger.info(`ground-control: ${line}`)
|
|
403
|
+
})
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
}),
|
|
407
|
+
discard: defineCommand({
|
|
408
|
+
meta: {
|
|
409
|
+
name: "discard",
|
|
410
|
+
description: "Close the PR/MR (gh/glab), delete the gate-exit branch and clear the ticket"
|
|
411
|
+
},
|
|
412
|
+
args: { stamp: stampArg, cwd: cwdArg },
|
|
413
|
+
async run({ args }) {
|
|
414
|
+
report(
|
|
415
|
+
await discardTicket({
|
|
416
|
+
cwd: String(args.cwd),
|
|
417
|
+
stamp: String(args.stamp),
|
|
418
|
+
log: (line) => logger.info(`ground-control: ${line}`)
|
|
419
|
+
})
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
})
|
|
423
|
+
}
|
|
424
|
+
});
|
|
425
|
+
export {
|
|
426
|
+
GROUND_CONTROL_EXIT,
|
|
427
|
+
acceptTicket,
|
|
428
|
+
discardTicket,
|
|
429
|
+
formatGroundControlStatus,
|
|
430
|
+
groundControlCommand,
|
|
431
|
+
groundControlErrorText,
|
|
432
|
+
groundControlStatus,
|
|
433
|
+
isTicketMerged
|
|
434
|
+
};
|
|
@@ -6,7 +6,8 @@ import {
|
|
|
6
6
|
extractHandoffNamedPlans,
|
|
7
7
|
namedPlanCandidatePaths,
|
|
8
8
|
parsePlanFrontmatter
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-L5V3W3DY.js";
|
|
10
|
+
import "./chunk-MUTTNRX4.js";
|
|
10
11
|
import {
|
|
11
12
|
PM_TOOL_LABELS
|
|
12
13
|
} from "./chunk-F6C3GFKV.js";
|
|
@@ -15,7 +16,7 @@ import {
|
|
|
15
16
|
} from "./chunk-ZB43YMHW.js";
|
|
16
17
|
import {
|
|
17
18
|
HANDOFF_REL
|
|
18
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-C4Q77GGJ.js";
|
|
19
20
|
import {
|
|
20
21
|
ensureDir,
|
|
21
22
|
fileExists,
|
|
@@ -16,25 +16,26 @@ import {
|
|
|
16
16
|
import {
|
|
17
17
|
formatPlanIndexSection,
|
|
18
18
|
writePlanIndex
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-L5V3W3DY.js";
|
|
20
|
+
import "./chunk-MUTTNRX4.js";
|
|
20
21
|
import {
|
|
21
22
|
READINESS_SNAPSHOT_RELATIVE_PATH
|
|
22
23
|
} from "./chunk-HAFRAXGV.js";
|
|
23
24
|
import {
|
|
24
25
|
stampLastCheckedAt
|
|
25
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-TW4BF5OE.js";
|
|
26
27
|
import {
|
|
27
28
|
loadContextConfig
|
|
28
29
|
} from "./chunk-PFEUZXVT.js";
|
|
29
|
-
import "./chunk-
|
|
30
|
-
import "./chunk-
|
|
30
|
+
import "./chunk-CWDXNBEU.js";
|
|
31
|
+
import "./chunk-X45O2AIE.js";
|
|
31
32
|
import {
|
|
32
33
|
MANIFEST_RELATIVE_PATH
|
|
33
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-NSSXSZLL.js";
|
|
34
35
|
import "./chunk-7HDQEK6T.js";
|
|
35
36
|
import {
|
|
36
37
|
HANDOFF_REL
|
|
37
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-C4Q77GGJ.js";
|
|
38
39
|
import {
|
|
39
40
|
fileExists
|
|
40
41
|
} from "./chunk-5B4DVO6C.js";
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
rewriteRootArgvToRun
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-Z7ABX5QI.js";
|
|
5
|
+
import "./chunk-JEI6HACW.js";
|
|
6
6
|
import "./chunk-WGLPZXNU.js";
|
|
7
7
|
import "./chunk-MAPOQEA2.js";
|
|
8
8
|
import {
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
import {
|
|
17
17
|
KIT_VERSION
|
|
18
18
|
} from "./chunk-7HDQEK6T.js";
|
|
19
|
-
import "./chunk-
|
|
19
|
+
import "./chunk-C4Q77GGJ.js";
|
|
20
20
|
import "./chunk-5B4DVO6C.js";
|
|
21
21
|
|
|
22
22
|
// src/index.ts
|
|
@@ -118,7 +118,15 @@ var CLI_HELP_GROUPS = [
|
|
|
118
118
|
{
|
|
119
119
|
id: "mission",
|
|
120
120
|
title: "MISSION",
|
|
121
|
-
commands: [
|
|
121
|
+
commands: [
|
|
122
|
+
"handoff",
|
|
123
|
+
"plan-index",
|
|
124
|
+
"run",
|
|
125
|
+
"run-plan",
|
|
126
|
+
"run-plan-all",
|
|
127
|
+
"countdown",
|
|
128
|
+
"ground-control"
|
|
129
|
+
]
|
|
122
130
|
},
|
|
123
131
|
{
|
|
124
132
|
id: "dashboard",
|
|
@@ -213,29 +221,31 @@ var main = defineCommand({
|
|
|
213
221
|
version: KIT_VERSION
|
|
214
222
|
},
|
|
215
223
|
subCommands: {
|
|
216
|
-
init: () => import("./init-
|
|
217
|
-
install: () => import("./install-
|
|
218
|
-
scan: () => import("./scan-
|
|
219
|
-
add: () => import("./add-
|
|
220
|
-
doctor: () => import("./doctor-
|
|
221
|
-
"setup-global": () => import("./setup-global-
|
|
222
|
-
status: () => import("./status-
|
|
223
|
-
update: () => import("./update-
|
|
224
|
+
init: () => import("./init-HKMRU2V4.js").then((m) => m.initCommand),
|
|
225
|
+
install: () => import("./install-X2J6KWZ5.js").then((m) => m.installCommand),
|
|
226
|
+
scan: () => import("./scan-UX4HARMJ.js").then((m) => m.scanCommand),
|
|
227
|
+
add: () => import("./add-Y2426TGU.js").then((m) => m.addCommand),
|
|
228
|
+
doctor: () => import("./doctor-VLZNXJNA.js").then((m) => m.doctorCommand),
|
|
229
|
+
"setup-global": () => import("./setup-global-ADJFMOZX.js").then((m) => m.setupGlobalCommand),
|
|
230
|
+
status: () => import("./status-UB6NL3Q3.js").then((m) => m.statusCommand),
|
|
231
|
+
update: () => import("./update-PFBFY7GT.js").then((m) => m.updateCommand),
|
|
224
232
|
"cursor-awareness": () => import("./cursor-awareness-TN5JXD2C.js").then((m) => m.cursorAwarenessCommand),
|
|
225
233
|
"public-inbound-radar": () => import("./public-inbound-radar-5U4JMBRU.js").then((m) => m.publicInboundRadarCommand),
|
|
226
234
|
"remote-issues": () => import("./remote-issues-APYOMIJC.js").then((m) => m.remoteIssuesCommand),
|
|
227
235
|
dogfood: () => import("./dogfood-2JAHSYQA.js").then((m) => m.dogfoodCommand),
|
|
228
|
-
diff: () => import("./diff-
|
|
229
|
-
contribute: () => import("./contribute-
|
|
230
|
-
handoff: () => import("./handoff-
|
|
231
|
-
"plan-index": () => import("./plan-index-
|
|
232
|
-
run: () => import("./run-
|
|
233
|
-
"run-plan": () => import("./run-plan-
|
|
234
|
-
"run-plan-all": () => import("./run-
|
|
235
|
-
|
|
236
|
-
"
|
|
237
|
-
|
|
238
|
-
|
|
236
|
+
diff: () => import("./diff-MECE5RZB.js").then((m) => m.diffCommand),
|
|
237
|
+
contribute: () => import("./contribute-TVST3CJO.js").then((m) => m.contributeCommand),
|
|
238
|
+
handoff: () => import("./handoff-5AGE2D3T.js").then((m) => m.handoffCommand),
|
|
239
|
+
"plan-index": () => import("./plan-index-BNLUU6T5.js").then((m) => m.planIndexCommand),
|
|
240
|
+
run: () => import("./run-R66G276Q.js").then((m) => m.runCommand),
|
|
241
|
+
"run-plan": () => import("./run-plan-24Z5K4P3.js").then((m) => m.runPlanCommand),
|
|
242
|
+
"run-plan-all": () => import("./run-R66G276Q.js").then((m) => m.runPlanAllCommand),
|
|
243
|
+
countdown: () => import("./countdown-QXJD6TDB.js").then((m) => m.countdownCommand),
|
|
244
|
+
"ground-control": () => import("./ground-control-NMYYIVCV.js").then((m) => m.groundControlCommand),
|
|
245
|
+
dashboard: () => import("./dashboard-YNCFISNO.js").then((m) => m.dashboardCommand),
|
|
246
|
+
"dashboard-broadcast": () => import("./dashboard-broadcast-NK7PU72L.js").then((m) => m.dashboardBroadcastCommand),
|
|
247
|
+
"mission-control": () => import("./mission-control-MHQU73XC.js").then((m) => m.missionControlCommand),
|
|
248
|
+
hook: () => import("./hook-XCZWX462.js").then((m) => m.hookCommand),
|
|
239
249
|
guard: () => import("./guard-EHXF76ID.js").then((m) => m.guardCommand),
|
|
240
250
|
monitors: () => import("./monitors-PDXBLB3U.js").then((m) => m.monitorsCommand),
|
|
241
251
|
validate: () => import("./validate-V2CW7J4B.js").then((m) => m.validateCommand)
|
|
@@ -2,25 +2,25 @@ import {
|
|
|
2
2
|
nextStepAfterInstall,
|
|
3
3
|
performInstall,
|
|
4
4
|
printInstallEpilogue
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-IR7FFPUU.js";
|
|
6
6
|
import {
|
|
7
7
|
NON_INTERACTIVE_ROOT_ARGS
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-TGNFGMPV.js";
|
|
9
9
|
import {
|
|
10
10
|
SkippedSymlinkError,
|
|
11
11
|
logApplyStats
|
|
12
12
|
} from "./chunk-HS7LVVLO.js";
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-C2SJDYAM.js";
|
|
14
|
+
import "./chunk-BEKQ6PVD.js";
|
|
15
15
|
import "./chunk-HAFRAXGV.js";
|
|
16
|
-
import "./chunk-
|
|
16
|
+
import "./chunk-SPYIP76F.js";
|
|
17
17
|
import "./chunk-WGLPZXNU.js";
|
|
18
18
|
import "./chunk-MAPOQEA2.js";
|
|
19
19
|
import {
|
|
20
20
|
withCliProgress
|
|
21
21
|
} from "./chunk-QTON2GQX.js";
|
|
22
22
|
import "./chunk-PNFF6OU3.js";
|
|
23
|
-
import "./chunk-
|
|
23
|
+
import "./chunk-GO3K752H.js";
|
|
24
24
|
import "./chunk-F6C3GFKV.js";
|
|
25
25
|
import {
|
|
26
26
|
logger
|
|
@@ -31,19 +31,19 @@ import {
|
|
|
31
31
|
confirmProjectRoot,
|
|
32
32
|
isNonInteractive,
|
|
33
33
|
syncPathCliToRuntime
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-VO73OL5V.js";
|
|
35
35
|
import {
|
|
36
36
|
assessEnvironment
|
|
37
37
|
} from "./chunk-B3VR5YBQ.js";
|
|
38
|
-
import "./chunk-
|
|
38
|
+
import "./chunk-TW4BF5OE.js";
|
|
39
39
|
import "./chunk-PFEUZXVT.js";
|
|
40
|
-
import "./chunk-
|
|
41
|
-
import "./chunk-
|
|
42
|
-
import "./chunk-
|
|
40
|
+
import "./chunk-CWDXNBEU.js";
|
|
41
|
+
import "./chunk-X45O2AIE.js";
|
|
42
|
+
import "./chunk-NSSXSZLL.js";
|
|
43
43
|
import {
|
|
44
44
|
KIT_VERSION
|
|
45
45
|
} from "./chunk-7HDQEK6T.js";
|
|
46
|
-
import "./chunk-
|
|
46
|
+
import "./chunk-C4Q77GGJ.js";
|
|
47
47
|
import "./chunk-5B4DVO6C.js";
|
|
48
48
|
|
|
49
49
|
// src/commands/init.ts
|
|
@@ -3,29 +3,29 @@ import {
|
|
|
3
3
|
nextStepAfterInstall,
|
|
4
4
|
performInstall,
|
|
5
5
|
printInstallEpilogue
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-IR7FFPUU.js";
|
|
7
|
+
import "./chunk-TGNFGMPV.js";
|
|
8
8
|
import "./chunk-HS7LVVLO.js";
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-C2SJDYAM.js";
|
|
10
|
+
import "./chunk-BEKQ6PVD.js";
|
|
11
11
|
import "./chunk-HAFRAXGV.js";
|
|
12
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-SPYIP76F.js";
|
|
13
13
|
import "./chunk-WGLPZXNU.js";
|
|
14
14
|
import "./chunk-MAPOQEA2.js";
|
|
15
15
|
import "./chunk-QTON2GQX.js";
|
|
16
16
|
import "./chunk-PNFF6OU3.js";
|
|
17
|
-
import "./chunk-
|
|
17
|
+
import "./chunk-GO3K752H.js";
|
|
18
18
|
import "./chunk-F6C3GFKV.js";
|
|
19
19
|
import "./chunk-ZB43YMHW.js";
|
|
20
|
-
import "./chunk-
|
|
20
|
+
import "./chunk-VO73OL5V.js";
|
|
21
21
|
import "./chunk-B3VR5YBQ.js";
|
|
22
|
-
import "./chunk-
|
|
22
|
+
import "./chunk-TW4BF5OE.js";
|
|
23
23
|
import "./chunk-PFEUZXVT.js";
|
|
24
|
-
import "./chunk-
|
|
25
|
-
import "./chunk-
|
|
26
|
-
import "./chunk-
|
|
24
|
+
import "./chunk-CWDXNBEU.js";
|
|
25
|
+
import "./chunk-X45O2AIE.js";
|
|
26
|
+
import "./chunk-NSSXSZLL.js";
|
|
27
27
|
import "./chunk-7HDQEK6T.js";
|
|
28
|
-
import "./chunk-
|
|
28
|
+
import "./chunk-C4Q77GGJ.js";
|
|
29
29
|
import "./chunk-5B4DVO6C.js";
|
|
30
30
|
export {
|
|
31
31
|
installCommand,
|