@brainervirus/workit-cli 8.19.1 → 8.20.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/dist/index.js +430 -315
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -65,7 +65,7 @@ var package_default;
|
|
|
65
65
|
var init_package = __esm(() => {
|
|
66
66
|
package_default = {
|
|
67
67
|
name: "@brainervirus/workit-cli",
|
|
68
|
-
version: "8.
|
|
68
|
+
version: "8.20.0",
|
|
69
69
|
private: false,
|
|
70
70
|
description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
|
|
71
71
|
keywords: [
|
|
@@ -103,13 +103,13 @@ var init_package = __esm(() => {
|
|
|
103
103
|
},
|
|
104
104
|
dependencies: {
|
|
105
105
|
"@babel/parser": "7.29.9",
|
|
106
|
-
"@brainervirus/workit-cursor": "^8.
|
|
106
|
+
"@brainervirus/workit-cursor": "^8.20.0",
|
|
107
107
|
"@inkjs/ui": "2.0.0",
|
|
108
108
|
ink: "7.1.1",
|
|
109
109
|
react: "19.2.8"
|
|
110
110
|
},
|
|
111
111
|
devDependencies: {
|
|
112
|
-
"@brainervirus/workit-core": "^8.
|
|
112
|
+
"@brainervirus/workit-core": "^8.20.0"
|
|
113
113
|
},
|
|
114
114
|
engines: {
|
|
115
115
|
node: ">=24"
|
|
@@ -117,55 +117,6 @@ var init_package = __esm(() => {
|
|
|
117
117
|
};
|
|
118
118
|
});
|
|
119
119
|
|
|
120
|
-
// packages/workit-cli/src/output.ts
|
|
121
|
-
function emit(io, envelope, human) {
|
|
122
|
-
if (io.json) {
|
|
123
|
-
io.stdout(`${JSON.stringify(envelope)}
|
|
124
|
-
`);
|
|
125
|
-
} else if (envelope.ok) {
|
|
126
|
-
const text = human?.(envelope.data);
|
|
127
|
-
const lines = typeof text === "string" ? [text] : text ?? [];
|
|
128
|
-
for (const value of lines)
|
|
129
|
-
io.stdout(`${value}
|
|
130
|
-
`);
|
|
131
|
-
} else {
|
|
132
|
-
io.stderr(`workit: ${envelope.error ?? envelope.code}
|
|
133
|
-
`);
|
|
134
|
-
if (envelope.unblock)
|
|
135
|
-
io.stderr(` unblock: ${envelope.unblock}
|
|
136
|
-
`);
|
|
137
|
-
}
|
|
138
|
-
return exitCodeFor(envelope.code);
|
|
139
|
-
}
|
|
140
|
-
var EXIT, EXIT_BY_CODE, exitCodeFor = (code) => EXIT_BY_CODE[code], ok = (data) => ({ ok: true, code: "ok", data }), fail = (code, error, extra = {}) => ({
|
|
141
|
-
ok: false,
|
|
142
|
-
code,
|
|
143
|
-
data: extra.data ?? {},
|
|
144
|
-
error,
|
|
145
|
-
...extra.unblock ? { unblock: extra.unblock } : {}
|
|
146
|
-
});
|
|
147
|
-
var init_output = __esm(() => {
|
|
148
|
-
EXIT = {
|
|
149
|
-
ok: 0,
|
|
150
|
-
failed: 1,
|
|
151
|
-
usage: 2,
|
|
152
|
-
blocked: 3,
|
|
153
|
-
busy: 4,
|
|
154
|
-
unavailable: 5
|
|
155
|
-
};
|
|
156
|
-
EXIT_BY_CODE = {
|
|
157
|
-
ok: EXIT.ok,
|
|
158
|
-
failed: EXIT.failed,
|
|
159
|
-
not_found: EXIT.failed,
|
|
160
|
-
invalid_input: EXIT.usage,
|
|
161
|
-
not_implemented: EXIT.usage,
|
|
162
|
-
blocked: EXIT.blocked,
|
|
163
|
-
busy: EXIT.busy,
|
|
164
|
-
pending: EXIT.busy,
|
|
165
|
-
unavailable: EXIT.unavailable
|
|
166
|
-
};
|
|
167
|
-
});
|
|
168
|
-
|
|
169
120
|
// packages/workit-core/src/check-config.ts
|
|
170
121
|
import { spawnSync } from "node:child_process";
|
|
171
122
|
import fs from "node:fs";
|
|
@@ -21482,7 +21433,7 @@ function resolveInside(root, candidate) {
|
|
|
21482
21433
|
}
|
|
21483
21434
|
return target;
|
|
21484
21435
|
}
|
|
21485
|
-
var
|
|
21436
|
+
var ok = (data) => ({ ok: true, data, error: null }), fail = (error, data = null) => ({
|
|
21486
21437
|
ok: false,
|
|
21487
21438
|
data,
|
|
21488
21439
|
error
|
|
@@ -21604,6 +21555,12 @@ async function parseTaskArgs(argv, deps) {
|
|
|
21604
21555
|
json = true;
|
|
21605
21556
|
continue;
|
|
21606
21557
|
}
|
|
21558
|
+
if (family === "task" && action === "list" && token === "--status") {
|
|
21559
|
+
const value = inline ?? argv[++i];
|
|
21560
|
+
if (value !== "all")
|
|
21561
|
+
return parseUsage(`task list has no status filter (got --status ${value ?? ""}); it lists every task`, json);
|
|
21562
|
+
continue;
|
|
21563
|
+
}
|
|
21607
21564
|
if (takesWorkerId && workerId === undefined && !argv[i].startsWith("-")) {
|
|
21608
21565
|
workerId = argv[i];
|
|
21609
21566
|
continue;
|
|
@@ -21885,6 +21842,55 @@ var init_task = __esm(() => {
|
|
|
21885
21842
|
};
|
|
21886
21843
|
});
|
|
21887
21844
|
|
|
21845
|
+
// packages/workit-cli/src/output.ts
|
|
21846
|
+
function emit(io, envelope, human) {
|
|
21847
|
+
if (io.json) {
|
|
21848
|
+
io.stdout(`${JSON.stringify(envelope)}
|
|
21849
|
+
`);
|
|
21850
|
+
} else if (envelope.ok) {
|
|
21851
|
+
const text = human?.(envelope.data);
|
|
21852
|
+
const lines = typeof text === "string" ? [text] : text ?? [];
|
|
21853
|
+
for (const value of lines)
|
|
21854
|
+
io.stdout(`${value}
|
|
21855
|
+
`);
|
|
21856
|
+
} else {
|
|
21857
|
+
io.stderr(`workit: ${envelope.error ?? envelope.code}
|
|
21858
|
+
`);
|
|
21859
|
+
if (envelope.unblock)
|
|
21860
|
+
io.stderr(` unblock: ${envelope.unblock}
|
|
21861
|
+
`);
|
|
21862
|
+
}
|
|
21863
|
+
return exitCodeFor(envelope.code);
|
|
21864
|
+
}
|
|
21865
|
+
var EXIT, EXIT_BY_CODE, exitCodeFor = (code) => EXIT_BY_CODE[code], ok2 = (data) => ({ ok: true, code: "ok", data }), fail2 = (code, error, extra = {}) => ({
|
|
21866
|
+
ok: false,
|
|
21867
|
+
code,
|
|
21868
|
+
data: extra.data ?? {},
|
|
21869
|
+
error,
|
|
21870
|
+
...extra.unblock ? { unblock: extra.unblock } : {}
|
|
21871
|
+
});
|
|
21872
|
+
var init_output = __esm(() => {
|
|
21873
|
+
EXIT = {
|
|
21874
|
+
ok: 0,
|
|
21875
|
+
failed: 1,
|
|
21876
|
+
usage: 2,
|
|
21877
|
+
blocked: 3,
|
|
21878
|
+
busy: 4,
|
|
21879
|
+
unavailable: 5
|
|
21880
|
+
};
|
|
21881
|
+
EXIT_BY_CODE = {
|
|
21882
|
+
ok: EXIT.ok,
|
|
21883
|
+
failed: EXIT.failed,
|
|
21884
|
+
not_found: EXIT.failed,
|
|
21885
|
+
invalid_input: EXIT.usage,
|
|
21886
|
+
not_implemented: EXIT.usage,
|
|
21887
|
+
blocked: EXIT.blocked,
|
|
21888
|
+
busy: EXIT.busy,
|
|
21889
|
+
pending: EXIT.busy,
|
|
21890
|
+
unavailable: EXIT.unavailable
|
|
21891
|
+
};
|
|
21892
|
+
});
|
|
21893
|
+
|
|
21888
21894
|
// packages/workit-cli/src/verbs/task.ts
|
|
21889
21895
|
function isImplicitTaskForm(argv) {
|
|
21890
21896
|
const [action, ...rest] = argv;
|
|
@@ -21929,7 +21935,7 @@ async function run(argv, io) {
|
|
|
21929
21935
|
const [action, ...rest] = argv;
|
|
21930
21936
|
const flags = parse4(rest);
|
|
21931
21937
|
if (flags instanceof Error)
|
|
21932
|
-
return emit(io,
|
|
21938
|
+
return emit(io, fail2("invalid_input", flags.message, { unblock: USAGE }));
|
|
21933
21939
|
await Promise.resolve().then(() => init_core3());
|
|
21934
21940
|
const root = rootFor(io);
|
|
21935
21941
|
const store = new TaskStore(root);
|
|
@@ -21951,7 +21957,7 @@ async function run(argv, io) {
|
|
|
21951
21957
|
};
|
|
21952
21958
|
const key = store.currentKey();
|
|
21953
21959
|
if (!key.ok)
|
|
21954
|
-
return emit(io,
|
|
21960
|
+
return emit(io, fail2("unavailable", key.error));
|
|
21955
21961
|
const where = key.data.branch ? `branch ${key.data.branch}` : key.data.key;
|
|
21956
21962
|
if (action === "status") {
|
|
21957
21963
|
if (flags.switches.has("--all")) {
|
|
@@ -21968,7 +21974,7 @@ async function run(argv, io) {
|
|
|
21968
21974
|
progress: entry.progress,
|
|
21969
21975
|
current: entry.key === key.data.key && entry.status !== "closed"
|
|
21970
21976
|
}));
|
|
21971
|
-
return emit(io,
|
|
21977
|
+
return emit(io, ok2({ key: key.data, tasks }), (data) => data.tasks.length ? data.tasks.map((task) => `${task.current ? "*" : " "} ${task.id} ${task.status}${task.key ? ` [${task.key}]` : task.legacy ? " [2.x; adopt with workit task adopt <id>]" : ""} — ${task.objective}`) : ["no tasks in this store"]);
|
|
21972
21978
|
}
|
|
21973
21979
|
const found = store.implicitTask({ provenance, create: false });
|
|
21974
21980
|
if (!found.ok)
|
|
@@ -21985,7 +21991,7 @@ async function run(argv, io) {
|
|
|
21985
21991
|
});
|
|
21986
21992
|
const noteLines = notes.map((note) => `duplicate open task ${note.id} on ${note.key} (not used); close it: ${note.hint}`);
|
|
21987
21993
|
if (!found.data)
|
|
21988
|
-
return emit(io,
|
|
21994
|
+
return emit(io, ok2({ key: key.data, task: null, notes }), () => [
|
|
21989
21995
|
`no task for ${where} yet; it is created by the first note, check or recording (or: workit task start "<objective>")`,
|
|
21990
21996
|
...noteLines
|
|
21991
21997
|
]);
|
|
@@ -21998,7 +22004,7 @@ async function run(argv, io) {
|
|
|
21998
22004
|
if (!summary.ok)
|
|
21999
22005
|
return engineFailure(io, summary);
|
|
22000
22006
|
const task = found.data.task;
|
|
22001
|
-
return emit(io,
|
|
22007
|
+
return emit(io, ok2({ key: key.data, task: summary.data, notes }), () => [
|
|
22002
22008
|
`${task.id} ${task.status} — ${task.intent.data.objective} (${where})`,
|
|
22003
22009
|
...task.progress.summary ? [`progress: ${task.progress.summary}`] : [],
|
|
22004
22010
|
...task.progress.nextAction ? [`next: ${task.progress.nextAction}`] : [],
|
|
@@ -22009,7 +22015,7 @@ async function run(argv, io) {
|
|
|
22009
22015
|
if (action === "start" || action === "note") {
|
|
22010
22016
|
const text = flags.positionals.join(" ").trim();
|
|
22011
22017
|
if (!text)
|
|
22012
|
-
return emit(io,
|
|
22018
|
+
return emit(io, fail2("invalid_input", `task ${action} needs ${action === "start" ? "an objective" : "a note"}`, {
|
|
22013
22019
|
unblock: USAGE
|
|
22014
22020
|
}));
|
|
22015
22021
|
const objective = action === "start" ? text : flags.values.get("--objective") ?? undefined;
|
|
@@ -22048,7 +22054,7 @@ async function run(argv, io) {
|
|
|
22048
22054
|
const latest = store.readTask(task.id);
|
|
22049
22055
|
if (latest.ok)
|
|
22050
22056
|
task = latest.data;
|
|
22051
|
-
return emit(io,
|
|
22057
|
+
return emit(io, ok2({
|
|
22052
22058
|
key: key.data,
|
|
22053
22059
|
created: found.data.created,
|
|
22054
22060
|
task: {
|
|
@@ -22063,12 +22069,12 @@ async function run(argv, io) {
|
|
|
22063
22069
|
const outcomeFlag = flags.values.get("--outcome") ?? "verified";
|
|
22064
22070
|
const outcome = OUTCOMES[outcomeFlag];
|
|
22065
22071
|
if (!outcome)
|
|
22066
|
-
return emit(io,
|
|
22072
|
+
return emit(io, fail2("invalid_input", "--outcome is verified, limited or stopped", { unblock: USAGE }));
|
|
22067
22073
|
const found = store.implicitTask({ provenance, create: false });
|
|
22068
22074
|
if (!found.ok)
|
|
22069
22075
|
return engineFailure(io, found);
|
|
22070
22076
|
if (!found.data)
|
|
22071
|
-
return emit(io,
|
|
22077
|
+
return emit(io, fail2("not_found", `no open task for ${where}`));
|
|
22072
22078
|
const task = found.data.task;
|
|
22073
22079
|
const summary = flags.values.get("--summary") ?? (task.progress.summary || `closed (${outcomeFlag})`);
|
|
22074
22080
|
return runTaskCommand([
|
|
@@ -22085,15 +22091,15 @@ async function run(argv, io) {
|
|
|
22085
22091
|
if (action === "adopt") {
|
|
22086
22092
|
const [id] = flags.positionals;
|
|
22087
22093
|
if (!id || flags.positionals.length !== 1)
|
|
22088
|
-
return emit(io,
|
|
22094
|
+
return emit(io, fail2("invalid_input", "task adopt takes one task id", { unblock: USAGE }));
|
|
22089
22095
|
const adopted = store.adoptTask(id);
|
|
22090
22096
|
if (!adopted.ok)
|
|
22091
22097
|
return engineFailure(io, adopted, "workit task status --all");
|
|
22092
|
-
return emit(io,
|
|
22098
|
+
return emit(io, ok2({ key: key.data, task: { id: adopted.data.id, status: adopted.data.status } }), () => `${adopted.data.id} now tracks ${where}`);
|
|
22093
22099
|
}
|
|
22094
|
-
return emit(io,
|
|
22100
|
+
return emit(io, fail2("invalid_input", `unknown task action ${action ?? ""}`, { unblock: USAGE }));
|
|
22095
22101
|
}
|
|
22096
|
-
var USAGE = 'workit task status [--all] | task start "<objective>" | task note "<text>" [--next "<t>"] [--objective "<t>"] | task close [--outcome verified|limited|stopped] [--summary "<t>"] [--confirm] | task adopt <id>', IMPLICIT2, VALUE_FLAGS, SWITCHES, ENGINE_CODES, engineFailure = (io, result, unblock) => emit(io,
|
|
22102
|
+
var USAGE = 'workit task status [--all] | task start "<objective>" | task note "<text>" [--next "<t>"] [--objective "<t>"] | task close [--outcome verified|limited|stopped] [--summary "<t>"] [--confirm] | task adopt <id>', IMPLICIT2, VALUE_FLAGS, SWITCHES, ENGINE_CODES, engineFailure = (io, result, unblock) => emit(io, fail2(ENGINE_CODES[result.code] ?? "failed", `${result.code}: ${result.error}`, {
|
|
22097
22103
|
data: { code: result.code },
|
|
22098
22104
|
...unblock ? { unblock } : result.code === "busy" ? { unblock: "retry the same command" } : {}
|
|
22099
22105
|
})), OUTCOMES, rootFor = (io) => io.env.WORKFLOW_WORKSPACE_ROOT || checkRoot(io.cwd);
|
|
@@ -36767,7 +36773,7 @@ function getSgrPrefix(code) {
|
|
|
36767
36773
|
if (code.startsWith("")) {
|
|
36768
36774
|
return "";
|
|
36769
36775
|
}
|
|
36770
|
-
return `${
|
|
36776
|
+
return `${ESCAPE}${ANSI_CSI2}`;
|
|
36771
36777
|
}
|
|
36772
36778
|
function createSgrCode(prefix, values) {
|
|
36773
36779
|
return `${prefix}${values.join(";")}${ANSI_SGR_TERMINATOR2}`;
|
|
@@ -36776,7 +36782,7 @@ function getSgrFragments(code) {
|
|
|
36776
36782
|
const fragments = [];
|
|
36777
36783
|
const sgrPrefix = getSgrPrefix(code);
|
|
36778
36784
|
let parameterString;
|
|
36779
|
-
if (code.startsWith(`${
|
|
36785
|
+
if (code.startsWith(`${ESCAPE}${ANSI_CSI2}`)) {
|
|
36780
36786
|
parameterString = code.slice(2, -1);
|
|
36781
36787
|
} else if (code.startsWith("")) {
|
|
36782
36788
|
parameterString = code.slice(1, -1);
|
|
@@ -36937,7 +36943,7 @@ function parseHyperlinkCode(string, index) {
|
|
|
36937
36943
|
endIndex: sequenceIndex + 1
|
|
36938
36944
|
};
|
|
36939
36945
|
}
|
|
36940
|
-
if (character ===
|
|
36946
|
+
if (character === ESCAPE && string[sequenceIndex + 1] === ANSI_OSC_TERMINATOR) {
|
|
36941
36947
|
const code = string.slice(index, sequenceIndex + 2);
|
|
36942
36948
|
const action = sequenceIndex === uriStart + 1 ? "close" : "open";
|
|
36943
36949
|
return {
|
|
@@ -37020,7 +37026,7 @@ function parseControlStringCode(string, index) {
|
|
|
37020
37026
|
if (supportsBellTerminator && string[sequenceIndex] === ANSI_BELL) {
|
|
37021
37027
|
return createControlParseResult(string.slice(index, sequenceIndex + 1), sequenceIndex + 1);
|
|
37022
37028
|
}
|
|
37023
|
-
if (string[sequenceIndex] ===
|
|
37029
|
+
if (string[sequenceIndex] === ESCAPE && string[sequenceIndex + 1] === ANSI_OSC_TERMINATOR) {
|
|
37024
37030
|
return createControlParseResult(string.slice(index, sequenceIndex + 2), sequenceIndex + 2);
|
|
37025
37031
|
}
|
|
37026
37032
|
if (string[sequenceIndex] === C1_STRING_TERMINATOR) {
|
|
@@ -37245,7 +37251,7 @@ function tokenizeAnsi(string, { endCharacter = Number.POSITIVE_INFINITY } = {})
|
|
|
37245
37251
|
}
|
|
37246
37252
|
return tokens;
|
|
37247
37253
|
}
|
|
37248
|
-
var ESCAPE_CODE_POINT = 27, C1_DCS_CODE_POINT = 144, C1_SOS_CODE_POINT = 152, C1_CSI_CODE_POINT = 155, C1_ST_CODE_POINT = 156, C1_OSC_CODE_POINT = 157, C1_PM_CODE_POINT = 158, C1_APC_CODE_POINT = 159, ESCAPES2,
|
|
37254
|
+
var ESCAPE_CODE_POINT = 27, C1_DCS_CODE_POINT = 144, C1_SOS_CODE_POINT = 152, C1_CSI_CODE_POINT = 155, C1_ST_CODE_POINT = 156, C1_OSC_CODE_POINT = 157, C1_PM_CODE_POINT = 158, C1_APC_CODE_POINT = 159, ESCAPES2, ESCAPE = "\x1B", ANSI_BELL = "\x07", ANSI_CSI2 = "[", ANSI_OSC2 = "]", ANSI_DCS = "P", ANSI_SOS = "X", ANSI_PM = "^", ANSI_APC = "_", ANSI_SGR_TERMINATOR2 = "m", ANSI_OSC_TERMINATOR = "\\", ANSI_STRING_TERMINATOR, C1_OSC = "", C1_STRING_TERMINATOR = "", ANSI_HYPERLINK_ESC_PREFIX, ANSI_HYPERLINK_C1_PREFIX, ANSI_HYPERLINK_ESC_CLOSE, ANSI_HYPERLINK_C1_CLOSE, CODE_POINT_0, CODE_POINT_9, CODE_POINT_SEMICOLON, CODE_POINT_COLON, CODE_POINT_CSI_PARAMETER_START, CODE_POINT_CSI_PARAMETER_END, CODE_POINT_CSI_INTERMEDIATE_START, CODE_POINT_CSI_INTERMEDIATE_END, CODE_POINT_CSI_FINAL_START, CODE_POINT_CSI_FINAL_END, REGIONAL_INDICATOR_SYMBOL_LETTER_A = 127462, REGIONAL_INDICATOR_SYMBOL_LETTER_Z = 127487, SGR_RESET_CODE = 0, SGR_EXTENDED_FOREGROUND_CODE = 38, SGR_DEFAULT_FOREGROUND_CODE = 39, SGR_EXTENDED_BACKGROUND_CODE = 48, SGR_DEFAULT_BACKGROUND_CODE = 49, SGR_COLOR_TYPE_ANSI_256 = 5, SGR_COLOR_TYPE_TRUECOLOR = 2, SGR_ANSI_256_FRAGMENT_LENGTH = 3, SGR_TRUECOLOR_FRAGMENT_LENGTH = 5, SGR_ANSI_256_LAST_PARAMETER_OFFSET = 2, SGR_TRUECOLOR_LAST_PARAMETER_OFFSET = 4, VARIATION_SELECTOR_16_CODE_POINT = 65039, COMBINING_ENCLOSING_KEYCAP_CODE_POINT = 8419, EMOJI_PRESENTATION_GRAPHEME_REGEX, GRAPHEME_SEGMENTER, endCodeNumbers;
|
|
37249
37255
|
var init_tokenize_ansi = __esm(() => {
|
|
37250
37256
|
init_ansi_styles();
|
|
37251
37257
|
init_is_fullwidth_code_point();
|
|
@@ -37259,8 +37265,8 @@ var init_tokenize_ansi = __esm(() => {
|
|
|
37259
37265
|
C1_PM_CODE_POINT,
|
|
37260
37266
|
C1_APC_CODE_POINT
|
|
37261
37267
|
]);
|
|
37262
|
-
ANSI_STRING_TERMINATOR = `${
|
|
37263
|
-
ANSI_HYPERLINK_ESC_PREFIX = `${
|
|
37268
|
+
ANSI_STRING_TERMINATOR = `${ESCAPE}${ANSI_OSC_TERMINATOR}`;
|
|
37269
|
+
ANSI_HYPERLINK_ESC_PREFIX = `${ESCAPE}${ANSI_OSC2}8;`;
|
|
37264
37270
|
ANSI_HYPERLINK_C1_PREFIX = `${C1_OSC}8;`;
|
|
37265
37271
|
ANSI_HYPERLINK_ESC_CLOSE = `${ANSI_HYPERLINK_ESC_PREFIX};`;
|
|
37266
37272
|
ANSI_HYPERLINK_C1_CLOSE = `${ANSI_HYPERLINK_C1_PREFIX};`;
|
|
@@ -73094,7 +73100,7 @@ __export(exports_init, {
|
|
|
73094
73100
|
});
|
|
73095
73101
|
async function run3(_argv, io) {
|
|
73096
73102
|
if (io.json)
|
|
73097
|
-
return emit(io,
|
|
73103
|
+
return emit(io, fail2("invalid_input", "workit init is an interactive wizard and has no --json output", {
|
|
73098
73104
|
unblock: "run `workit init` in a terminal without --json"
|
|
73099
73105
|
}));
|
|
73100
73106
|
await init_src2();
|
|
@@ -73982,7 +73988,7 @@ async function run6(argv, io) {
|
|
|
73982
73988
|
if (!confirmed) {
|
|
73983
73989
|
if (!io.json)
|
|
73984
73990
|
return 3;
|
|
73985
|
-
return emit(io,
|
|
73991
|
+
return emit(io, fail2("blocked", "fix-lock --force: refusing without --yes outside an interactive terminal", {
|
|
73986
73992
|
data: { lock: inspectMetadataLock(root) },
|
|
73987
73993
|
unblock: "workit doctor --fix-lock --force --yes"
|
|
73988
73994
|
}));
|
|
@@ -74550,7 +74556,7 @@ async function run7(argv, io) {
|
|
|
74550
74556
|
const dryRun = argv.includes("--dry-run");
|
|
74551
74557
|
const pruneRecovery = argv.includes("--prune-recovery");
|
|
74552
74558
|
if (pruneRecovery && !dryRun && !argv.includes("--yes"))
|
|
74553
|
-
return emit(io,
|
|
74559
|
+
return emit(io, fail2("blocked", "--prune-recovery deletes the 2.x recovery copies; confirm with --yes", {
|
|
74554
74560
|
unblock: "workit gc --prune-recovery --yes"
|
|
74555
74561
|
}));
|
|
74556
74562
|
const store = new TaskStore(workspaceRootFor({ cwd: io.cwd }));
|
|
@@ -74558,11 +74564,11 @@ async function run7(argv, io) {
|
|
|
74558
74564
|
const logs = location.ok ? pruneCheckLogs(location.data.dir, { dryRun }) : null;
|
|
74559
74565
|
const result = store.collectGarbage({ dryRun, pruneRecovery });
|
|
74560
74566
|
if (!result.ok)
|
|
74561
|
-
return emit(io,
|
|
74567
|
+
return emit(io, fail2(result.code === "busy" ? "busy" : "failed", `${result.code}: ${result.error}`, {
|
|
74562
74568
|
data: { code: result.code, details: result.details },
|
|
74563
74569
|
...result.code === "busy" ? { unblock: "retry `workit gc`" } : {}
|
|
74564
74570
|
}));
|
|
74565
|
-
return emit(io,
|
|
74571
|
+
return emit(io, ok2({ ...result.data, logs }), (data) => {
|
|
74566
74572
|
const verb = data.dryRun ? "would" : "did";
|
|
74567
74573
|
const { compacted, blobs, legacyRecovery } = data;
|
|
74568
74574
|
return [
|
|
@@ -74594,7 +74600,7 @@ __export(exports_uninstall, {
|
|
|
74594
74600
|
});
|
|
74595
74601
|
async function run8(_argv, io) {
|
|
74596
74602
|
if (io.json)
|
|
74597
|
-
return emit(io,
|
|
74603
|
+
return emit(io, fail2("invalid_input", "workit uninstall is interactive and has no --json output", {
|
|
74598
74604
|
unblock: "run `workit uninstall` in a terminal without --json"
|
|
74599
74605
|
}));
|
|
74600
74606
|
await init_src2();
|
|
@@ -74619,11 +74625,11 @@ function show(argv, io) {
|
|
|
74619
74625
|
if (all || named.length === 1) {
|
|
74620
74626
|
const listed = listGrants();
|
|
74621
74627
|
if (listed.error)
|
|
74622
|
-
return emit(io,
|
|
74628
|
+
return emit(io, fail2("invalid_input", listed.error));
|
|
74623
74629
|
const rows = named.length ? listed.workspaces.filter((entry) => entry.name === named[0]) : listed.workspaces;
|
|
74624
74630
|
if (named.length && rows.length === 0)
|
|
74625
|
-
return emit(io,
|
|
74626
|
-
return emit(io,
|
|
74631
|
+
return emit(io, fail2("not_found", `no workspace named "${named[0]}" in ${listed.path}`));
|
|
74632
|
+
return emit(io, ok2({ path: listed.path, defaults: DEFAULT_GRANTS, workspaces: rows }), () => rows.flatMap((entry) => [
|
|
74627
74633
|
`${entry.name} (${entry.glob})`,
|
|
74628
74634
|
...describe2(entry.grants, entry.configured, entry, entry.verification)
|
|
74629
74635
|
]));
|
|
@@ -74632,7 +74638,7 @@ function show(argv, io) {
|
|
|
74632
74638
|
try {
|
|
74633
74639
|
autonomy = resolveAutonomy(io.cwd);
|
|
74634
74640
|
} catch (error) {
|
|
74635
|
-
return emit(io,
|
|
74641
|
+
return emit(io, fail2("invalid_input", error instanceof Error ? error.message : String(error)));
|
|
74636
74642
|
}
|
|
74637
74643
|
const tracks = releaseTracksReport(io.cwd);
|
|
74638
74644
|
const tierModelIssues = workspaceTierModelIssues(io.cwd);
|
|
@@ -74641,7 +74647,7 @@ function show(argv, io) {
|
|
|
74641
74647
|
...tracks.tracks.length || tracks.error ? { releaseTracks: tracks } : {},
|
|
74642
74648
|
...tierModelIssues.length ? { tierModelIssues } : {}
|
|
74643
74649
|
};
|
|
74644
|
-
return emit(io,
|
|
74650
|
+
return emit(io, ok2(shown), (data) => [
|
|
74645
74651
|
...data.note ? [`note: ${data.note}`] : [],
|
|
74646
74652
|
...tierModelIssues.map((issue) => `note: ${issue}`),
|
|
74647
74653
|
data.workspace ? `workspace ${data.workspace} (${data.source === "default" ? "D4 defaults" : `from ${data.source}`})` : "no workspace matches this checkout: D4 defaults apply",
|
|
@@ -74656,10 +74662,10 @@ async function change(verb, argv, io, deps) {
|
|
|
74656
74662
|
return usage2(io, `${verb} needs <workspace> and a kind`);
|
|
74657
74663
|
const listed = listGrants();
|
|
74658
74664
|
if (listed.error)
|
|
74659
|
-
return emit(io,
|
|
74665
|
+
return emit(io, fail2("invalid_input", listed.error));
|
|
74660
74666
|
const entry = listed.workspaces.find((item) => item.name === workspace);
|
|
74661
74667
|
if (!entry)
|
|
74662
|
-
return emit(io,
|
|
74668
|
+
return emit(io, fail2("not_found", `no workspace named "${workspace}" in ${listed.path}`));
|
|
74663
74669
|
const changes = [];
|
|
74664
74670
|
let endpoint;
|
|
74665
74671
|
let verification;
|
|
@@ -74703,17 +74709,17 @@ async function change(verb, argv, io, deps) {
|
|
|
74703
74709
|
const command = `workit grant ${verb} ${workspace} ${specs.join(" ")}`;
|
|
74704
74710
|
const agent = agentMarker(io.env);
|
|
74705
74711
|
if (!deps.interactive() || agent)
|
|
74706
|
-
return emit(io,
|
|
74712
|
+
return emit(io, fail2("blocked", `grant_raise_refused: raising ${raised.map(({ kind }) => kind).join(", ")} needs the user at an interactive terminal${agent ? ` (this shell belongs to an agent: ${agent} is set)` : ""}; grants are never raised headless`, { unblock: `ask the user to run, in their own terminal: ${command}` }));
|
|
74707
74713
|
const answer = await askOrCancel(io, () => deps.ask(`Raise ${raised.map(({ kind, value }) => `${kind}=${value}`).join(", ")} for workspace "${workspace}"? An agent there may then do this without asking. Type the workspace name to confirm: `));
|
|
74708
74714
|
if (answer === null)
|
|
74709
74715
|
return cancelled(io);
|
|
74710
74716
|
if (answer.trim() !== workspace)
|
|
74711
|
-
return emit(io,
|
|
74717
|
+
return emit(io, fail2("blocked", "grant change not confirmed; nothing was written"));
|
|
74712
74718
|
}
|
|
74713
74719
|
const written = writeGrants(workspace, changes, undefined, endpoint, verification);
|
|
74714
74720
|
if (!written.ok)
|
|
74715
|
-
return emit(io,
|
|
74716
|
-
return emit(io,
|
|
74721
|
+
return emit(io, fail2(written.code, written.error));
|
|
74722
|
+
return emit(io, ok2(written), (data) => [
|
|
74717
74723
|
`${data.workspace}: grants updated in ${data.path}${data.backup ? ` (previous copy: ${data.backup})` : ""}`,
|
|
74718
74724
|
...describe2(data.grants, data.configured, data, data.verification)
|
|
74719
74725
|
]);
|
|
@@ -74734,7 +74740,7 @@ var USAGE2 = "workit grant show [<workspace>] [--all] | grant set <workspace> <k
|
|
|
74734
74740
|
` default endpoint: ${endpointLabel(endpoint)} (an unnamed request stops at ${STOPS_AT[endpoint.effectiveEndpoint]})`,
|
|
74735
74741
|
...endpoint.endpointIssue ? [` note: ${endpoint.endpointIssue}`] : [],
|
|
74736
74742
|
` verification: ${verification} (${verification === "independent" ? "a normal-risk behavior change needs a non-author verdict" : "a normal-risk behavior change needs a passing check and the author's --self verdict, shown as self-reviewed"})`
|
|
74737
|
-
], usage2 = (io, message) => emit(io,
|
|
74743
|
+
], usage2 = (io, message) => emit(io, fail2("invalid_input", `${message}
|
|
74738
74744
|
usage: ${USAGE2}`)), run9 = (argv, io) => runGrant(argv, io);
|
|
74739
74745
|
var init_grant = __esm(() => {
|
|
74740
74746
|
init_autonomy();
|
|
@@ -75851,7 +75857,7 @@ async function prepareHeavy(io, settings, label, runCwd, timeoutMs) {
|
|
|
75851
75857
|
});
|
|
75852
75858
|
if (!acquired.ok && acquired.reason === "timeout") {
|
|
75853
75859
|
const holders = acquired.holders.map((holder) => describeHolder(holder)).join("; ");
|
|
75854
|
-
emit(io,
|
|
75860
|
+
emit(io, fail2("busy", `the heavy-check lease stayed busy for ${Math.round(acquired.waitedMs / 1000)} s`, {
|
|
75855
75861
|
data: { lease: { waitedMs: acquired.waitedMs, holders: acquired.holders } },
|
|
75856
75862
|
unblock: `wait for ${holders || "the holders"} to finish, then run it again`
|
|
75857
75863
|
}));
|
|
@@ -75901,7 +75907,7 @@ async function prepareHeavy(io, settings, label, runCwd, timeoutMs) {
|
|
|
75901
75907
|
async function run10(argv, io) {
|
|
75902
75908
|
const options = parse5(argv);
|
|
75903
75909
|
if (options instanceof Error)
|
|
75904
|
-
return emit(io,
|
|
75910
|
+
return emit(io, fail2("invalid_input", options.message, { unblock: USAGE3 }));
|
|
75905
75911
|
const config = loadCheckConfig(io.cwd);
|
|
75906
75912
|
if (config.note)
|
|
75907
75913
|
io.stderr(`note: ${config.note}
|
|
@@ -75912,13 +75918,13 @@ async function run10(argv, io) {
|
|
|
75912
75918
|
let name = options.name;
|
|
75913
75919
|
if (options.command === null) {
|
|
75914
75920
|
if (options.positionals.length !== 1 || options.name || options.shell)
|
|
75915
|
-
return emit(io,
|
|
75921
|
+
return emit(io, fail2("invalid_input", "pass a check name, or a command after --", { unblock: USAGE3 }));
|
|
75916
75922
|
name = options.positionals[0];
|
|
75917
75923
|
if (config.error)
|
|
75918
|
-
return emit(io,
|
|
75924
|
+
return emit(io, fail2("invalid_input", `check config is invalid: ${config.error}`));
|
|
75919
75925
|
const check = config.checks.find((item) => item.name === name);
|
|
75920
75926
|
if (!check)
|
|
75921
|
-
return emit(io,
|
|
75927
|
+
return emit(io, fail2("not_found", `no configured check named "${name}"`, {
|
|
75922
75928
|
data: { configured: config.checks.map((item) => item.name), source: config.source },
|
|
75923
75929
|
unblock: config.checks.length ? `workit check ${config.checks.map((item) => item.name).join("|")}` : `add {"checks":{"${name}":"<command>"}} to .workit/checks.json, or run workit check --name ${name} -- <cmd…>`
|
|
75924
75930
|
}));
|
|
@@ -75926,14 +75932,14 @@ async function run10(argv, io) {
|
|
|
75926
75932
|
runCwd = config.root;
|
|
75927
75933
|
} else {
|
|
75928
75934
|
if (options.positionals.length)
|
|
75929
|
-
return emit(io,
|
|
75935
|
+
return emit(io, fail2("invalid_input", `unexpected argument ${options.positionals[0]} before --`, {
|
|
75930
75936
|
unblock: USAGE3
|
|
75931
75937
|
}));
|
|
75932
75938
|
command = options.command;
|
|
75933
75939
|
if (!command.length)
|
|
75934
|
-
return emit(io,
|
|
75940
|
+
return emit(io, fail2("invalid_input", "no command after --", { unblock: USAGE3 }));
|
|
75935
75941
|
if (options.shell && command.length !== 1)
|
|
75936
|
-
return emit(io,
|
|
75942
|
+
return emit(io, fail2("invalid_input", '--shell takes the command as one string: workit check --shell -- "<cmd>"'));
|
|
75937
75943
|
}
|
|
75938
75944
|
const relCwd = posix(path45.relative(top, runCwd));
|
|
75939
75945
|
const configured = !options.shell && matchesNamedCheck(config, name, command, relCwd);
|
|
@@ -76146,7 +76152,7 @@ function slotLines(slots) {
|
|
|
76146
76152
|
async function status(io) {
|
|
76147
76153
|
const settings = await settingsFor(io);
|
|
76148
76154
|
const slots = leaseSlots(leaseDir(io.env), settings.slots);
|
|
76149
|
-
return emit(io,
|
|
76155
|
+
return emit(io, ok2({ dir: leaseDir(io.env), slots, waitMs: settings.waitMs }), (data) => slotLines(data.slots));
|
|
76150
76156
|
}
|
|
76151
76157
|
function timeoutOf(args) {
|
|
76152
76158
|
const at = args.findIndex((arg) => arg === "--timeout" || arg.startsWith("--timeout="));
|
|
@@ -76159,7 +76165,7 @@ function timeoutOf(args) {
|
|
|
76159
76165
|
async function wait(args, io) {
|
|
76160
76166
|
const timeout = timeoutOf(args);
|
|
76161
76167
|
if (timeout instanceof Error)
|
|
76162
|
-
return emit(io,
|
|
76168
|
+
return emit(io, fail2("invalid_input", timeout.message));
|
|
76163
76169
|
const settings = await settingsFor(io);
|
|
76164
76170
|
const limit = timeout ?? settings.waitMs;
|
|
76165
76171
|
const dir = leaseDir(io.env);
|
|
@@ -76170,11 +76176,11 @@ async function wait(args, io) {
|
|
|
76170
76176
|
const busy = held(slots);
|
|
76171
76177
|
const waitedMs = Date.now() - started;
|
|
76172
76178
|
if (busy.length < slots.length)
|
|
76173
|
-
return emit(io,
|
|
76179
|
+
return emit(io, ok2({ free: true, waitedMs, slots }), () => [
|
|
76174
76180
|
`workit: the heavy-check lease has a free slot${waitedMs ? ` after ${Math.round(waitedMs / 1000)} s` : ""}`
|
|
76175
76181
|
]);
|
|
76176
76182
|
if (waitedMs >= limit)
|
|
76177
|
-
return emit(io,
|
|
76183
|
+
return emit(io, fail2("busy", `the heavy-check lease stayed busy for ${Math.round(waitedMs / 1000)} s`, {
|
|
76178
76184
|
data: { free: false, waitedMs, slots },
|
|
76179
76185
|
unblock: "workit lock status"
|
|
76180
76186
|
}));
|
|
@@ -76191,7 +76197,7 @@ async function runHeavy(args, io) {
|
|
|
76191
76197
|
const head = split < 0 ? args : args.slice(0, split);
|
|
76192
76198
|
const unknown = head.find((arg, index) => arg !== "--shell" && arg !== "--json" && !arg.startsWith("--timeout") && !arg.startsWith("--wait") && !((head[index - 1] === "--timeout" || head[index - 1] === "--wait") && !arg.startsWith("-")));
|
|
76193
76199
|
if (split < 0 || unknown)
|
|
76194
|
-
return emit(io,
|
|
76200
|
+
return emit(io, fail2("invalid_input", unknown ? `unexpected ${unknown}` : "no command after --", {
|
|
76195
76201
|
unblock: "workit lock run [--shell] [--wait <s>] [--timeout <s>] -- <cmd…>"
|
|
76196
76202
|
}));
|
|
76197
76203
|
const check = await Promise.resolve().then(() => (init_check(), {}));
|
|
@@ -76219,7 +76225,7 @@ async function heavy(args, io) {
|
|
|
76219
76225
|
const [action, ...rest] = args.filter((arg) => arg !== "--json");
|
|
76220
76226
|
const file = heavyCommandsFile(io.env);
|
|
76221
76227
|
if (action === "list")
|
|
76222
|
-
return emit(io,
|
|
76228
|
+
return emit(io, ok2({ file, machine: machinePatterns(io.env), repo: repoPatterns(io.cwd) }), (data) => [
|
|
76223
76229
|
"built in: test runners, builds and bundlers, lint and typecheck, installs, image builds, Sonar, browser tests (JS, Go, Rust, JVM, .NET, Python, Ruby, PHP, Elixir, Swift, C)",
|
|
76224
76230
|
`machine (${data.file}): ${data.machine.length ? data.machine.join(", ") : "none"}`,
|
|
76225
76231
|
`repo (checks config resources.heavyCommands): ${data.repo.length ? data.repo.join(", ") : "none"}`
|
|
@@ -76227,7 +76233,7 @@ async function heavy(args, io) {
|
|
|
76227
76233
|
if (action === "add" || action === "remove") {
|
|
76228
76234
|
const pattern = commandText(rest);
|
|
76229
76235
|
if (!parsePattern(pattern))
|
|
76230
|
-
return emit(io,
|
|
76236
|
+
return emit(io, fail2("invalid_input", `${action} needs a command pattern`, {
|
|
76231
76237
|
unblock: `workit lock heavy ${action} '<command words>'`
|
|
76232
76238
|
}));
|
|
76233
76239
|
const current = readPatterns(file);
|
|
@@ -76238,22 +76244,22 @@ async function heavy(args, io) {
|
|
|
76238
76244
|
if (patterns !== current.patterns)
|
|
76239
76245
|
writePatterns(file, { ...current, patterns });
|
|
76240
76246
|
} catch (error) {
|
|
76241
|
-
return emit(io,
|
|
76247
|
+
return emit(io, fail2("unavailable", `cannot write ${file}: ${error.message}`));
|
|
76242
76248
|
}
|
|
76243
76249
|
const changed = action === "add" ? !has : has;
|
|
76244
|
-
return emit(io,
|
|
76250
|
+
return emit(io, ok2({ file, pattern: normalized, changed, patterns }), () => [
|
|
76245
76251
|
action === "add" ? `workit: ${changed ? "added" : "already had"} heavy pattern "${normalized}" (machine-wide, ${file})` : `workit: ${changed ? "removed" : "had no"} heavy pattern "${normalized}"`
|
|
76246
76252
|
]);
|
|
76247
76253
|
}
|
|
76248
76254
|
if (action === "test") {
|
|
76249
76255
|
const command = commandText(rest);
|
|
76250
76256
|
if (!command)
|
|
76251
|
-
return emit(io,
|
|
76257
|
+
return emit(io, fail2("invalid_input", "test needs a command", {
|
|
76252
76258
|
unblock: "workit lock heavy test -- <cmd…>"
|
|
76253
76259
|
}));
|
|
76254
76260
|
const match = heavyCommand(command, { cwd: io.cwd, env: io.env });
|
|
76255
76261
|
const plan = heavyPlan(command, { cwd: io.cwd, env: io.env, rules: null });
|
|
76256
|
-
return emit(io,
|
|
76262
|
+
return emit(io, ok2({
|
|
76257
76263
|
command,
|
|
76258
76264
|
heavy: Boolean(match),
|
|
76259
76265
|
reason: match?.reason ?? null,
|
|
@@ -76262,7 +76268,7 @@ async function heavy(args, io) {
|
|
|
76262
76268
|
split: plan.kind === "split" ? plan.reason : null
|
|
76263
76269
|
}), (data) => !data.heavy ? ["light: the shell hook leaves it alone"] : data.rewrite ? [`heavy (${data.reason}): the shell hook runs it as ${data.rewrite}`] : data.split ? [`heavy (${data.reason}): the shell hook denies the chain: ${data.split}`] : [`heavy (${data.reason}): outside a git checkout the shell hook leaves it alone`]);
|
|
76264
76270
|
}
|
|
76265
|
-
return emit(io,
|
|
76271
|
+
return emit(io, fail2("invalid_input", `unknown lock heavy action ${action ?? "(none)"}`, {
|
|
76266
76272
|
unblock: "workit lock heavy list|add <pattern>|remove <pattern>|test -- <cmd…>"
|
|
76267
76273
|
}));
|
|
76268
76274
|
}
|
|
@@ -76276,7 +76282,7 @@ async function run11(argv, io) {
|
|
|
76276
76282
|
return runHeavy(rest, io);
|
|
76277
76283
|
if (sub === "heavy")
|
|
76278
76284
|
return heavy(rest, io);
|
|
76279
|
-
return emit(io,
|
|
76285
|
+
return emit(io, fail2("invalid_input", `unknown lock subcommand ${sub ?? "(none)"}`, { unblock: USAGE4 }));
|
|
76280
76286
|
}
|
|
76281
76287
|
var USAGE4 = "workit lock status | wait [--timeout <s>] | run [--shell] [--wait <s>] [--timeout <s>] -- <cmd…> | heavy list|add|remove|test", held = (slots) => slots.filter((slot) => slot.holder && !slot.stale), sleep2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms)), commandText = (args) => {
|
|
76282
76288
|
const split = args.indexOf("--");
|
|
@@ -76295,15 +76301,15 @@ async function logTimeUpdate(input, operation = defaultOperations) {
|
|
|
76295
76301
|
try {
|
|
76296
76302
|
const value = await operation.logTime(input);
|
|
76297
76303
|
if (notApplied(value))
|
|
76298
|
-
return
|
|
76304
|
+
return fail(value.error, {
|
|
76299
76305
|
issueId: input.issueId,
|
|
76300
76306
|
loggedMinutes: 0,
|
|
76301
76307
|
outcome: "not_applied",
|
|
76302
76308
|
retry: "youtrack.time"
|
|
76303
76309
|
});
|
|
76304
|
-
return
|
|
76310
|
+
return ok(unwrap(value));
|
|
76305
76311
|
} catch (error) {
|
|
76306
|
-
return
|
|
76312
|
+
return fail(message(error), {
|
|
76307
76313
|
issueId: input.issueId,
|
|
76308
76314
|
loggedMinutes: 0,
|
|
76309
76315
|
outcome: "unknown",
|
|
@@ -82161,7 +82167,7 @@ function renderStatus(doc) {
|
|
|
82161
82167
|
lines.push(`next: ${doc.next}`);
|
|
82162
82168
|
return lines;
|
|
82163
82169
|
}
|
|
82164
|
-
var forgeDeps, MAX_REASON = 500, usage3 = (io, message, line) => emit(io,
|
|
82170
|
+
var forgeDeps, MAX_REASON = 500, usage3 = (io, message, line) => emit(io, fail2("invalid_input", message, { unblock: line })), forgeFail = (io, result, data) => emit(io, fail2(result.code, result.error, { data, unblock: result.unblock })), CONNECT_BUDGET_MS = 15000, pushIdentity = (io, branch) => checkPushIdentity(io.cwd, {
|
|
82165
82171
|
branch,
|
|
82166
82172
|
env: io.env,
|
|
82167
82173
|
runner: forgeDeps.runner,
|
|
@@ -82228,7 +82234,7 @@ async function status2(argv, io) {
|
|
|
82228
82234
|
const doc = report.data.doc;
|
|
82229
82235
|
const hint = nextHint(doc.next, doc.number);
|
|
82230
82236
|
const issues = issuesBlock(io.cwd, doc);
|
|
82231
|
-
return emit(io,
|
|
82237
|
+
return emit(io, ok2({ ...doc, nextHint: hint, verdict: verdictBlock(io.cwd, doc.head.branch, doc), issues }), (data) => {
|
|
82232
82238
|
const lines = renderStatus(data);
|
|
82233
82239
|
if (data.issues?.length)
|
|
82234
82240
|
lines.splice(1, 0, `issues: ${data.issues.map((entry) => `${entry.tracker === "youtrack" ? entry.issue : entry.url ?? `${entry.repo ?? ""}#${entry.issue}`} (${entry.relation})`).join(", ")}`);
|
|
@@ -82312,18 +82318,18 @@ async function create4(argv, io) {
|
|
|
82312
82318
|
const flow = gitFlowOf(io.cwd);
|
|
82313
82319
|
const mismatch = flowMismatch(flow, kind, base, "target");
|
|
82314
82320
|
if (mismatch && flow && kind)
|
|
82315
|
-
return emit(io,
|
|
82321
|
+
return emit(io, fail2("blocked", mismatch, {
|
|
82316
82322
|
unblock: `workit pr create … # without --base it targets ${flowRoute(flow, kind).target}`
|
|
82317
82323
|
}));
|
|
82318
82324
|
} else {
|
|
82319
82325
|
const resolved = vcsConfig("resolve", io.cwd, { track: flags.values.track ?? null });
|
|
82320
82326
|
if (resolved.ok === false)
|
|
82321
|
-
return emit(io,
|
|
82327
|
+
return emit(io, fail2("blocked", String(resolved.error), {
|
|
82322
82328
|
unblock: "fix ~/.config/workit/vcs.json or pass --base <b>"
|
|
82323
82329
|
}));
|
|
82324
82330
|
releaseTrack = resolved.releaseTrack ?? null;
|
|
82325
82331
|
if (releaseTrack?.blocking)
|
|
82326
|
-
return emit(io,
|
|
82332
|
+
return emit(io, fail2("blocked", releaseTrack.blocking, {
|
|
82327
82333
|
unblock: "workit pr create --track <name> … # or --base <branch>"
|
|
82328
82334
|
}));
|
|
82329
82335
|
base = String(resolved.defaultTargetBranch ?? "") || null;
|
|
@@ -82385,7 +82391,7 @@ async function create4(argv, io) {
|
|
|
82385
82391
|
...releaseTrack ? { releaseTrack } : {},
|
|
82386
82392
|
...route ? { flow: route } : {}
|
|
82387
82393
|
};
|
|
82388
|
-
return emit(io,
|
|
82394
|
+
return emit(io, ok2(created), (data) => [
|
|
82389
82395
|
`${data.created ? "opened" : "found open"} ${connected.data.forge.kind === "github" ? "PR #" : "MR !"}${data.number}${data.draft && data.created ? " (draft)" : ""}: ${data.branch} -> ${data.base} ${data.url}`,
|
|
82390
82396
|
...data.releaseTrack?.name ? [`release track: ${data.releaseTrack.name} (${data.releaseTrack.detail})`] : [],
|
|
82391
82397
|
...(data.releaseTrack?.warnings ?? []).map((warning) => `note: ${warning}`),
|
|
@@ -82465,11 +82471,11 @@ async function merge3(argv, io) {
|
|
|
82465
82471
|
...body !== undefined ? { body } : {}
|
|
82466
82472
|
}, forgeDeps.sleep);
|
|
82467
82473
|
if (!result.ok)
|
|
82468
|
-
return emit(io,
|
|
82474
|
+
return emit(io, fail2(result.code, result.error, {
|
|
82469
82475
|
unblock: result.unblock,
|
|
82470
82476
|
data: "refusal" in result && result.refusal ? result.refusal : ("recorded" in result) && result.recorded ? { recorded: result.recorded } : {}
|
|
82471
82477
|
}));
|
|
82472
|
-
return emit(io,
|
|
82478
|
+
return emit(io, ok2(result.data), (data) => [
|
|
82473
82479
|
`merged ${connected.data.forge.kind === "github" ? "PR #" : "MR !"}${data.number} (${data.method}) at head ${data.head.slice(0, 12)}${data.mergeSha ? ` -> ${data.mergeSha.slice(0, 12)}` : ""}`,
|
|
82474
82480
|
data.unverified ? `UNVERIFIED: merged without a verdict (--unverified: ${data.unverified.reason}); ledger ${data.unverified.recorded}` : `verdict ${data.verdict.verdictId ?? "?"} accepted for that head`,
|
|
82475
82481
|
...data.mergeBack.length ? [
|
|
@@ -82499,7 +82505,7 @@ async function ready(argv, io) {
|
|
|
82499
82505
|
if (!result.ok)
|
|
82500
82506
|
return forgeFail(io, result);
|
|
82501
82507
|
const kind = connected.data.forge.kind;
|
|
82502
|
-
return emit(io,
|
|
82508
|
+
return emit(io, ok2(result.data), (data) => [
|
|
82503
82509
|
`${prLabel(kind, data.number)} ${data.changed ? "is now" : "was already"} ${data.draft ? "a draft" : "ready for review"} ${data.url}`
|
|
82504
82510
|
]);
|
|
82505
82511
|
}
|
|
@@ -82544,7 +82550,7 @@ async function edit(argv, io) {
|
|
|
82544
82550
|
if (!result.ok)
|
|
82545
82551
|
return result.code === "invalid_input" ? usage3(io, result.error, EDIT_USAGE) : forgeFail(io, result);
|
|
82546
82552
|
const kind = connected.data.forge.kind;
|
|
82547
|
-
return emit(io,
|
|
82553
|
+
return emit(io, ok2(result.data), (data) => [
|
|
82548
82554
|
`edited ${prLabel(kind, data.number)} (${data.changed.join(", ")}): ${data.title} -> ${data.base} ${data.url}`
|
|
82549
82555
|
]);
|
|
82550
82556
|
}
|
|
@@ -82564,7 +82570,7 @@ async function threads(argv, io) {
|
|
|
82564
82570
|
if (!result.ok)
|
|
82565
82571
|
return forgeFail(io, result);
|
|
82566
82572
|
const kind = connected.data.forge.kind;
|
|
82567
|
-
return emit(io,
|
|
82573
|
+
return emit(io, ok2(result.data), (data) => [
|
|
82568
82574
|
`${prLabel(kind, data.number)}: ${data.threads.length} unresolved thread${data.threads.length === 1 ? "" : "s"}${data.truncated ? " (truncated at the page cap)" : ""}`,
|
|
82569
82575
|
...data.threads.map((thread) => `${thread.id} ${thread.path ? `${thread.path}${thread.line ? `:${thread.line}` : ""} ` : ""}@${thread.author ?? "?"}${thread.isBot ? " (bot)" : ""}${thread.outdated ? " (outdated)" : ""}: ${thread.body}`)
|
|
82570
82576
|
]);
|
|
@@ -82605,7 +82611,7 @@ async function reply(argv, io) {
|
|
|
82605
82611
|
if (!result.ok)
|
|
82606
82612
|
return result.code === "invalid_input" ? usage3(io, result.error, REPLY_USAGE) : forgeFail(io, result);
|
|
82607
82613
|
const kind = connected.data.forge.kind;
|
|
82608
|
-
return emit(io,
|
|
82614
|
+
return emit(io, ok2(result.data), (data) => [
|
|
82609
82615
|
`${[data.replied ? "replied to" : null, data.resolved ? "resolved" : null].filter(Boolean).join(" and ")} thread ${data.thread} on ${prLabel(kind, data.number)}${data.replyUrl ? ` ${data.replyUrl}` : ""}`
|
|
82610
82616
|
]);
|
|
82611
82617
|
}
|
|
@@ -82717,7 +82723,7 @@ async function wait2(argv, io) {
|
|
|
82717
82723
|
}
|
|
82718
82724
|
const elapsedMs = forgeDeps.now() - started;
|
|
82719
82725
|
if (!status)
|
|
82720
|
-
return emit(io,
|
|
82726
|
+
return emit(io, fail2("unavailable", "no successful poll before the timeout", { data: { polls } }));
|
|
82721
82727
|
const left = deadline - forgeDeps.now();
|
|
82722
82728
|
const built = buildStatusDoc(io.cwd, resolved, status, {
|
|
82723
82729
|
logLines: verdict.state === "failed" && left > 0 ? 60 : 0,
|
|
@@ -82741,18 +82747,18 @@ async function wait2(argv, io) {
|
|
|
82741
82747
|
io.stdout(`${value}
|
|
82742
82748
|
`);
|
|
82743
82749
|
if (verdict.state === "ready")
|
|
82744
|
-
return emit(io,
|
|
82750
|
+
return emit(io, ok2(data), () => [
|
|
82745
82751
|
`CI ready (${verdict.reason}) after ${polls} poll${polls === 1 ? "" : "s"}, ${seconds(elapsedMs)}`,
|
|
82746
82752
|
...renderStatus(doc)
|
|
82747
82753
|
]);
|
|
82748
82754
|
if (verdict.state === "failed")
|
|
82749
|
-
return emit(io,
|
|
82755
|
+
return emit(io, fail2("failed", `CI failed: ${doc.checks.failing.map((check) => check.name).join(", ")}`, {
|
|
82750
82756
|
data,
|
|
82751
82757
|
unblock: "fix the failure, or if it is a flake: workit ci rerun --failed --reason flake"
|
|
82752
82758
|
}));
|
|
82753
82759
|
if (verdict.state === "blocked")
|
|
82754
|
-
return emit(io,
|
|
82755
|
-
return emit(io,
|
|
82760
|
+
return emit(io, fail2("blocked", `CI wait blocked: ${verdict.reason}`, { data, unblock: verdict.unblock }));
|
|
82761
|
+
return emit(io, fail2("pending", `CI still ${verdict.reason.replaceAll("_", " ")} after ${seconds(elapsedMs)}`, {
|
|
82756
82762
|
data,
|
|
82757
82763
|
unblock: `workit ci wait --pr ${doc.number}${head ? ` --head ${head}` : ""}`
|
|
82758
82764
|
}));
|
|
@@ -82786,12 +82792,12 @@ async function rerun(argv, io) {
|
|
|
82786
82792
|
return forgeFail(io, connected);
|
|
82787
82793
|
const resolved = connected.data;
|
|
82788
82794
|
if (resolved.expectedAccount && resolved.identity.login === null)
|
|
82789
|
-
return emit(io,
|
|
82795
|
+
return emit(io, fail2("blocked", `identity_unverified: the credential cannot prove it is ${resolved.expectedAccount} (${resolved.identity.note ?? "no /user access"})`, {
|
|
82790
82796
|
unblock: `use a credential for ${resolved.expectedAccount} that can read /user (vcs.tokenFile or ${resolved.forge.kind === "github" ? "gh" : "glab"} auth login --hostname ${resolved.forge.apiHost})`
|
|
82791
82797
|
}));
|
|
82792
82798
|
const grant = requireGrant(io.cwd, "rerun");
|
|
82793
82799
|
if (!grant.allowed)
|
|
82794
|
-
return emit(io,
|
|
82800
|
+
return emit(io, fail2("blocked", grant.error, { unblock: grant.unblock, data: { reason: grant.reason } }));
|
|
82795
82801
|
const number = selectPr(io.cwd, resolved, { pr, branch: flags.values.branch ?? null });
|
|
82796
82802
|
if (!number.ok)
|
|
82797
82803
|
return forgeFail(io, number);
|
|
@@ -82807,7 +82813,7 @@ async function rerun(argv, io) {
|
|
|
82807
82813
|
if (!done.ok)
|
|
82808
82814
|
return forgeFail(io, done);
|
|
82809
82815
|
const outcome = done.data;
|
|
82810
|
-
return emit(io,
|
|
82816
|
+
return emit(io, ok2(outcome), () => [
|
|
82811
82817
|
`rerun requested on #${outcome.pr} head ${outcome.head.slice(0, 7)} (${outcome.reason}${outcome.forced ? ", forced" : ""}): ${outcome.rerun.map((check) => check.name).join(", ")}`,
|
|
82812
82818
|
...outcome.skipped.length ? [`not rerunnable here: ${outcome.skipped.join(", ")}`] : [],
|
|
82813
82819
|
...outcome.recorded ? [] : ["warning: the rerun could not be recorded; the once-per-head guard will not see it"],
|
|
@@ -82906,7 +82912,7 @@ async function branch(argv, io) {
|
|
|
82906
82912
|
});
|
|
82907
82913
|
if (!result.ok)
|
|
82908
82914
|
return forgeFail(io, result);
|
|
82909
|
-
return emit(io,
|
|
82915
|
+
return emit(io, ok2(result.data), (data) => [
|
|
82910
82916
|
`switched to new branch ${data.branch} from ${data.baseRef} (${short2(data.baseSha)})${data.carried ? ", carrying uncommitted changes" : ""}`,
|
|
82911
82917
|
...data.releaseTrack?.name ? [`release track: ${data.releaseTrack.name} (${data.releaseTrack.detail})`] : [],
|
|
82912
82918
|
...data.notes.map((note) => `note: ${note}`)
|
|
@@ -83007,7 +83013,7 @@ async function commit(argv, io) {
|
|
|
83007
83013
|
if (!result.ok)
|
|
83008
83014
|
return forgeFail(io, result);
|
|
83009
83015
|
await ensureImplicitTask(io);
|
|
83010
|
-
return emit(io,
|
|
83016
|
+
return emit(io, ok2(result.data), (data) => [
|
|
83011
83017
|
`${data.branch} ${short2(data.sha)} ${data.message.split(`
|
|
83012
83018
|
`, 1)[0]} (${data.files.length ? `${data.files.length} file${data.files.length === 1 ? "" : "s"}` : "empty commit"})${data.amended ? `, amends ${short2(data.amended)}` : ""}`,
|
|
83013
83019
|
...data.leftDirty ? [`${data.leftDirty} change(s) left uncommitted`] : [],
|
|
@@ -83051,7 +83057,7 @@ async function push(argv, io) {
|
|
|
83051
83057
|
const checked = identity?.data ?? null;
|
|
83052
83058
|
const grant = requireGrant(io.cwd, "push", { forge: checked?.forge != null });
|
|
83053
83059
|
if (!grant.allowed)
|
|
83054
|
-
return emit(io,
|
|
83060
|
+
return emit(io, fail2("blocked", grant.error, {
|
|
83055
83061
|
unblock: grant.unblock,
|
|
83056
83062
|
data: { reason: grant.reason }
|
|
83057
83063
|
}));
|
|
@@ -83074,7 +83080,7 @@ async function push(argv, io) {
|
|
|
83074
83080
|
for (const warning of warnings)
|
|
83075
83081
|
io.stderr(`warning: ${warning}
|
|
83076
83082
|
`);
|
|
83077
|
-
const envelope =
|
|
83083
|
+
const envelope = ok2({ ...result.data, identity: checked });
|
|
83078
83084
|
return emit(io, warnings.length ? { ...envelope, warnings } : envelope, (data) => [
|
|
83079
83085
|
data.pushed ? `pushed ${data.branch} ${short2(data.previous)} -> ${short2(data.sha)} to ${data.remote}${data.forced ? " (force-with-lease)" : ""}; remote tip verified` : `${data.remote}/${data.branch} is already at ${short2(data.sha)}; remote tip verified`,
|
|
83080
83086
|
...data.upstream ? [`upstream: ${data.remote}/${data.branch}`] : []
|
|
@@ -83086,7 +83092,7 @@ async function releasePush(names, io) {
|
|
|
83086
83092
|
return forgeFail(io, plan);
|
|
83087
83093
|
const release = requireGrant(io.cwd, "release");
|
|
83088
83094
|
if (!release.allowed)
|
|
83089
|
-
return emit(io,
|
|
83095
|
+
return emit(io, fail2("blocked", release.error, {
|
|
83090
83096
|
unblock: release.unblock,
|
|
83091
83097
|
data: { reason: release.reason }
|
|
83092
83098
|
}));
|
|
@@ -83097,7 +83103,7 @@ async function releasePush(names, io) {
|
|
|
83097
83103
|
const checked = identity?.data ?? null;
|
|
83098
83104
|
const pushGrant = requireGrant(io.cwd, "push", { forge: checked?.forge != null });
|
|
83099
83105
|
if (!pushGrant.allowed)
|
|
83100
|
-
return emit(io,
|
|
83106
|
+
return emit(io, fail2("blocked", pushGrant.error, {
|
|
83101
83107
|
unblock: pushGrant.unblock,
|
|
83102
83108
|
data: { reason: pushGrant.reason }
|
|
83103
83109
|
}));
|
|
@@ -83108,7 +83114,7 @@ async function releasePush(names, io) {
|
|
|
83108
83114
|
});
|
|
83109
83115
|
if (!result.ok)
|
|
83110
83116
|
return forgeFail(io, result);
|
|
83111
|
-
return emit(io,
|
|
83117
|
+
return emit(io, ok2({ ...result.data, identity: checked }), (data) => [
|
|
83112
83118
|
...data.refs.map((ref) => ref.pushed ? `pushed ${ref.name} ${short2(ref.previous)} -> ${short2(ref.sha)} to ${data.remote}; remote tip verified` : `${data.remote} ${ref.name} is already at ${short2(ref.sha)}; remote tip verified`),
|
|
83113
83119
|
..."error" in data.recorded ? [`ledger: not recorded (${data.recorded.error})`] : []
|
|
83114
83120
|
]);
|
|
@@ -83118,7 +83124,7 @@ function trailers(argv, io) {
|
|
|
83118
83124
|
if (extra !== undefined)
|
|
83119
83125
|
return usage3(io, `unexpected argument ${extra}`, "workit git trailers");
|
|
83120
83126
|
const state = workspaceTrailers(io.cwd);
|
|
83121
|
-
return emit(io,
|
|
83127
|
+
return emit(io, ok2(state), (data) => data.enabled ? "on" : "off");
|
|
83122
83128
|
}
|
|
83123
83129
|
async function run14(argv, io) {
|
|
83124
83130
|
const [sub, ...rest] = argv;
|
|
@@ -83828,7 +83834,7 @@ async function subVerb(load, argv, io) {
|
|
|
83828
83834
|
try {
|
|
83829
83835
|
return JSON.parse(out);
|
|
83830
83836
|
} catch {
|
|
83831
|
-
return
|
|
83837
|
+
return fail2("failed", (out + err).trim() || `${argv.join(" ")} printed nothing`);
|
|
83832
83838
|
}
|
|
83833
83839
|
}
|
|
83834
83840
|
async function start(argv, io) {
|
|
@@ -83845,7 +83851,7 @@ async function start(argv, io) {
|
|
|
83845
83851
|
});
|
|
83846
83852
|
if (!result.ok)
|
|
83847
83853
|
return forgeFail(io, result);
|
|
83848
|
-
return emit(io,
|
|
83854
|
+
return emit(io, ok2(result.data), (data) => [
|
|
83849
83855
|
`started ${data.branch} from ${data.base} (${short4(data.baseSha)}), local only; it will be tagged ${data.tag}`,
|
|
83850
83856
|
`next: commit the version bump, changelog and docs on ${data.branch} (workit git commit), then: workit release finish`,
|
|
83851
83857
|
...data.notes.map((note) => `note: ${note}`)
|
|
@@ -83854,7 +83860,7 @@ async function start(argv, io) {
|
|
|
83854
83860
|
async function releasePr(io, plan, dryRun) {
|
|
83855
83861
|
const title = `chore(release): ${plan.version}`;
|
|
83856
83862
|
if (dryRun)
|
|
83857
|
-
return emit(io,
|
|
83863
|
+
return emit(io, ok2({
|
|
83858
83864
|
...plan,
|
|
83859
83865
|
steps: [`push ${plan.branch}`, `open a PR ${plan.branch} -> ${plan.production}: ${title}`]
|
|
83860
83866
|
}), () => [
|
|
@@ -83881,7 +83887,7 @@ async function releasePr(io, plan, dryRun) {
|
|
|
83881
83887
|
branch: plan.branch,
|
|
83882
83888
|
pr: pr.data.number ?? null
|
|
83883
83889
|
});
|
|
83884
|
-
return emit(io,
|
|
83890
|
+
return emit(io, ok2({ ...plan, pr: pr.data }), () => [
|
|
83885
83891
|
`opened the release PR ${String(pr.data.url ?? "")} into ${plan.production}`,
|
|
83886
83892
|
`next: once it merges, tag the merged commit ${plan.tag} and: workit git push --release ${plan.tag}`
|
|
83887
83893
|
]);
|
|
@@ -83902,7 +83908,7 @@ async function finish2(argv, io) {
|
|
|
83902
83908
|
const plan = planned.data;
|
|
83903
83909
|
if (!plan.gitflow) {
|
|
83904
83910
|
if (!dryRun && plan.state.branchDeleted)
|
|
83905
|
-
return emit(io,
|
|
83911
|
+
return emit(io, fail2("not_found", `${plan.branch} is gone; nothing to open a PR from`));
|
|
83906
83912
|
return releasePr(io, plan, dryRun);
|
|
83907
83913
|
}
|
|
83908
83914
|
const actor = actorFromEnv(io.env);
|
|
@@ -83918,8 +83924,8 @@ async function finish2(argv, io) {
|
|
|
83918
83924
|
const missing = [release, push].find((grant) => !grant.allowed);
|
|
83919
83925
|
const data = { ...plan, steps, grants: { release: release.allowed, push: push.allowed } };
|
|
83920
83926
|
if (missing && !missing.allowed)
|
|
83921
|
-
return emit(io, warned(
|
|
83922
|
-
return emit(io, warned(
|
|
83927
|
+
return emit(io, warned(fail2("blocked", missing.error, { unblock: missing.unblock, data })));
|
|
83928
|
+
return emit(io, warned(ok2(data)), () => [
|
|
83923
83929
|
`finish ${plan.branch} -> ${plan.production} as ${plan.tag}:`,
|
|
83924
83930
|
...steps.map((entry) => ` ${entry.done ? "done" : "todo"} ${entry.step}`)
|
|
83925
83931
|
]);
|
|
@@ -83980,7 +83986,7 @@ async function finish2(argv, io) {
|
|
|
83980
83986
|
if (!verified.ok)
|
|
83981
83987
|
return forgeFail(io, verified, { step: "verify", resume });
|
|
83982
83988
|
if (!verified.data.delivered)
|
|
83983
|
-
return emit(io,
|
|
83989
|
+
return emit(io, fail2("failed", `release_unverified: ${plan.tag} is not on ${plan.remote ?? "the remote"}`, {
|
|
83984
83990
|
data: { step: "verify", resume, report: verified.data },
|
|
83985
83991
|
unblock: resume
|
|
83986
83992
|
}));
|
|
@@ -83989,7 +83995,7 @@ async function finish2(argv, io) {
|
|
|
83989
83995
|
branch: plan.branch,
|
|
83990
83996
|
head: merged.data.tagTarget
|
|
83991
83997
|
});
|
|
83992
|
-
return emit(io, warned(
|
|
83998
|
+
return emit(io, warned(ok2({ ...plan, ran: merged.data.ran, push: pushed.data, forgeRelease, notes })), () => [
|
|
83993
83999
|
`finished ${plan.branch}: ${plan.production} and ${plan.mergeBack.join(", ")} merged, ${plan.tag} tagged on ${short4(merged.data.tagTarget)}`,
|
|
83994
84000
|
`pushed ${[...plan.pushBranches, plan.tag].join(", ")} to ${plan.remote ?? "the remote"}; remote tips verified`,
|
|
83995
84001
|
...forgeRelease ? [
|
|
@@ -84032,7 +84038,7 @@ async function publish(argv, io) {
|
|
|
84032
84038
|
branch: located.data.branch,
|
|
84033
84039
|
head: result.data.sha
|
|
84034
84040
|
});
|
|
84035
|
-
return emit(io,
|
|
84041
|
+
return emit(io, ok2({ ...result.data, version: located.data.version }), (data) => [
|
|
84036
84042
|
`published ${data.branch} (${short4(data.sha)}) to ${data.remote}; remote tip verified`
|
|
84037
84043
|
]);
|
|
84038
84044
|
}
|
|
@@ -84046,7 +84052,7 @@ async function run15(argv, io) {
|
|
|
84046
84052
|
return publish(rest, io);
|
|
84047
84053
|
return usage3(io, sub && !sub.startsWith("-") ? `unknown release subcommand "${sub}"` : "missing release subcommand", USAGE7);
|
|
84048
84054
|
}
|
|
84049
|
-
var START_USAGE = "workit release start <version> [--hotfix] [--track <t>] [--json]", FINISH_USAGE = "workit release finish [<version>] [--track <t>] [--dry-run] [--json]", PUBLISH_USAGE = "workit release publish [<version>] [--json]", USAGE7 = "workit release start|finish|publish ... (workit help release)", short4 = (sha) => sha ? sha.slice(0, 12) : "(none)", blocked = (io, grant) => emit(io,
|
|
84055
|
+
var START_USAGE = "workit release start <version> [--hotfix] [--track <t>] [--json]", FINISH_USAGE = "workit release finish [<version>] [--track <t>] [--dry-run] [--json]", PUBLISH_USAGE = "workit release publish [<version>] [--json]", USAGE7 = "workit release start|finish|publish ... (workit help release)", short4 = (sha) => sha ? sha.slice(0, 12) : "(none)", blocked = (io, grant) => emit(io, fail2("blocked", grant.error, { unblock: grant.unblock, data: { reason: grant.reason } })), isLocalRemote = (cwd, remote) => {
|
|
84050
84056
|
const url = remote ? pushUrl(cwd, remote) : null;
|
|
84051
84057
|
return !url || parseRemoteUrl(url)?.protocol === "file";
|
|
84052
84058
|
}, stepsOf = (plan) => [
|
|
@@ -84128,13 +84134,13 @@ async function run16(argv, io) {
|
|
|
84128
84134
|
return forgeFail(io, result);
|
|
84129
84135
|
const report = result.data;
|
|
84130
84136
|
if (report.delivered)
|
|
84131
|
-
return emit(io,
|
|
84137
|
+
return emit(io, ok2(report), render2);
|
|
84132
84138
|
const failed = report.observations.filter((entry) => !entry.ok);
|
|
84133
84139
|
if (!io.json)
|
|
84134
84140
|
for (const line of render2(report))
|
|
84135
84141
|
io.stdout(`${line}
|
|
84136
84142
|
`);
|
|
84137
|
-
return emit(io,
|
|
84143
|
+
return emit(io, fail2("failed", `not_delivered: ${failed.map((entry) => entry.note ?? `${entry.kind} is ${entry.observed ?? "absent"}, expected ${entry.expected ?? "-"}`).join("; ")}`, {
|
|
84138
84144
|
data: report,
|
|
84139
84145
|
unblock: expect === "pushed" ? "workit git push" : expect === "pr" ? "workit git push && workit pr create --fill" : expect === "merged" ? "workit pr status # then workit pr merge when READY and granted" : "check the release workflow; the tag/package is not published"
|
|
84140
84146
|
}));
|
|
@@ -84185,11 +84191,11 @@ async function plan(argv, io) {
|
|
|
84185
84191
|
if (trunk === null || track !== null) {
|
|
84186
84192
|
const derived = releaseTrunk(io, track, flags.positionals[0] ?? null);
|
|
84187
84193
|
if ("error" in derived)
|
|
84188
|
-
return emit(io,
|
|
84194
|
+
return emit(io, fail2("blocked", derived.error, {
|
|
84189
84195
|
unblock: "workit stack plan --track <name> … # or --trunk <branch>"
|
|
84190
84196
|
}));
|
|
84191
84197
|
if (existing && track !== null && derived.trunk !== existing.trunk)
|
|
84192
|
-
return emit(io,
|
|
84198
|
+
return emit(io, fail2("invalid_input", `stack ${existing.name} is on trunk ${existing.trunk}; --track ${track} targets ${derived.trunk ?? "(none)"}`, { unblock: "drop --track to re-plan on the recorded trunk" }));
|
|
84193
84199
|
trunk ??= derived.trunk ?? "main";
|
|
84194
84200
|
}
|
|
84195
84201
|
const connected = connect(io, flags.positionals[0] ?? null);
|
|
@@ -84205,7 +84211,7 @@ async function plan(argv, io) {
|
|
|
84205
84211
|
});
|
|
84206
84212
|
if (!result.ok)
|
|
84207
84213
|
return stackFailed(io, result);
|
|
84208
|
-
return emit(io,
|
|
84214
|
+
return emit(io, ok2(result.data), (data) => [
|
|
84209
84215
|
`${data.created ? "planned" : "re-planned"} stack ${data.stack.name} on ${data.stack.trunk}:`,
|
|
84210
84216
|
...data.stack.branches.map((entry, index) => {
|
|
84211
84217
|
const check = data.checks.find((item) => item.branch === entry.branch);
|
|
@@ -84229,7 +84235,7 @@ async function status3(argv, io) {
|
|
|
84229
84235
|
const result = stackStatus({ cwd: io.cwd, resolved: connected.data, actor: actorFromEnv(io.env), sleep: forgeDeps.sleep }, selected.data);
|
|
84230
84236
|
if (!result.ok)
|
|
84231
84237
|
return stackFailed(io, result);
|
|
84232
|
-
return emit(io,
|
|
84238
|
+
return emit(io, ok2(result.data), (data) => [
|
|
84233
84239
|
`stack ${data.name} on ${data.trunk}: ${data.verdict}${data.reason ? ` (${data.reason})` : ""}`,
|
|
84234
84240
|
...data.branches.map((row, index) => ` ${index + 1}. ${row.branch} ${label3(connected.data.forge.kind, row.pr)} ${row.merged ? "merged" : `${row.next ?? "?"} · checks ${row.checks ?? "?"} · verdict ${row.verdict.accepted ? `accepted (${row.verdict.basis})` : `missing (${row.verdict.reasons.join(", ") || row.verdict.basis})`} · ${row.onParent === false ? `not on ${row.parent}` : `on ${row.parent}`}${row.baseMatches === false ? ` · PR base ${row.prBase}` : ""}`}`),
|
|
84235
84241
|
...data.next ? [`next: ${data.next}`] : []
|
|
@@ -84279,7 +84285,7 @@ async function sync(argv, io) {
|
|
|
84279
84285
|
});
|
|
84280
84286
|
if (!result.ok)
|
|
84281
84287
|
return stackFailed(io, result);
|
|
84282
|
-
return emit(io,
|
|
84288
|
+
return emit(io, ok2(result.data), renderSync);
|
|
84283
84289
|
}
|
|
84284
84290
|
async function land(argv, io) {
|
|
84285
84291
|
const flags = parseFlags(argv, {
|
|
@@ -84332,7 +84338,7 @@ async function land(argv, io) {
|
|
|
84332
84338
|
if (!result.ok)
|
|
84333
84339
|
return stackFailed(io, result);
|
|
84334
84340
|
const kind = connected.data.forge.kind;
|
|
84335
|
-
return emit(io,
|
|
84341
|
+
return emit(io, ok2(result.data), (data) => [
|
|
84336
84342
|
...data.dryRun ? [
|
|
84337
84343
|
data.wouldLand.length ? `would land: ${data.wouldLand.map((item) => `${label3(kind, item.pr)} (${item.branch})`).join(", ")}` : "would land nothing"
|
|
84338
84344
|
] : [
|
|
@@ -84356,7 +84362,7 @@ async function run17(argv, io) {
|
|
|
84356
84362
|
return land(rest, io);
|
|
84357
84363
|
return usage3(io, sub && !sub.startsWith("-") ? `unknown stack subcommand "${sub}"` : "missing stack subcommand", USAGE9);
|
|
84358
84364
|
}
|
|
84359
|
-
var PLAN_USAGE = "workit stack plan [--name <n>] [--trunk <b> | --track <t>] [<bottom> … <top>] [--json]", STATUS_USAGE2 = "workit stack status [--name <n>] [--json]", SYNC_USAGE = "workit stack sync [--name <n>] [--local] [--dry-run] [--force <branch>]… [--json]", LAND_USAGE = "workit stack land [--name <n>] [--dry-run] [--max <n>] [--method squash|merge|rebase] [--unverified --reason <why>] [--timeout 20m] [--interval 30s] [--json]", USAGE9 = "workit stack plan|status|sync|land ... (workit help stack)", short5 = (sha) => sha ? sha.slice(0, 12) : "?", stackFailed = (io, result) => emit(io,
|
|
84365
|
+
var PLAN_USAGE = "workit stack plan [--name <n>] [--trunk <b> | --track <t>] [<bottom> … <top>] [--json]", STATUS_USAGE2 = "workit stack status [--name <n>] [--json]", SYNC_USAGE = "workit stack sync [--name <n>] [--local] [--dry-run] [--force <branch>]… [--json]", LAND_USAGE = "workit stack land [--name <n>] [--dry-run] [--max <n>] [--method squash|merge|rebase] [--unverified --reason <why>] [--timeout 20m] [--interval 30s] [--json]", USAGE9 = "workit stack plan|status|sync|land ... (workit help stack)", short5 = (sha) => sha ? sha.slice(0, 12) : "?", stackFailed = (io, result) => emit(io, fail2(result.code, result.error, { unblock: result.unblock, data: result.data ?? {} })), label3 = (forge, pr) => pr === null ? "no PR" : `${forge === "gitlab" ? "MR !" : "PR #"}${pr}`, renderSync = (data) => [
|
|
84360
84366
|
`${data.dryRun ? "would sync" : "synced"} stack ${data.name}${data.merged.length ? `; merged: ${data.merged.map((item) => item.branch).join(", ")}` : ""}`,
|
|
84361
84367
|
...data.steps.map((step) => [
|
|
84362
84368
|
` ${step.branch} on ${step.parent}:`,
|
|
@@ -85597,7 +85603,7 @@ function resolveTrunk(io, raw, flag, track) {
|
|
|
85597
85603
|
const derived = releaseTrunk(io, track, null);
|
|
85598
85604
|
if ("error" in derived)
|
|
85599
85605
|
return {
|
|
85600
|
-
code: emit(io,
|
|
85606
|
+
code: emit(io, fail2("blocked", derived.error, {
|
|
85601
85607
|
unblock: "workit fanout plan <plan.json> --track <name> # or --trunk <branch>"
|
|
85602
85608
|
}))
|
|
85603
85609
|
};
|
|
@@ -85643,7 +85649,7 @@ function plan2(argv, io) {
|
|
|
85643
85649
|
renderBlockedPlan(io, result);
|
|
85644
85650
|
return code;
|
|
85645
85651
|
}
|
|
85646
|
-
return emit(io,
|
|
85652
|
+
return emit(io, ok2(result.data), (data) => [
|
|
85647
85653
|
`${data.created ? "planned" : "re-planned"} fanout ${data.name} on ${data.trunk}${data.fanIn === "integration" ? " (integration branch: one PR)" : ""}: ${data.slices.length} slice${data.slices.length === 1 ? "" : "s"}`,
|
|
85648
85654
|
...data.slices.map((slice) => ` ${slice.id} [${slice.tier}] ${slice.branch} <- ${slice.base}${slice.dependsOn.length ? ` after ${slice.dependsOn.join(", ")}` : ""}
|
|
85649
85655
|
worktree ${slice.worktree}`),
|
|
@@ -85678,7 +85684,7 @@ function brief(argv, io) {
|
|
|
85678
85684
|
});
|
|
85679
85685
|
if (!result.ok)
|
|
85680
85686
|
return failed(io, result);
|
|
85681
|
-
return emit(io,
|
|
85687
|
+
return emit(io, ok2(result.data), (data) => data.text.trimEnd());
|
|
85682
85688
|
}
|
|
85683
85689
|
function check2(argv, io) {
|
|
85684
85690
|
const flags = parseFlags(argv, { name: "value", base: "value", offline: "boolean" });
|
|
@@ -85695,13 +85701,13 @@ function check2(argv, io) {
|
|
|
85695
85701
|
if (!result.ok)
|
|
85696
85702
|
return failed(io, result);
|
|
85697
85703
|
if (result.data.ready)
|
|
85698
|
-
return emit(io,
|
|
85704
|
+
return emit(io, ok2(result.data), renderCheck);
|
|
85699
85705
|
if (!io.json)
|
|
85700
85706
|
for (const line of renderCheck(result.data))
|
|
85701
85707
|
io.stdout(`${line}
|
|
85702
85708
|
`);
|
|
85703
85709
|
const first = result.data.slices.find((slice) => slice.status === "blocked");
|
|
85704
|
-
return emit(io,
|
|
85710
|
+
return emit(io, fail2("blocked", `slice ${first?.id ?? "?"} is not ready: ${first?.reasons[0] ?? "blocked"}`, {
|
|
85705
85711
|
data: result.data,
|
|
85706
85712
|
unblock: result.data.next
|
|
85707
85713
|
}));
|
|
@@ -85727,7 +85733,7 @@ function status4(argv, io) {
|
|
|
85727
85733
|
});
|
|
85728
85734
|
if (!result.ok)
|
|
85729
85735
|
return failed(io, result);
|
|
85730
|
-
return emit(io,
|
|
85736
|
+
return emit(io, ok2(result.data), renderStatus2);
|
|
85731
85737
|
}
|
|
85732
85738
|
function worktree(argv, io) {
|
|
85733
85739
|
const [action, ...rest] = argv;
|
|
@@ -85751,7 +85757,7 @@ function worktree(argv, io) {
|
|
|
85751
85757
|
});
|
|
85752
85758
|
if (!result.ok)
|
|
85753
85759
|
return failed(io, result);
|
|
85754
|
-
return emit(io,
|
|
85760
|
+
return emit(io, ok2(result.data), (data) => [
|
|
85755
85761
|
`${data.created ? "created" : "kept"} worktree for slice ${data.slice} (${data.mode}): ${data.path}`,
|
|
85756
85762
|
` branch ${data.branch} <- ${data.base} at ${short6(data.head)}`,
|
|
85757
85763
|
` scratch ${data.scratch} (put it in the worker brief: temp files go here)`,
|
|
@@ -85772,7 +85778,7 @@ function worktree(argv, io) {
|
|
|
85772
85778
|
`);
|
|
85773
85779
|
return code;
|
|
85774
85780
|
}
|
|
85775
|
-
return emit(io,
|
|
85781
|
+
return emit(io, ok2(result.data), (data) => [
|
|
85776
85782
|
data.removed ? `released slice ${data.slice}: removed ${data.path}${data.dirty.length ? ` (dropped ${data.dirty.length} uncommitted change${data.dirty.length === 1 ? "" : "s"}, recorded in the ledger)` : ""}; branch ${data.branch} kept` : `slice ${data.slice}: nothing released`,
|
|
85777
85783
|
...data.notes.map((note) => `note: ${note}`)
|
|
85778
85784
|
]);
|
|
@@ -85791,7 +85797,7 @@ async function run18(argv, io) {
|
|
|
85791
85797
|
return worktree(rest, io);
|
|
85792
85798
|
return usage3(io, sub && !sub.startsWith("-") ? `unknown fanout subcommand "${sub}"` : "missing fanout subcommand", USAGE10);
|
|
85793
85799
|
}
|
|
85794
|
-
var PLAN_USAGE2 = "workit fanout plan <plan.json> [--name <n>] [--trunk <b> | --track <t>] [--take-lead] [--json]", BRIEF_USAGE = "workit fanout brief <slice> [--name <n>] [--mode new|resume] [--attempt <n>] [--json]", CHECK_USAGE = "workit fanout check [<slice>…] [--name <n>] [--base <ref>] [--offline] [--json]", STATUS_USAGE3 = "workit fanout status [--name <n>] [--stuck-after 30m] [--offline] [--json]", WORKTREE_USAGE = "workit fanout worktree create <slice> [--name <n>] | worktree release <slice> [--name <n>] [--force] [--json]", USAGE10 = "workit fanout plan|brief|check|status|worktree ... (workit help fanout)", failed = (io, result) => emit(io,
|
|
85800
|
+
var PLAN_USAGE2 = "workit fanout plan <plan.json> [--name <n>] [--trunk <b> | --track <t>] [--take-lead] [--json]", BRIEF_USAGE = "workit fanout brief <slice> [--name <n>] [--mode new|resume] [--attempt <n>] [--json]", CHECK_USAGE = "workit fanout check [<slice>…] [--name <n>] [--base <ref>] [--offline] [--json]", STATUS_USAGE3 = "workit fanout status [--name <n>] [--stuck-after 30m] [--offline] [--json]", WORKTREE_USAGE = "workit fanout worktree create <slice> [--name <n>] | worktree release <slice> [--name <n>] [--force] [--json]", USAGE10 = "workit fanout plan|brief|check|status|worktree ... (workit help fanout)", failed = (io, result) => emit(io, fail2(result.code, result.error, { unblock: result.unblock, data: result.data ?? {} })), renderCheck = (data) => [
|
|
85795
85801
|
`fanout ${data.name} against ${data.trunkRef}: ${data.ready ? "ready to land" : "blocked"}`,
|
|
85796
85802
|
...data.slices.map((slice) => slice.status === "landed" ? ` -- ${slice.id} (${slice.branch}) landed (${slice.landed?.how}${slice.landed?.pr ? ` #${slice.landed.pr}` : ""})` : ` ${slice.status === "ready" ? "ok " : "x "}${slice.id} (${slice.branch}) ${slice.changed} file${slice.changed === 1 ? "" : "s"} · verdict ${slice.verdict.accepted ? "accepted" : slice.verdict.basis}${slice.reasons.length ? `
|
|
85797
85803
|
${slice.reasons.join(`
|
|
@@ -85914,7 +85920,7 @@ async function run19(argv, io) {
|
|
|
85914
85920
|
if (rest.length)
|
|
85915
85921
|
return usage4(io, `unexpected argument: ${rest[0]}`);
|
|
85916
85922
|
const integrity = ledger.value.integrity ?? { chained: 0, legacy: 0, unverified: [] };
|
|
85917
|
-
return emit(io,
|
|
85923
|
+
return emit(io, ok2({
|
|
85918
85924
|
path: ledger.value.path,
|
|
85919
85925
|
intact: integrity.unverified.length === 0,
|
|
85920
85926
|
chained: integrity.chained,
|
|
@@ -85931,7 +85937,7 @@ async function run19(argv, io) {
|
|
|
85931
85937
|
type: values.type,
|
|
85932
85938
|
last: last ?? 50
|
|
85933
85939
|
});
|
|
85934
|
-
return emit(io,
|
|
85940
|
+
return emit(io, ok2({ path: ledger.value.path, skipped: ledger.value.skipped, rows: listed }), (data) => data.rows.length ? data.rows.map((row) => {
|
|
85935
85941
|
const line = summarizeRow(row);
|
|
85936
85942
|
return `#${line.seq} ${line.at} ${line.type}${line.branch ? ` [${line.branch}]` : ""}${line.labels.length ? ` (${line.labels.join(", ")})` : ""} ${line.summary}`;
|
|
85937
85943
|
}) : "ledger is empty");
|
|
@@ -85945,14 +85951,22 @@ async function run19(argv, io) {
|
|
|
85945
85951
|
return failed2(io, target);
|
|
85946
85952
|
const branch = target.value ?? currentBranch(io.cwd);
|
|
85947
85953
|
if (!branch)
|
|
85948
|
-
return emit(io,
|
|
85954
|
+
return emit(io, fail2("invalid_input", "HEAD is detached; name the branch", {
|
|
85949
85955
|
unblock: "pass --branch <branch>"
|
|
85950
85956
|
}));
|
|
85951
|
-
return emit(io,
|
|
85957
|
+
return emit(io, ok2(checkVerdicts(io.cwd, branch, rows)), verdictLines);
|
|
85952
85958
|
}
|
|
85953
85959
|
const target = targetBranch(io, rows, values.branch, pr);
|
|
85954
85960
|
if (!target.ok)
|
|
85955
85961
|
return failed2(io, target);
|
|
85962
|
+
if (values.head !== undefined) {
|
|
85963
|
+
const actual = target.value === null ? headSha(io.cwd) : resolveRef(io.cwd, target.value);
|
|
85964
|
+
const wanted = values.head.trim().toLowerCase();
|
|
85965
|
+
if (!actual || wanted.length < 4 || !actual.startsWith(wanted))
|
|
85966
|
+
return emit(io, fail2("invalid_input", `--head ${values.head} is not the head of ${target.value ?? "this checkout"}${actual ? ` (${actual.slice(0, 12)})` : ""}`, {
|
|
85967
|
+
unblock: "a verdict is keyed to the branch head: check out the commit to judge (or pass --branch/--pr), or drop --head"
|
|
85968
|
+
}));
|
|
85969
|
+
}
|
|
85956
85970
|
const acting = actorFor(io, values);
|
|
85957
85971
|
if (acting instanceof Error)
|
|
85958
85972
|
return usage4(io, acting.message);
|
|
@@ -85992,7 +86006,7 @@ async function run19(argv, io) {
|
|
|
85992
86006
|
const token = values.token ?? io.env.WORKIT_SESSION_TOKEN ?? null;
|
|
85993
86007
|
const refusal = claimed === null ? null : sessionClaimRefusal(io.env, claimed, io.cwd, { token, flag: acting.source === "flag" });
|
|
85994
86008
|
if (refusal)
|
|
85995
|
-
return emit(io,
|
|
86009
|
+
return emit(io, fail2("blocked", refusal.error, { unblock: refusal.unblock }));
|
|
85996
86010
|
const bound = claimed !== null && issuedTokenMatches(io.cwd, claimed, token);
|
|
85997
86011
|
const verdict = await recorded(recordVerdict({ ...context, ...bound ? { sessionBound: true } : {} }, {
|
|
85998
86012
|
result: rest[0],
|
|
@@ -86031,10 +86045,10 @@ function standingFanout(io, values) {
|
|
|
86031
86045
|
async function standing(io, values, args) {
|
|
86032
86046
|
const [action, ...rest] = args;
|
|
86033
86047
|
if (action !== "add" && action !== "list" && action !== "clear")
|
|
86034
|
-
return emit(io,
|
|
86048
|
+
return emit(io, fail2("invalid_input", action ? `unknown standing action "${action}"` : "missing add, list or clear", { unblock: STANDING_USAGE }));
|
|
86035
86049
|
const target = standingFanout(io, values);
|
|
86036
86050
|
if (target instanceof Error)
|
|
86037
|
-
return emit(io,
|
|
86051
|
+
return emit(io, fail2("invalid_input", target.message, { unblock: STANDING_USAGE }));
|
|
86038
86052
|
const fanout = target.name;
|
|
86039
86053
|
const lead = target.plan?.leadSession ?? null;
|
|
86040
86054
|
const leads = target.plan ? planLeads(target.plan) : null;
|
|
@@ -86049,7 +86063,7 @@ async function standing(io, values, args) {
|
|
|
86049
86063
|
at: row.at,
|
|
86050
86064
|
what: row.what
|
|
86051
86065
|
}));
|
|
86052
|
-
return emit(io,
|
|
86066
|
+
return emit(io, ok2({ fanout, orders }), (data) => data.orders.length ? [
|
|
86053
86067
|
`standing orders for fanout ${fanout}:`,
|
|
86054
86068
|
...data.orders.map((o) => ` ${o.id} ${o.what}`)
|
|
86055
86069
|
] : `no standing orders for fanout ${fanout}`);
|
|
@@ -86063,7 +86077,7 @@ async function standing(io, values, args) {
|
|
|
86063
86077
|
...values.supersedes ? { supersedes: values.supersedes } : {}
|
|
86064
86078
|
};
|
|
86065
86079
|
if (action === "add" && target.plan === null)
|
|
86066
|
-
return emit(io,
|
|
86080
|
+
return emit(io, fail2("not_found", `no fanout plan named ${fanout}`, {
|
|
86067
86081
|
unblock: "workit fanout plan <plan.json> first, or name an existing plan with --fanout"
|
|
86068
86082
|
}));
|
|
86069
86083
|
if (action === "add")
|
|
@@ -86097,7 +86111,7 @@ var USAGE11 = "workit ledger decision|ruling|verdict|standing|list|check ... (wo
|
|
|
86097
86111
|
return;
|
|
86098
86112
|
const parsed = Number(value);
|
|
86099
86113
|
return Number.isInteger(parsed) && parsed > 0 ? parsed : new Error(`${flag} must be a positive integer`);
|
|
86100
|
-
}, failed2 = (io, result) => emit(io,
|
|
86114
|
+
}, failed2 = (io, result) => emit(io, fail2(result.code, result.error, result.unblock ? { unblock: result.unblock } : {})), fromResult = (io, result, human) => result.ok ? emit(io, ok2(result.value), human) : failed2(io, result), usage4 = (io, error) => emit(io, fail2("invalid_input", error, { unblock: USAGE11 })), passedTestOn = (cwd, verdict) => {
|
|
86101
86115
|
const ledger = readLedger(cwd);
|
|
86102
86116
|
return ledger.ok && ledger.value.rows.some((row) => row.type === "check" && row.observer === "workit_cli" && row.name === "test" && row.result === "passed" && row.dirty !== true && row.branch === verdict.branch && row.head === verdict.head);
|
|
86103
86117
|
}, verdictLines = (check) => {
|
|
@@ -86159,6 +86173,7 @@ var init_ledger2 = __esm(() => {
|
|
|
86159
86173
|
evidence: { type: "string", multiple: true },
|
|
86160
86174
|
self: { type: "boolean" },
|
|
86161
86175
|
branch: { type: "string" },
|
|
86176
|
+
head: { type: "string" },
|
|
86162
86177
|
base: { type: "string" },
|
|
86163
86178
|
pr: { type: "string" },
|
|
86164
86179
|
type: { type: "string" },
|
|
@@ -102735,7 +102750,7 @@ function human(data) {
|
|
|
102735
102750
|
async function run20(argv, io) {
|
|
102736
102751
|
const options = parse7(argv);
|
|
102737
102752
|
if (typeof options === "string")
|
|
102738
|
-
return emit(io,
|
|
102753
|
+
return emit(io, fail2("invalid_input", `${options}
|
|
102739
102754
|
usage: ${USAGE12}`));
|
|
102740
102755
|
const top = git7(io.cwd, ["rev-parse", "--show-toplevel"]);
|
|
102741
102756
|
const repo = top.ok ? path59.resolve(top.stdout.trim()) : null;
|
|
@@ -102744,12 +102759,12 @@ usage: ${USAGE12}`));
|
|
|
102744
102759
|
let changed = null;
|
|
102745
102760
|
if (options.diff || options.mutate) {
|
|
102746
102761
|
if (!repo)
|
|
102747
|
-
return emit(io,
|
|
102762
|
+
return emit(io, fail2("unavailable", "--diff and --mutate need a git repository", {
|
|
102748
102763
|
unblock: "run inside a git work tree"
|
|
102749
102764
|
}));
|
|
102750
102765
|
base = resolveBase(io.cwd, options.base);
|
|
102751
102766
|
if (!base)
|
|
102752
|
-
return emit(io,
|
|
102767
|
+
return emit(io, fail2("invalid_input", `cannot resolve a base to diff against${options.base ? `: ${options.base}` : ""}`, {
|
|
102753
102768
|
unblock: "workit test-audit --diff <base-branch-or-sha>"
|
|
102754
102769
|
}));
|
|
102755
102770
|
changed = changedLines(io.cwd, base);
|
|
@@ -102760,7 +102775,7 @@ usage: ${USAGE12}`));
|
|
|
102760
102775
|
else {
|
|
102761
102776
|
const expanded = expandPaths(io.cwd, options.paths);
|
|
102762
102777
|
if (expanded.missing.length > 0)
|
|
102763
|
-
return emit(io,
|
|
102778
|
+
return emit(io, fail2("not_found", `no such path: ${expanded.missing.join(", ")}`));
|
|
102764
102779
|
files = expanded.files;
|
|
102765
102780
|
}
|
|
102766
102781
|
const report = auditFiles(files, display);
|
|
@@ -102778,7 +102793,7 @@ usage: ${USAGE12}`));
|
|
|
102778
102793
|
if (options.mutate && repo && base && changed) {
|
|
102779
102794
|
const runner = testCommand(repo, io.cwd, options.testCmd);
|
|
102780
102795
|
if (!runner)
|
|
102781
|
-
return emit(io,
|
|
102796
|
+
return emit(io, fail2("unavailable", "no test command for --mutate", {
|
|
102782
102797
|
unblock: 'workit test-audit --mutate --test-cmd "<runner> {files}" (or configure a `test` check in .workit/checks.json)'
|
|
102783
102798
|
}));
|
|
102784
102799
|
try {
|
|
@@ -102797,7 +102812,7 @@ usage: ${USAGE12}`));
|
|
|
102797
102812
|
});
|
|
102798
102813
|
} catch (error) {
|
|
102799
102814
|
if (error instanceof BaselineFailed)
|
|
102800
|
-
return emit(io,
|
|
102815
|
+
return emit(io, fail2("failed", error.message, {
|
|
102801
102816
|
data: { command: error.command, tail: error.tail },
|
|
102802
102817
|
unblock: "make the related tests pass before mutating"
|
|
102803
102818
|
}));
|
|
@@ -102818,9 +102833,9 @@ usage: ${USAGE12}`));
|
|
|
102818
102833
|
for (const line of human(data))
|
|
102819
102834
|
io.stdout(`${line}
|
|
102820
102835
|
`);
|
|
102821
|
-
return emit(io,
|
|
102836
|
+
return emit(io, fail2("failed", problems.join("; "), { data }));
|
|
102822
102837
|
}
|
|
102823
|
-
return emit(io,
|
|
102838
|
+
return emit(io, ok2(data), human);
|
|
102824
102839
|
}
|
|
102825
102840
|
var USAGE12 = "workit test-audit [paths…] [--diff [base]] [--rule <ids>] [--min-severity <level>] [--fail-on <level>] [--mutate [--test-cmd <cmd>] [--max-mutants <n>] [--budget <s>] [--timeout <s>]] [--json]", LEVELS, VALUE_FLAGS2, quote = (arg) => /^[\w./@:=+-]+$/.test(arg) ? arg : `'${arg.replace(/'/g, "'\\''")}'`;
|
|
102826
102841
|
var init_test_audit = __esm(() => {
|
|
@@ -102848,16 +102863,16 @@ __export(exports_knowledge, {
|
|
|
102848
102863
|
async function run21(argv, io) {
|
|
102849
102864
|
const [sub, ...rest] = argv.filter((arg) => arg !== "--json");
|
|
102850
102865
|
if (sub !== "lint" || rest.length > 0)
|
|
102851
|
-
return emit(io,
|
|
102866
|
+
return emit(io, fail2("invalid_input", `usage: ${USAGE13}`));
|
|
102852
102867
|
const report = lintKnowledge(checkRoot(io.cwd));
|
|
102853
102868
|
if (report.unreadable.length > 0)
|
|
102854
|
-
return emit(io,
|
|
102869
|
+
return emit(io, fail2("unavailable", `knowledge lint: cannot read ${report.unreadable.join(", ")}`, {
|
|
102855
102870
|
data: report,
|
|
102856
102871
|
unblock: `make ${report.unreadable.join(", ")} readable, then re-run workit knowledge lint`
|
|
102857
102872
|
}));
|
|
102858
102873
|
const summary = `knowledge lint: ${report.findings.length} finding${report.findings.length === 1 ? "" : "s"} in ${report.files.length} file${report.files.length === 1 ? "" : "s"} (${report.files.map((file) => `${file.file} ${file.bytes} B`).join(", ") || "no knowledge files"}; AGENTS.md budget ${report.budget} B)`;
|
|
102859
102874
|
if (io.json)
|
|
102860
|
-
return emit(io, report.findings.length === 0 ?
|
|
102875
|
+
return emit(io, report.findings.length === 0 ? ok2(report) : fail2("failed", summary, { data: report }));
|
|
102861
102876
|
for (const finding of report.findings)
|
|
102862
102877
|
io.stdout(`${finding.file}${finding.line === null ? "" : `:${finding.line}`} [${finding.rule}] ${finding.message}
|
|
102863
102878
|
`);
|
|
@@ -102932,7 +102947,7 @@ async function run22(argv, io) {
|
|
|
102932
102947
|
return usage3(io, "the note is empty", USAGE14);
|
|
102933
102948
|
const missing = step("comment", "comments", { operation: "note", issueId, markdown }, markdown, async (text) => commentResult(await postComment(issueId, text, root))) ?? (minutes ? step("time", "workItems", { operation: "note.time", issueId, markdown, minutes, ...markedDay }, "workit update", (text) => logTimeUpdate({ issueId, minutes, text, dateMs, workspace_root: root })) : null);
|
|
102934
102949
|
if (missing)
|
|
102935
|
-
return emit(io,
|
|
102950
|
+
return emit(io, fail2("unavailable", missing));
|
|
102936
102951
|
} else {
|
|
102937
102952
|
if (!minutes)
|
|
102938
102953
|
return usage3(io, `${sub} needs --minutes <n>`, USAGE14);
|
|
@@ -102941,7 +102956,7 @@ async function run22(argv, io) {
|
|
|
102941
102956
|
const text = flags.values.text ?? "";
|
|
102942
102957
|
const missing = step(sub, "workItems", { operation: sub, issueId, minutes, text, ...markedDay }, text, (marked) => logTimeUpdate({ issueId, minutes, text: marked, dateMs, workspace_root: root }));
|
|
102943
102958
|
if (missing)
|
|
102944
|
-
return emit(io,
|
|
102959
|
+
return emit(io, fail2("unavailable", missing));
|
|
102945
102960
|
}
|
|
102946
102961
|
const results = [];
|
|
102947
102962
|
for (const entry of steps) {
|
|
@@ -102954,14 +102969,14 @@ async function run22(argv, io) {
|
|
|
102954
102969
|
} : {}
|
|
102955
102970
|
});
|
|
102956
102971
|
if (outcome.status === "failed" || outcome.status === "unknown")
|
|
102957
|
-
return emit(io,
|
|
102972
|
+
return emit(io, fail2(outcome.status === "unknown" ? "unavailable" : "failed", outcome.error, {
|
|
102958
102973
|
data: { issueId, steps: results, ...outcome.data ? { detail: outcome.data } : {} },
|
|
102959
102974
|
...outcome.status === "unknown" ? {
|
|
102960
102975
|
unblock: `check ${issueId} in YouTrack; re-running is safe (the marker skips a write that already landed)`
|
|
102961
102976
|
} : {}
|
|
102962
102977
|
}));
|
|
102963
102978
|
}
|
|
102964
|
-
return emit(io,
|
|
102979
|
+
return emit(io, ok2({ issueId, date: date.data.localDate, steps: results }), (data) => [
|
|
102965
102980
|
`${issueId}: ${data.steps.map((entry) => `${entry.step} ${entry.status.replace("_", " ")}`).join(", ")} (${data.date})`,
|
|
102966
102981
|
...data.steps.flatMap((entry) => entry.note ? [` note (${entry.step}): ${entry.note}`] : [])
|
|
102967
102982
|
]);
|
|
@@ -103027,14 +103042,14 @@ async function run23(argv, io) {
|
|
|
103027
103042
|
if (flags.booleans.has("preview")) {
|
|
103028
103043
|
const preview = changelogApplyPreview(input);
|
|
103029
103044
|
if (preview.error)
|
|
103030
|
-
return emit(io,
|
|
103045
|
+
return emit(io, fail2("invalid_input", String(preview.error)));
|
|
103031
103046
|
const { after, ...summary } = preview;
|
|
103032
|
-
return emit(io,
|
|
103047
|
+
return emit(io, ok2({ ...summary, after }), () => [String(after)]);
|
|
103033
103048
|
}
|
|
103034
103049
|
const applied = changelogApply(input);
|
|
103035
103050
|
if (applied.error)
|
|
103036
|
-
return emit(io,
|
|
103037
|
-
return emit(io,
|
|
103051
|
+
return emit(io, fail2("failed", String(applied.error)));
|
|
103052
|
+
return emit(io, ok2(applied), () => [
|
|
103038
103053
|
`changelog updated: ${String(applied.path ?? "CHANGELOG.md")}`
|
|
103039
103054
|
]);
|
|
103040
103055
|
}
|
|
@@ -103099,27 +103114,27 @@ async function resumeBrief(argv, io) {
|
|
|
103099
103114
|
strict: true
|
|
103100
103115
|
}));
|
|
103101
103116
|
} catch (error) {
|
|
103102
|
-
return emit(io,
|
|
103117
|
+
return emit(io, fail2("invalid_input", error.message, { unblock: USAGE16 }));
|
|
103103
103118
|
}
|
|
103104
103119
|
const last = values.last === undefined ? 10 : Number(values.last);
|
|
103105
103120
|
if (!Number.isInteger(last) || last < 1)
|
|
103106
|
-
return emit(io,
|
|
103121
|
+
return emit(io, fail2("invalid_input", "--last must be a positive integer", { unblock: USAGE16 }));
|
|
103107
103122
|
const built = buildHandoff(io.cwd, {
|
|
103108
103123
|
last,
|
|
103109
103124
|
note: values.note ?? null,
|
|
103110
103125
|
next: values.next ?? null
|
|
103111
103126
|
});
|
|
103112
103127
|
if (!built.ok)
|
|
103113
|
-
return emit(io,
|
|
103128
|
+
return emit(io, fail2(built.code, built.error, built.unblock ? { unblock: built.unblock } : {}));
|
|
103114
103129
|
const data = built.value;
|
|
103115
103130
|
let recorded = null;
|
|
103116
103131
|
if (values.record) {
|
|
103117
103132
|
const row = recordHandoff({ cwd: io.cwd, actor: actorFromEnv(io.env), branch: data.branch }, { note: data.note, next: data.next });
|
|
103118
103133
|
if (!row.ok)
|
|
103119
|
-
return emit(io,
|
|
103134
|
+
return emit(io, fail2(row.code, row.error, { data: { ...data, recorded } }));
|
|
103120
103135
|
recorded = row.value.id;
|
|
103121
103136
|
}
|
|
103122
|
-
return emit(io,
|
|
103137
|
+
return emit(io, ok2({ ...data, recorded }), human2);
|
|
103123
103138
|
}
|
|
103124
103139
|
async function run24(argv, io) {
|
|
103125
103140
|
if (!argv.some((arg) => arg === "--task" || arg.startsWith("--task=")))
|
|
@@ -103137,100 +103152,6 @@ var init_handoff = __esm(() => {
|
|
|
103137
103152
|
init_package();
|
|
103138
103153
|
import path62 from "node:path";
|
|
103139
103154
|
|
|
103140
|
-
// packages/workit-cli/src/help.ts
|
|
103141
|
-
var HELP_FLAGS = new Set(["--help", "-h"]);
|
|
103142
|
-
var ESCAPE = "A value that starts with - goes as --flag=value (or after a bare --).";
|
|
103143
|
-
var options = (args) => {
|
|
103144
|
-
const end = args.indexOf("--");
|
|
103145
|
-
return end < 0 ? args : args.slice(0, end);
|
|
103146
|
-
};
|
|
103147
|
-
var wantsHelp = (args) => options(args).some((arg) => HELP_FLAGS.has(arg));
|
|
103148
|
-
var firstWord = (args) => options(args).find((arg) => !arg.startsWith("-"));
|
|
103149
|
-
var valueFlags = (lines) => {
|
|
103150
|
-
const out = new Map;
|
|
103151
|
-
const group = /(?<![\w-])(--?[a-zA-Z][\w-]*(?:\|--?[a-zA-Z][\w-]*)*) (?=[<"a-z0-9])/gu;
|
|
103152
|
-
for (const line of lines)
|
|
103153
|
-
for (const match of line.matchAll(group)) {
|
|
103154
|
-
const names = match[1].split("|");
|
|
103155
|
-
const long = names.find((name) => name.startsWith("--")) ?? names[0];
|
|
103156
|
-
for (const name of names)
|
|
103157
|
-
out.set(name, long);
|
|
103158
|
-
}
|
|
103159
|
-
return out;
|
|
103160
|
-
};
|
|
103161
|
-
function helpAsValue(args, lines) {
|
|
103162
|
-
const before = options(args);
|
|
103163
|
-
const takes = valueFlags(lines);
|
|
103164
|
-
for (let index = 1;index < before.length; index += 1) {
|
|
103165
|
-
const flag = before[index];
|
|
103166
|
-
const long = takes.get(before[index - 1]);
|
|
103167
|
-
if (HELP_FLAGS.has(flag) && long)
|
|
103168
|
-
return `\`${flag}\` looks like the value of ${before[index - 1]}; use ${long}=${flag} or put it after --`;
|
|
103169
|
-
}
|
|
103170
|
-
return null;
|
|
103171
|
-
}
|
|
103172
|
-
function takesPositionals(lines) {
|
|
103173
|
-
const flag = /(?<![\w-])--?[a-zA-Z][\w-]*(?:\|--?[a-zA-Z][\w-]*)*(?:[ =](?!-)(?:<[^>]*>|"[^"]*"|[\w.,@/|=-]+)…?)?/gu;
|
|
103174
|
-
return lines.some((line) => /<|"|\w…|\s…/u.test(line.replace(flag, "")));
|
|
103175
|
-
}
|
|
103176
|
-
var usageLines = (entry) => entry.subcommands?.length ? entry.subcommands.map((sub) => sub.usage) : [entry.usage];
|
|
103177
|
-
var examplesFor = (entry, sub) => (entry.examples ?? []).filter((example) => sub ? new RegExp(`^workit ${entry.name} ${sub.name}(?![\\w-])`, "u").test(example) : true);
|
|
103178
|
-
var exampleBlock = (examples) => examples.length ? ["", "examples:", ...examples.map((line) => ` ${line}`)] : [];
|
|
103179
|
-
var noteBlock = (entry) => (entry.notes ?? []).flatMap((note) => ["", note]);
|
|
103180
|
-
function verbHelp(entry) {
|
|
103181
|
-
const subs = entry.subcommands ?? [];
|
|
103182
|
-
const usages = usageLines(entry);
|
|
103183
|
-
const examples = examplesFor(entry);
|
|
103184
|
-
const text = [
|
|
103185
|
-
...subs.length ? [
|
|
103186
|
-
`workit ${entry.name}: ${entry.summary}`,
|
|
103187
|
-
"",
|
|
103188
|
-
...subs.flatMap((sub) => [`usage: ${sub.usage}`, ` ${sub.summary}`])
|
|
103189
|
-
] : [`usage: ${entry.usage}`, "", entry.summary],
|
|
103190
|
-
...noteBlock(entry),
|
|
103191
|
-
...exampleBlock(examples),
|
|
103192
|
-
"",
|
|
103193
|
-
...subs.length ? [`More: workit help ${entry.name} <${subs.map((sub) => sub.name).join("|")}>`] : [],
|
|
103194
|
-
ESCAPE
|
|
103195
|
-
].join(`
|
|
103196
|
-
`);
|
|
103197
|
-
return {
|
|
103198
|
-
name: entry.name,
|
|
103199
|
-
group: entry.group,
|
|
103200
|
-
usage: usages[0],
|
|
103201
|
-
usages,
|
|
103202
|
-
summary: entry.summary,
|
|
103203
|
-
examples,
|
|
103204
|
-
text
|
|
103205
|
-
};
|
|
103206
|
-
}
|
|
103207
|
-
function subcommandHelp(entry, sub) {
|
|
103208
|
-
const examples = examplesFor(entry, sub);
|
|
103209
|
-
return {
|
|
103210
|
-
name: entry.name,
|
|
103211
|
-
group: entry.group,
|
|
103212
|
-
subcommand: sub.name,
|
|
103213
|
-
usage: sub.usage,
|
|
103214
|
-
usages: [sub.usage],
|
|
103215
|
-
summary: sub.summary,
|
|
103216
|
-
examples,
|
|
103217
|
-
text: [
|
|
103218
|
-
`usage: ${sub.usage}`,
|
|
103219
|
-
"",
|
|
103220
|
-
sub.summary,
|
|
103221
|
-
...noteBlock(entry),
|
|
103222
|
-
...exampleBlock(examples),
|
|
103223
|
-
"",
|
|
103224
|
-
...sub.aliases?.length ? [`aliases: ${sub.aliases.join(", ")}`] : [],
|
|
103225
|
-
ESCAPE
|
|
103226
|
-
].join(`
|
|
103227
|
-
`)
|
|
103228
|
-
};
|
|
103229
|
-
}
|
|
103230
|
-
|
|
103231
|
-
// packages/workit-cli/src/main.ts
|
|
103232
|
-
init_output();
|
|
103233
|
-
|
|
103234
103155
|
// packages/workit-cli/src/verbs/registry.ts
|
|
103235
103156
|
var TASK_FAMILY_NAMES = [
|
|
103236
103157
|
"task",
|
|
@@ -103300,7 +103221,7 @@ var familySubcommands = (name) => {
|
|
|
103300
103221
|
const implicit = name === "task" ? TASK_IMPLICIT : [];
|
|
103301
103222
|
const grammar = Object.entries(FAMILY_ACTIONS[name]).filter(([action]) => !implicit.some((entry) => entry.name === action)).map(([action, summary]) => ({
|
|
103302
103223
|
name: action,
|
|
103303
|
-
usage: name === "policy" && action !== "explain" ? `workit policy ${action} ${POLICY_JUDGE} ${FAMILY_OPTIONS}` : name === "worker" && action !== "assign" ? `workit worker ${action} [<workerId>] ${FAMILY_OPTIONS}` : `workit ${name} ${action} ${FAMILY_OPTIONS}`,
|
|
103224
|
+
usage: name === "task" && action === "list" ? `workit task list [--status all] ${FAMILY_OPTIONS}` : name === "policy" && action !== "explain" ? `workit policy ${action} ${POLICY_JUDGE} ${FAMILY_OPTIONS}` : name === "worker" && action !== "assign" ? `workit worker ${action} [<workerId>] ${FAMILY_OPTIONS}` : `workit ${name} ${action} ${FAMILY_OPTIONS}`,
|
|
103304
103225
|
summary
|
|
103305
103226
|
}));
|
|
103306
103227
|
return [...implicit, ...grammar];
|
|
@@ -103356,6 +103277,7 @@ var VERBS = [
|
|
|
103356
103277
|
{
|
|
103357
103278
|
name: "launch",
|
|
103358
103279
|
group: "setup",
|
|
103280
|
+
passthrough: true,
|
|
103359
103281
|
usage: "workit launch <host> [--auto-upgrade] [-- <host args…>]",
|
|
103360
103282
|
summary: "Upgrade before host startup, then start the host",
|
|
103361
103283
|
load: () => Promise.resolve().then(() => (init_launch(), exports_launch))
|
|
@@ -103410,6 +103332,9 @@ var VERBS = [
|
|
|
103410
103332
|
name: "check",
|
|
103411
103333
|
group: "delivery",
|
|
103412
103334
|
usage: 'workit check <name> [--task <id>] [--base <ref>] [--no-lease --reason "<why>"] | workit check [--name <n>] [--shell] [--timeout <s>] [--task <id>] [--base <ref>] [--heavy [--wait <s>]] [--no-lease --reason "<why>"] -- <cmd…>',
|
|
103335
|
+
flagHints: {
|
|
103336
|
+
list: "workit check <name> runs a configured check; a name that is not configured prints the valid ones (workit check test|lint|typecheck|check)"
|
|
103337
|
+
},
|
|
103413
103338
|
summary: "Run a configured or ad-hoc check and record CLI-observed evidence (exit = the command's); heavy checks wait for the machine-wide heavy-check lease",
|
|
103414
103339
|
examples: [
|
|
103415
103340
|
"workit check test",
|
|
@@ -103468,6 +103393,9 @@ var VERBS = [
|
|
|
103468
103393
|
},
|
|
103469
103394
|
{
|
|
103470
103395
|
name: "create",
|
|
103396
|
+
flagHints: {
|
|
103397
|
+
head: "pr create opens the PR for the current branch: git switch <branch>, then workit pr create (--base sets the target)"
|
|
103398
|
+
},
|
|
103471
103399
|
usage: "workit pr create [--base <b> | --track <t>] (--title <t> [--body <text> | --body-file <f|->] | --fill) [--issue <#n|ID|url>]… [--refs] [--label <l>]… [--reviewer <login>]… [--draft]",
|
|
103472
103400
|
summary: "Open a PR/MR for the pushed branch, verified against the local HEAD, linking its issues"
|
|
103473
103401
|
},
|
|
@@ -103539,6 +103467,7 @@ var VERBS = [
|
|
|
103539
103467
|
},
|
|
103540
103468
|
{
|
|
103541
103469
|
name: "push",
|
|
103470
|
+
deferredFlags: ["force"],
|
|
103542
103471
|
usage: "workit git push [-u|--set-upstream] [--force-with-lease [--expect <sha>] [--overwrite-unintegrated]] [--release <main|develop|v-tag>…]",
|
|
103543
103472
|
summary: "Push the current branch and verify the remote tip (never a blind --force); --release finishes a git-flow release"
|
|
103544
103473
|
},
|
|
@@ -103640,26 +103569,31 @@ var VERBS = [
|
|
|
103640
103569
|
subcommands: [
|
|
103641
103570
|
{
|
|
103642
103571
|
name: "plan",
|
|
103572
|
+
flagAliases: { fanout: "name" },
|
|
103643
103573
|
usage: "workit fanout plan <plan.json> [--name <n>] [--trunk <b> | --track <t>] [--take-lead]",
|
|
103644
103574
|
summary: "Register the slices of a plan file"
|
|
103645
103575
|
},
|
|
103646
103576
|
{
|
|
103647
103577
|
name: "brief",
|
|
103578
|
+
flagAliases: { fanout: "name" },
|
|
103648
103579
|
usage: "workit fanout brief <slice> [--mode new|resume] [--attempt <n>] [--name <n>]",
|
|
103649
103580
|
summary: "Render one worker's brief with the standing orders"
|
|
103650
103581
|
},
|
|
103651
103582
|
{
|
|
103652
103583
|
name: "check",
|
|
103584
|
+
flagAliases: { fanout: "name" },
|
|
103653
103585
|
usage: "workit fanout check [<slice>…] [--name <n>] [--base <ref>] [--offline]",
|
|
103654
103586
|
summary: "Gate fan-in: out-of-scope edits, trunk and sibling merge conflicts"
|
|
103655
103587
|
},
|
|
103656
103588
|
{
|
|
103657
103589
|
name: "status",
|
|
103590
|
+
flagAliases: { fanout: "name" },
|
|
103658
103591
|
usage: "workit fanout status [--name <n>] [--stuck-after 30m] [--offline]",
|
|
103659
103592
|
summary: "Each slice's state: STUCK, PR, CI, verdict, landed, landing order"
|
|
103660
103593
|
},
|
|
103661
103594
|
{
|
|
103662
103595
|
name: "worktree",
|
|
103596
|
+
flagAliases: { fanout: "name" },
|
|
103663
103597
|
usage: "workit fanout worktree create|release <slice> [--name <n>] [--force]",
|
|
103664
103598
|
summary: "Make or release a slice's worktree (--force applies to release only)"
|
|
103665
103599
|
}
|
|
@@ -103673,6 +103607,7 @@ var VERBS = [
|
|
|
103673
103607
|
withSubcommands({
|
|
103674
103608
|
name: "ledger",
|
|
103675
103609
|
group: "delivery",
|
|
103610
|
+
sharedParser: true,
|
|
103676
103611
|
summary: "Record and query decisions, rulings, SHA-keyed verdicts (patch-id carry-over across rebases) and a fanout's standing orders",
|
|
103677
103612
|
subcommands: [
|
|
103678
103613
|
{
|
|
@@ -103687,7 +103622,11 @@ var VERBS = [
|
|
|
103687
103622
|
},
|
|
103688
103623
|
{
|
|
103689
103624
|
name: "verdict",
|
|
103690
|
-
|
|
103625
|
+
flagAliases: { sha: "head" },
|
|
103626
|
+
flagHints: {
|
|
103627
|
+
repo: "a verdict is recorded in the checkout you run it from: cd into the repo or pass --cwd <dir>"
|
|
103628
|
+
},
|
|
103629
|
+
usage: `workit ledger verdict <result> --how "<method/evidence>" [--head <sha>] [--kind unit|live|perf|review] [--base <ref>] [--surface ui|cli|api] [--evidence <ref>]… [--self] ${LEDGER_ACTOR} | ledger verdict [<branch>]`,
|
|
103691
103630
|
summary: "Record a SHA-keyed verdict on the branch head (result: verified, tests-verified, type-check-only, blocked, failed), or show the current verdicts"
|
|
103692
103631
|
},
|
|
103693
103632
|
{
|
|
@@ -103708,6 +103647,7 @@ var VERBS = [
|
|
|
103708
103647
|
},
|
|
103709
103648
|
{
|
|
103710
103649
|
name: "standing",
|
|
103650
|
+
flagAliases: { name: "fanout" },
|
|
103711
103651
|
usage: `workit ledger standing add "<order>" | standing list | standing clear [<id>] [--fanout <name>] [--supersedes <id>] [--session <id> [--token <t>] | --as <role>]`,
|
|
103712
103652
|
summary: "The lead's standing orders for a fanout's workers"
|
|
103713
103653
|
},
|
|
@@ -103791,7 +103731,179 @@ var BY_NAME = new Map(VERBS.map((entry) => [entry.name, entry]));
|
|
|
103791
103731
|
var findVerb = (name) => BY_NAME.get(name);
|
|
103792
103732
|
var findSubcommand = (entry, name) => entry.subcommands?.find((sub) => sub.name === name || sub.aliases?.includes(name));
|
|
103793
103733
|
|
|
103734
|
+
// packages/workit-cli/src/help.ts
|
|
103735
|
+
var HELP_FLAGS = new Set(["--help", "-h"]);
|
|
103736
|
+
var ESCAPE2 = "A value that starts with - goes as --flag=value (or after a bare --).";
|
|
103737
|
+
var options = (args) => {
|
|
103738
|
+
const end = args.indexOf("--");
|
|
103739
|
+
return end < 0 ? args : args.slice(0, end);
|
|
103740
|
+
};
|
|
103741
|
+
var wantsHelp = (args) => options(args).some((arg) => HELP_FLAGS.has(arg));
|
|
103742
|
+
var firstWord = (args) => options(args).find((arg) => !arg.startsWith("-"));
|
|
103743
|
+
var valueFlags = (lines) => {
|
|
103744
|
+
const out = new Map;
|
|
103745
|
+
const group = /(?<![\w-])(--?[a-zA-Z][\w-]*(?:\|--?[a-zA-Z][\w-]*)*) (?=[<"a-z0-9])/gu;
|
|
103746
|
+
for (const line of lines)
|
|
103747
|
+
for (const match of line.matchAll(group)) {
|
|
103748
|
+
const names = match[1].split("|");
|
|
103749
|
+
const long = names.find((name) => name.startsWith("--")) ?? names[0];
|
|
103750
|
+
for (const name of names)
|
|
103751
|
+
out.set(name, long);
|
|
103752
|
+
}
|
|
103753
|
+
return out;
|
|
103754
|
+
};
|
|
103755
|
+
function helpAsValue(args, lines) {
|
|
103756
|
+
const before = options(args);
|
|
103757
|
+
const takes = valueFlags(lines);
|
|
103758
|
+
for (let index = 1;index < before.length; index += 1) {
|
|
103759
|
+
const flag = before[index];
|
|
103760
|
+
const long = takes.get(before[index - 1]);
|
|
103761
|
+
if (HELP_FLAGS.has(flag) && long)
|
|
103762
|
+
return `\`${flag}\` looks like the value of ${before[index - 1]}; use ${long}=${flag} or put it after --`;
|
|
103763
|
+
}
|
|
103764
|
+
return null;
|
|
103765
|
+
}
|
|
103766
|
+
function takesPositionals(lines) {
|
|
103767
|
+
const flag = /(?<![\w-])--?[a-zA-Z][\w-]*(?:\|--?[a-zA-Z][\w-]*)*(?:[ =](?!-)(?:<[^>]*>|"[^"]*"|[\w.,@/|=-]+)…?)?/gu;
|
|
103768
|
+
return lines.some((line) => /<|"|\w…|\s…/u.test(line.replace(flag, "")));
|
|
103769
|
+
}
|
|
103770
|
+
var usageLines = (entry) => entry.subcommands?.length ? entry.subcommands.map((sub) => sub.usage) : [entry.usage];
|
|
103771
|
+
var examplesFor = (entry, sub) => (entry.examples ?? []).filter((example) => sub ? new RegExp(`^workit ${entry.name} ${sub.name}(?![\\w-])`, "u").test(example) : true);
|
|
103772
|
+
var exampleBlock = (examples) => examples.length ? ["", "examples:", ...examples.map((line) => ` ${line}`)] : [];
|
|
103773
|
+
var noteBlock = (entry) => (entry.notes ?? []).flatMap((note) => ["", note]);
|
|
103774
|
+
function verbHelp(entry) {
|
|
103775
|
+
const subs = entry.subcommands ?? [];
|
|
103776
|
+
const usages = usageLines(entry);
|
|
103777
|
+
const examples = examplesFor(entry);
|
|
103778
|
+
const text = [
|
|
103779
|
+
...subs.length ? [
|
|
103780
|
+
`workit ${entry.name}: ${entry.summary}`,
|
|
103781
|
+
"",
|
|
103782
|
+
...subs.flatMap((sub) => [`usage: ${sub.usage}`, ` ${sub.summary}`])
|
|
103783
|
+
] : [`usage: ${entry.usage}`, "", entry.summary],
|
|
103784
|
+
...noteBlock(entry),
|
|
103785
|
+
...exampleBlock(examples),
|
|
103786
|
+
"",
|
|
103787
|
+
...subs.length ? [`More: workit help ${entry.name} <${subs.map((sub) => sub.name).join("|")}>`] : [],
|
|
103788
|
+
ESCAPE2
|
|
103789
|
+
].join(`
|
|
103790
|
+
`);
|
|
103791
|
+
return {
|
|
103792
|
+
name: entry.name,
|
|
103793
|
+
group: entry.group,
|
|
103794
|
+
usage: usages[0],
|
|
103795
|
+
usages,
|
|
103796
|
+
summary: entry.summary,
|
|
103797
|
+
examples,
|
|
103798
|
+
text
|
|
103799
|
+
};
|
|
103800
|
+
}
|
|
103801
|
+
function subcommandHelp(entry, sub) {
|
|
103802
|
+
const examples = examplesFor(entry, sub);
|
|
103803
|
+
return {
|
|
103804
|
+
name: entry.name,
|
|
103805
|
+
group: entry.group,
|
|
103806
|
+
subcommand: sub.name,
|
|
103807
|
+
usage: sub.usage,
|
|
103808
|
+
usages: [sub.usage],
|
|
103809
|
+
summary: sub.summary,
|
|
103810
|
+
examples,
|
|
103811
|
+
text: [
|
|
103812
|
+
`usage: ${sub.usage}`,
|
|
103813
|
+
"",
|
|
103814
|
+
sub.summary,
|
|
103815
|
+
...noteBlock(entry),
|
|
103816
|
+
...exampleBlock(examples),
|
|
103817
|
+
"",
|
|
103818
|
+
...sub.aliases?.length ? [`aliases: ${sub.aliases.join(", ")}`] : [],
|
|
103819
|
+
ESCAPE2
|
|
103820
|
+
].join(`
|
|
103821
|
+
`)
|
|
103822
|
+
};
|
|
103823
|
+
}
|
|
103824
|
+
var distance = (left, right) => {
|
|
103825
|
+
let row = Array.from({ length: right.length + 1 }, (_, index) => index);
|
|
103826
|
+
for (let i = 1;i <= left.length; i += 1) {
|
|
103827
|
+
const next = [i];
|
|
103828
|
+
for (let j = 1;j <= right.length; j += 1)
|
|
103829
|
+
next[j] = Math.min(row[j] + 1, next[j - 1] + 1, row[j - 1] + (left[i - 1] === right[j - 1] ? 0 : 1));
|
|
103830
|
+
row = next;
|
|
103831
|
+
}
|
|
103832
|
+
return row[right.length];
|
|
103833
|
+
};
|
|
103834
|
+
function closest(word, candidates) {
|
|
103835
|
+
let best = null;
|
|
103836
|
+
let bestScore = Infinity;
|
|
103837
|
+
for (const candidate of candidates) {
|
|
103838
|
+
const near = distance(word, candidate);
|
|
103839
|
+
const score = candidate.startsWith(word) || word.startsWith(candidate) ? Math.min(near, 1) : near;
|
|
103840
|
+
if (score < bestScore) {
|
|
103841
|
+
best = candidate;
|
|
103842
|
+
bestScore = score;
|
|
103843
|
+
}
|
|
103844
|
+
}
|
|
103845
|
+
return best !== null && bestScore <= Math.max(2, Math.floor(word.length / 3)) ? best : null;
|
|
103846
|
+
}
|
|
103847
|
+
var COMMAND_HINTS = {
|
|
103848
|
+
status: "workit task status (this branch's task) or workit pr status (its PR); workit handoff prints the whole picture",
|
|
103849
|
+
context: "workit handoff prints the branch, HEAD, dirty state, verdict and next command"
|
|
103850
|
+
};
|
|
103851
|
+
function commandUnblock(command) {
|
|
103852
|
+
const near = closest(command, VERBS.filter((entry) => !entry.planned).map((entry) => entry.name));
|
|
103853
|
+
return COMMAND_HINTS[command] ?? (near ? `did you mean workit ${near}? (workit help)` : "workit help");
|
|
103854
|
+
}
|
|
103855
|
+
var LONG_FLAG = /^--([a-zA-Z][\w-]*)(=|$)/u;
|
|
103856
|
+
var GLOBAL_FLAGS = new Set(["json", "cwd", "help"]);
|
|
103857
|
+
function checkFlags(entry, args) {
|
|
103858
|
+
const word = firstWord(args);
|
|
103859
|
+
const sub = word === undefined ? undefined : findSubcommand(entry, word);
|
|
103860
|
+
const lines = sub && !entry.sharedParser && !/ …/u.test(sub.usage) ? [sub.usage] : usageLines(entry);
|
|
103861
|
+
const takes = valueFlags(lines);
|
|
103862
|
+
const known = new Set;
|
|
103863
|
+
for (const line of lines)
|
|
103864
|
+
for (const match of line.matchAll(/(?<![\w-])--([a-zA-Z][\w-]*)/gu))
|
|
103865
|
+
known.add(match[1]);
|
|
103866
|
+
const aliases = { ...entry.flagAliases, ...sub?.flagAliases };
|
|
103867
|
+
const hints = { ...entry.flagHints, ...sub?.flagHints };
|
|
103868
|
+
for (const flag of sub?.deferredFlags ?? [])
|
|
103869
|
+
known.add(flag);
|
|
103870
|
+
const where = `workit help ${entry.name}${sub ? ` ${sub.name}` : ""}`;
|
|
103871
|
+
const out = [];
|
|
103872
|
+
for (let index = 0;index < args.length; index += 1) {
|
|
103873
|
+
const arg = args[index];
|
|
103874
|
+
if (arg === "--") {
|
|
103875
|
+
out.push(...args.slice(index));
|
|
103876
|
+
break;
|
|
103877
|
+
}
|
|
103878
|
+
if (entry.passthrough && !arg.startsWith("-")) {
|
|
103879
|
+
out.push(...args.slice(index));
|
|
103880
|
+
break;
|
|
103881
|
+
}
|
|
103882
|
+
if (takes.has(arg) && index + 1 < args.length && args[index + 1] !== "--") {
|
|
103883
|
+
out.push(arg, args[index += 1]);
|
|
103884
|
+
continue;
|
|
103885
|
+
}
|
|
103886
|
+
const match = LONG_FLAG.exec(arg);
|
|
103887
|
+
if (!match || GLOBAL_FLAGS.has(match[1]) || known.has(match[1])) {
|
|
103888
|
+
out.push(arg);
|
|
103889
|
+
continue;
|
|
103890
|
+
}
|
|
103891
|
+
const canonical = aliases[match[1]];
|
|
103892
|
+
if (canonical !== undefined) {
|
|
103893
|
+
out.push(`--${canonical}${arg.slice(match[0].length - match[2].length)}`);
|
|
103894
|
+
continue;
|
|
103895
|
+
}
|
|
103896
|
+
const near = closest(match[1], known);
|
|
103897
|
+
return {
|
|
103898
|
+
error: `unknown option --${match[1]}`,
|
|
103899
|
+
unblock: hints[match[1]] ?? (near ? `did you mean --${near}? (${where})` : where)
|
|
103900
|
+
};
|
|
103901
|
+
}
|
|
103902
|
+
return { args: out };
|
|
103903
|
+
}
|
|
103904
|
+
|
|
103794
103905
|
// packages/workit-cli/src/main.ts
|
|
103906
|
+
init_output();
|
|
103795
103907
|
var GROUP_TITLES = {
|
|
103796
103908
|
setup: "Setup",
|
|
103797
103909
|
task: "Task control",
|
|
@@ -103870,11 +103982,11 @@ async function main(argv, overrides = {}, options = {}) {
|
|
|
103870
103982
|
const cwd = path62.resolve(overrides.cwd ?? process.cwd(), parsed.cwd ?? ".");
|
|
103871
103983
|
const io = { ...defaultIo(parsed.json), ...overrides, json: parsed.json, cwd };
|
|
103872
103984
|
if (parsed.error)
|
|
103873
|
-
return emit(io,
|
|
103985
|
+
return emit(io, fail2("invalid_input", parsed.error));
|
|
103874
103986
|
const [command, ...verbArgs] = parsed.rest;
|
|
103875
103987
|
const args = parsed.json && !verbArgs.includes("--json") ? withJsonFlag(verbArgs) : verbArgs;
|
|
103876
103988
|
if (command === "--version" || command === "-v" || command === "version") {
|
|
103877
|
-
return emit(io,
|
|
103989
|
+
return emit(io, ok2({ version: package_default.version }), (data) => data.version);
|
|
103878
103990
|
}
|
|
103879
103991
|
if (command === undefined || command === "help" || command === "--help" || command === "-h") {
|
|
103880
103992
|
const [topic, sub] = command === "help" ? words2(args) : [];
|
|
@@ -103886,12 +103998,12 @@ async function main(argv, overrides = {}, options = {}) {
|
|
|
103886
103998
|
return help(io, verbHelp(entry));
|
|
103887
103999
|
const found = findSubcommand(entry, sub);
|
|
103888
104000
|
if (!found)
|
|
103889
|
-
return emit(io,
|
|
104001
|
+
return emit(io, fail2("invalid_input", `unknown ${topic} subcommand "${sub}"`, {
|
|
103890
104002
|
unblock: `workit help ${topic}`
|
|
103891
104003
|
}));
|
|
103892
104004
|
return help(io, subcommandHelp(entry, found));
|
|
103893
104005
|
}
|
|
103894
|
-
return emit(io,
|
|
104006
|
+
return emit(io, ok2({ version: package_default.version, verbs: listed().map(describe3) }), () => helpText());
|
|
103895
104007
|
}
|
|
103896
104008
|
const entry = findVerb(command);
|
|
103897
104009
|
if (!entry)
|
|
@@ -103901,7 +104013,7 @@ async function main(argv, overrides = {}, options = {}) {
|
|
|
103901
104013
|
const sub = word === undefined ? undefined : findSubcommand(entry, word);
|
|
103902
104014
|
const asValue = helpAsValue(verbArgs, sub ? [sub.usage] : usageLines(entry));
|
|
103903
104015
|
if (asValue)
|
|
103904
|
-
return emit(io,
|
|
104016
|
+
return emit(io, fail2("invalid_input", asValue, {
|
|
103905
104017
|
unblock: `workit help ${entry.name}${sub ? ` ${sub.name}` : ""}`
|
|
103906
104018
|
}));
|
|
103907
104019
|
return help(io, sub ? subcommandHelp(entry, sub) : verbHelp(entry));
|
|
@@ -103909,11 +104021,14 @@ async function main(argv, overrides = {}, options = {}) {
|
|
|
103909
104021
|
const ended = endOfOptions(io, entry, args);
|
|
103910
104022
|
if (typeof ended === "number")
|
|
103911
104023
|
return ended;
|
|
104024
|
+
const checked = checkFlags(entry, ended);
|
|
104025
|
+
if ("error" in checked)
|
|
104026
|
+
return emit(io, fail2("invalid_input", checked.error, { unblock: checked.unblock }));
|
|
103912
104027
|
if (parsed.cwd !== null) {
|
|
103913
104028
|
try {
|
|
103914
104029
|
process.chdir(io.cwd);
|
|
103915
104030
|
} catch {
|
|
103916
|
-
return emit(io,
|
|
104031
|
+
return emit(io, fail2("invalid_input", `--cwd: cannot enter ${io.cwd}`));
|
|
103917
104032
|
}
|
|
103918
104033
|
if (process.env.WORKFLOW_WORKSPACE_ROOT !== undefined) {
|
|
103919
104034
|
process.env.WORKFLOW_WORKSPACE_ROOT = io.cwd;
|
|
@@ -103925,7 +104040,7 @@ async function main(argv, overrides = {}, options = {}) {
|
|
|
103925
104040
|
globalThis[Symbol.for("workit.migrationReporter")] = (report) => io.stderr(`workit: migrated ${report.tasks} task${report.tasks === 1 ? "" : "s"} from ${report.from} to ${report.to} (backup: ${report.backup})
|
|
103926
104041
|
`);
|
|
103927
104042
|
const verb = await entry.load();
|
|
103928
|
-
const runVerb = (target) => guarded(target, () => verb.run(
|
|
104043
|
+
const runVerb = (target) => guarded(target, () => verb.run(checked.args, target));
|
|
103929
104044
|
if (!io.json)
|
|
103930
104045
|
return runVerb(io);
|
|
103931
104046
|
return runJsonPure(io, command, runVerb);
|
|
@@ -103936,7 +104051,7 @@ async function guarded(io, run) {
|
|
|
103936
104051
|
} catch (error) {
|
|
103937
104052
|
if (!(error instanceof Error) || error.name !== "WorkspaceConfigError")
|
|
103938
104053
|
throw error;
|
|
103939
|
-
return emit(io,
|
|
104054
|
+
return emit(io, fail2("blocked", error.message, {
|
|
103940
104055
|
unblock: "fix ~/.config/workit/workspaces.json (workit init → Workspaces)"
|
|
103941
104056
|
}));
|
|
103942
104057
|
}
|
|
@@ -103991,7 +104106,7 @@ async function runJsonPure(io, command, run) {
|
|
|
103991
104106
|
io.stderr(buffered.endsWith(`
|
|
103992
104107
|
`) ? buffered : `${buffered}
|
|
103993
104108
|
`);
|
|
103994
|
-
const envelope = code === 0 ?
|
|
104109
|
+
const envelope = code === 0 ? ok2(text ? { text } : {}) : fail2(CODE_FOR_EXIT[code] ?? "failed", text.split(`
|
|
103995
104110
|
`)[0] || `${command} exited with ${code}`);
|
|
103996
104111
|
io.stdout(`${JSON.stringify(envelope)}
|
|
103997
104112
|
`);
|
|
@@ -104012,17 +104127,17 @@ function endOfOptions(io, entry, args) {
|
|
|
104012
104127
|
if (entry.subcommands?.length && !sub) {
|
|
104013
104128
|
if (entry.optionalSubcommand || word !== undefined)
|
|
104014
104129
|
return args;
|
|
104015
|
-
return emit(io,
|
|
104130
|
+
return emit(io, fail2("invalid_input", `missing ${entry.name} subcommand`, { unblock }));
|
|
104016
104131
|
}
|
|
104017
104132
|
if (takesPositionals(sub ? [sub.usage] : [entry.usage]))
|
|
104018
104133
|
return args;
|
|
104019
104134
|
const extra = args.slice(end + 1);
|
|
104020
104135
|
if (extra.length)
|
|
104021
|
-
return emit(io,
|
|
104136
|
+
return emit(io, fail2("invalid_input", `${entry.name}${sub ? ` ${sub.name}` : ""} takes no positional arguments (got: ${extra.join(" ")})`, { unblock }));
|
|
104022
104137
|
return args.slice(0, end);
|
|
104023
104138
|
}
|
|
104024
104139
|
var words2 = (args) => args.filter((arg) => !arg.startsWith("-"));
|
|
104025
|
-
var help = (io, doc) => emit(io,
|
|
104140
|
+
var help = (io, doc) => emit(io, ok2(doc), (data) => data.text);
|
|
104026
104141
|
var describe3 = (entry) => ({
|
|
104027
104142
|
name: entry.name,
|
|
104028
104143
|
group: entry.group,
|
|
@@ -104031,7 +104146,7 @@ var describe3 = (entry) => ({
|
|
|
104031
104146
|
summary: entry.summary,
|
|
104032
104147
|
...entry.planned ? { planned: entry.planned } : {}
|
|
104033
104148
|
});
|
|
104034
|
-
var unknown2 = (io, command) => emit(io,
|
|
104149
|
+
var unknown2 = (io, command) => emit(io, fail2("invalid_input", `unknown command "${command}"`, { unblock: commandUnblock(command) }));
|
|
104035
104150
|
if (__require.main == __require.module) {
|
|
104036
104151
|
process.exit(await main(process.argv.slice(2), {}, { diagnostics: true }));
|
|
104037
104152
|
}
|