@brainervirus/workit-claude-code 8.0.0 → 8.1.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/.claude-plugin/plugin.json +1 -1
- package/dist/workit-hook.js +47 -46
- package/dist/workit.js +1290 -512
- package/package.json +3 -3
package/dist/workit.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.1.0",
|
|
69
69
|
private: false,
|
|
70
70
|
description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
|
|
71
71
|
keywords: [
|
|
@@ -103,9 +103,9 @@ var init_package = __esm(() => {
|
|
|
103
103
|
},
|
|
104
104
|
dependencies: {
|
|
105
105
|
"@babel/parser": "7.29.9",
|
|
106
|
-
"@brainervirus/workit-core": "^8.
|
|
107
|
-
"@brainervirus/workit-cursor": "^8.
|
|
108
|
-
"@brainervirus/workit-opencode": "^8.
|
|
106
|
+
"@brainervirus/workit-core": "^8.1.0",
|
|
107
|
+
"@brainervirus/workit-cursor": "^8.1.0",
|
|
108
|
+
"@brainervirus/workit-opencode": "^8.1.0",
|
|
109
109
|
"@inkjs/ui": "2.0.0",
|
|
110
110
|
ink: "7.1.1",
|
|
111
111
|
react: "19.2.8"
|
|
@@ -165,7 +165,7 @@ var init_output = __esm(() => {
|
|
|
165
165
|
};
|
|
166
166
|
});
|
|
167
167
|
|
|
168
|
-
// packages/workit-
|
|
168
|
+
// packages/workit-core/src/check-config.ts
|
|
169
169
|
import { spawnSync } from "node:child_process";
|
|
170
170
|
import fs from "node:fs";
|
|
171
171
|
import path from "node:path";
|
|
@@ -7974,7 +7974,7 @@ var init_zod = __esm(() => {
|
|
|
7974
7974
|
init_external();
|
|
7975
7975
|
});
|
|
7976
7976
|
|
|
7977
|
-
// packages/workit-
|
|
7977
|
+
// packages/workit-core/src/core/task-contract.ts
|
|
7978
7978
|
import { createHash, randomUUID } from "node:crypto";
|
|
7979
7979
|
function parseOperation(family, input) {
|
|
7980
7980
|
if (typeof input === "object" && input !== null && "schemaVersion" in input && input.schemaVersion !== SCHEMA_VERSION)
|
|
@@ -8812,7 +8812,7 @@ var init_task_contract = __esm(() => {
|
|
|
8812
8812
|
compiledOperationSchemas = Object.fromEntries(OPERATION_FAMILIES.map((family) => [family, compile(operationSchemas[family])]));
|
|
8813
8813
|
});
|
|
8814
8814
|
|
|
8815
|
-
// packages/workit-
|
|
8815
|
+
// packages/workit-core/src/core/operation-input.ts
|
|
8816
8816
|
function normalizeOperationInput(family, input, host) {
|
|
8817
8817
|
if (!isObject2(input))
|
|
8818
8818
|
return input;
|
|
@@ -9149,7 +9149,7 @@ var init_operation_input = __esm(() => {
|
|
|
9149
9149
|
]);
|
|
9150
9150
|
});
|
|
9151
9151
|
|
|
9152
|
-
// packages/workit-
|
|
9152
|
+
// packages/workit-core/src/core/policy/judgment.ts
|
|
9153
9153
|
function normalizeJudgment(raw, previous) {
|
|
9154
9154
|
const input = isObject3(raw) ? raw : {};
|
|
9155
9155
|
const legacy = Object.keys(input).some((key) => LEGACY_KEYS.has(key));
|
|
@@ -9914,7 +9914,7 @@ var init_file_lock = __esm(() => {
|
|
|
9914
9914
|
init_file_lock_sync();
|
|
9915
9915
|
});
|
|
9916
9916
|
|
|
9917
|
-
// packages/workit-
|
|
9917
|
+
// packages/workit-core/src/core/package-root.ts
|
|
9918
9918
|
import { existsSync } from "node:fs";
|
|
9919
9919
|
import path4 from "node:path";
|
|
9920
9920
|
import { fileURLToPath } from "node:url";
|
|
@@ -9933,7 +9933,7 @@ var packageRoot = () => {
|
|
|
9933
9933
|
};
|
|
9934
9934
|
var init_package_root = () => {};
|
|
9935
9935
|
|
|
9936
|
-
// packages/workit-
|
|
9936
|
+
// packages/workit-core/src/store/paths.ts
|
|
9937
9937
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
9938
9938
|
import { createHash as createHash2 } from "node:crypto";
|
|
9939
9939
|
import fs5 from "node:fs";
|
|
@@ -10209,7 +10209,7 @@ var init_paths = __esm(() => {
|
|
|
10209
10209
|
];
|
|
10210
10210
|
});
|
|
10211
10211
|
|
|
10212
|
-
// packages/workit-
|
|
10212
|
+
// packages/workit-core/src/core/store-lock.ts
|
|
10213
10213
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
10214
10214
|
import fs6 from "node:fs";
|
|
10215
10215
|
import { hostname } from "node:os";
|
|
@@ -10401,7 +10401,7 @@ var init_store_lock = __esm(() => {
|
|
|
10401
10401
|
FOREIGN_LOCK_TTL_MS = 10 * 60000;
|
|
10402
10402
|
});
|
|
10403
10403
|
|
|
10404
|
-
// packages/workit-
|
|
10404
|
+
// packages/workit-core/src/store/event-log.ts
|
|
10405
10405
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
10406
10406
|
import fs7 from "node:fs";
|
|
10407
10407
|
import path7 from "node:path";
|
|
@@ -10556,7 +10556,7 @@ var init_event_log = __esm(() => {
|
|
|
10556
10556
|
TRANSIENT_WINDOWS_CODES = new Set(["EPERM", "EACCES", "EBUSY"]);
|
|
10557
10557
|
});
|
|
10558
10558
|
|
|
10559
|
-
// packages/workit-
|
|
10559
|
+
// packages/workit-core/src/store/patch.ts
|
|
10560
10560
|
function diff(before, after, path = []) {
|
|
10561
10561
|
if (equal(before, after))
|
|
10562
10562
|
return [];
|
|
@@ -10662,7 +10662,7 @@ var isPlainObject2 = (value) => typeof value === "object" && value !== null && !
|
|
|
10662
10662
|
return false;
|
|
10663
10663
|
});
|
|
10664
10664
|
|
|
10665
|
-
// packages/workit-
|
|
10665
|
+
// packages/workit-core/src/store/reduce.ts
|
|
10666
10666
|
import { createHash as createHash3 } from "node:crypto";
|
|
10667
10667
|
function reduce(state, event, blobs) {
|
|
10668
10668
|
const data = event.data;
|
|
@@ -10788,7 +10788,7 @@ var init_reduce = __esm(() => {
|
|
|
10788
10788
|
]);
|
|
10789
10789
|
});
|
|
10790
10790
|
|
|
10791
|
-
// packages/workit-
|
|
10791
|
+
// packages/workit-core/src/store/notes.ts
|
|
10792
10792
|
var SLOT, reportMigration = (report) => {
|
|
10793
10793
|
try {
|
|
10794
10794
|
const reporter = globalThis[SLOT];
|
|
@@ -10800,7 +10800,7 @@ var init_notes = __esm(() => {
|
|
|
10800
10800
|
SLOT = Symbol.for("workit.migrationReporter");
|
|
10801
10801
|
});
|
|
10802
10802
|
|
|
10803
|
-
// packages/workit-
|
|
10803
|
+
// packages/workit-core/src/core/task-store.ts
|
|
10804
10804
|
import { createHash as createHash4, randomUUID as randomUUID3 } from "node:crypto";
|
|
10805
10805
|
import * as fs8 from "node:fs";
|
|
10806
10806
|
import path8 from "node:path";
|
|
@@ -12427,13 +12427,13 @@ var init_task_store = __esm(() => {
|
|
|
12427
12427
|
heldInProcess = new Map;
|
|
12428
12428
|
});
|
|
12429
12429
|
|
|
12430
|
-
// packages/workit-
|
|
12430
|
+
// packages/workit-core/src/core/workers.ts
|
|
12431
12431
|
var UNCERTAIN_WORKER_STATES, isUncertainWorker = (state) => UNCERTAIN_WORKER_STATES.includes(state), workerBlocksTransition = (transition, state) => transition === "pause" ? false : isUncertainWorker(state);
|
|
12432
12432
|
var init_workers = __esm(() => {
|
|
12433
12433
|
UNCERTAIN_WORKER_STATES = ["dispatching", "running", "cancelling", "unknown"];
|
|
12434
12434
|
});
|
|
12435
12435
|
|
|
12436
|
-
// packages/workit-
|
|
12436
|
+
// packages/workit-core/src/git/rev.ts
|
|
12437
12437
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
12438
12438
|
import { createHash as createHash5 } from "node:crypto";
|
|
12439
12439
|
import fs9 from "node:fs";
|
|
@@ -12964,7 +12964,7 @@ var init_rev = __esm(() => {
|
|
|
12964
12964
|
};
|
|
12965
12965
|
});
|
|
12966
12966
|
|
|
12967
|
-
// packages/workit-
|
|
12967
|
+
// packages/workit-core/src/ledger.ts
|
|
12968
12968
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
12969
12969
|
import { createHash as createHash6, randomBytes as randomBytes2 } from "node:crypto";
|
|
12970
12970
|
import fs10 from "node:fs";
|
|
@@ -13267,7 +13267,7 @@ function authorSessions(cwd, rows, branch, range = { base: null, head: null }) {
|
|
|
13267
13267
|
sessions.add(session);
|
|
13268
13268
|
return sessions;
|
|
13269
13269
|
}
|
|
13270
|
-
function effectiveOf(rows, authors) {
|
|
13270
|
+
function effectiveOf(rows, authors, sameCode) {
|
|
13271
13271
|
let effective = null;
|
|
13272
13272
|
for (const row of rows) {
|
|
13273
13273
|
if (!effective) {
|
|
@@ -13278,7 +13278,7 @@ function effectiveOf(rows, authors) {
|
|
|
13278
13278
|
const effIndependent = independenceReasons(effective, authors).length === 0;
|
|
13279
13279
|
if (effIndependent && !rowIndependent)
|
|
13280
13280
|
continue;
|
|
13281
|
-
if (effIndependent && FAILING.has(String(effective.result)) && row.actor.session === effective.actor.session)
|
|
13281
|
+
if (effIndependent && FAILING.has(String(effective.result)) && row.actor.session === effective.actor.session && sameCode(effective, row))
|
|
13282
13282
|
continue;
|
|
13283
13283
|
effective = row;
|
|
13284
13284
|
}
|
|
@@ -13309,16 +13309,22 @@ function checkVerdicts(cwd, branch, rows) {
|
|
|
13309
13309
|
const head = branchHead(cwd, branch);
|
|
13310
13310
|
const fallbackBase = defaultBase(cwd);
|
|
13311
13311
|
const keyCache = new Map;
|
|
13312
|
-
const
|
|
13313
|
-
if (!base || !
|
|
13312
|
+
const keysAt = (base, at) => {
|
|
13313
|
+
if (!base || !at)
|
|
13314
13314
|
return { patchId: null, diffHash: null };
|
|
13315
|
-
|
|
13315
|
+
const cacheKey = `${base}\x00${at}`;
|
|
13316
|
+
let key = keyCache.get(cacheKey);
|
|
13316
13317
|
if (!key) {
|
|
13317
|
-
key = { patchId: patchId(cwd, base,
|
|
13318
|
-
keyCache.set(
|
|
13318
|
+
key = { patchId: patchId(cwd, base, at), diffHash: diffHash(cwd, base, at) };
|
|
13319
|
+
keyCache.set(cacheKey, key);
|
|
13319
13320
|
}
|
|
13320
13321
|
return key;
|
|
13321
13322
|
};
|
|
13323
|
+
const keyFor = (base) => keysAt(base, head);
|
|
13324
|
+
const sameCode = (failed, row) => verdictBasis(failed, {
|
|
13325
|
+
head: row.head,
|
|
13326
|
+
...keysAt(failed.base ?? fallbackBase, row.head)
|
|
13327
|
+
}) !== "stale" || restackCarries(rows, branch, failed.head, row.head);
|
|
13322
13328
|
const authors = authorSessions(cwd, rows, branch, { base: fallbackBase, head });
|
|
13323
13329
|
const byKind = new Map;
|
|
13324
13330
|
for (const row of rows)
|
|
@@ -13328,7 +13334,7 @@ function checkVerdicts(cwd, branch, rows) {
|
|
|
13328
13334
|
}
|
|
13329
13335
|
const verdicts = [];
|
|
13330
13336
|
for (const [kind, list] of byKind) {
|
|
13331
|
-
const row = effectiveOf(list, authors);
|
|
13337
|
+
const row = effectiveOf(list, authors, sameCode);
|
|
13332
13338
|
if (!row)
|
|
13333
13339
|
continue;
|
|
13334
13340
|
let basis = verdictBasis(row, { head, ...keyFor(row.base ?? fallbackBase) });
|
|
@@ -13354,11 +13360,11 @@ function checkVerdicts(cwd, branch, rows) {
|
|
|
13354
13360
|
verdicts.sort((a, b) => a.verdict.seq - b.verdict.seq);
|
|
13355
13361
|
const newestCurrent = verdicts.findLast((entry) => entry.current) ?? verdicts.at(-1) ?? null;
|
|
13356
13362
|
const failing = verdicts.find((entry) => entry.current && entry.independent && FAILING.has(String(entry.verdict.result)));
|
|
13357
|
-
const newestAccepted = verdicts.findLast((entry) => entry.accepted) ?? null;
|
|
13363
|
+
const newestAccepted = verdicts.findLast((entry) => entry.accepted && STRONG_RESULTS.has(String(entry.verdict.result))) ?? null;
|
|
13358
13364
|
const accepted = newestAccepted && !failing ? { accepted: true, verdict: newestAccepted.verdict, reasons: [] } : {
|
|
13359
13365
|
accepted: false,
|
|
13360
13366
|
verdict: failing?.verdict ?? null,
|
|
13361
|
-
reasons: failing ? ["failing_verdict"] : newestCurrent
|
|
13367
|
+
reasons: failing ? ["failing_verdict"] : !newestCurrent ? ["no_verdict"] : newestCurrent.reasons.length ? newestCurrent.reasons : ["type_check_only"]
|
|
13362
13368
|
};
|
|
13363
13369
|
const selfEntry = failing ? undefined : verdicts.findLast((entry) => entry.current && !entry.independent && STRONG_RESULTS.has(String(entry.verdict.result)));
|
|
13364
13370
|
return {
|
|
@@ -13587,6 +13593,9 @@ function summarizeRow(row) {
|
|
|
13587
13593
|
case "pr.merged":
|
|
13588
13594
|
summary = `#${row.pr ?? "?"} ${text("method")} at ${(row.head ?? "?").slice(0, 12)}${text("mergeSha") ? ` -> ${text("mergeSha").slice(0, 12)}` : ""}`;
|
|
13589
13595
|
break;
|
|
13596
|
+
case "merge.unverified":
|
|
13597
|
+
summary = `#${row.pr ?? "?"} unverified merge requested at ${(row.head ?? "?").slice(0, 12)} (reason: ${text("reason")})`;
|
|
13598
|
+
break;
|
|
13590
13599
|
case "delivery.verified":
|
|
13591
13600
|
summary = `${text("expect")} delivered at ${(row.head ?? "?").slice(0, 12)}`;
|
|
13592
13601
|
break;
|
|
@@ -13911,10 +13920,10 @@ var init_ledger = __esm(() => {
|
|
|
13911
13920
|
return false;
|
|
13912
13921
|
}
|
|
13913
13922
|
};
|
|
13914
|
-
OBSERVED_ONLY = new Set(["check", ...PR_ROW_TYPES]);
|
|
13923
|
+
OBSERVED_ONLY = new Set(["check", "merge.unverified", ...PR_ROW_TYPES]);
|
|
13915
13924
|
});
|
|
13916
13925
|
|
|
13917
|
-
// packages/workit-
|
|
13926
|
+
// packages/workit-core/src/core/policy/derive.ts
|
|
13918
13927
|
import { existsSync as existsSync3 } from "node:fs";
|
|
13919
13928
|
import path11 from "node:path";
|
|
13920
13929
|
function deriveRequirements(judgment, scope, constraints, verification = "self") {
|
|
@@ -14102,7 +14111,7 @@ var init_derive = __esm(() => {
|
|
|
14102
14111
|
};
|
|
14103
14112
|
});
|
|
14104
14113
|
|
|
14105
|
-
// packages/workit-
|
|
14114
|
+
// packages/workit-core/src/core/task-evaluation.ts
|
|
14106
14115
|
import { createHash as createHash7 } from "node:crypto";
|
|
14107
14116
|
import * as fs11 from "node:fs";
|
|
14108
14117
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
@@ -14750,7 +14759,7 @@ var init_task_evaluation = __esm(() => {
|
|
|
14750
14759
|
scopeCovers2 = scopeCovers;
|
|
14751
14760
|
});
|
|
14752
14761
|
|
|
14753
|
-
// packages/workit-
|
|
14762
|
+
// packages/workit-core/src/core/methods.ts
|
|
14754
14763
|
function selectMethods(policy, capabilities) {
|
|
14755
14764
|
return Object.entries(METHODS).flatMap(([id, definition]) => {
|
|
14756
14765
|
const requirements = policy.requirements.filter((requirement) => methodMatches(definition, requirement));
|
|
@@ -14797,7 +14806,7 @@ var init_methods = __esm(() => {
|
|
|
14797
14806
|
};
|
|
14798
14807
|
});
|
|
14799
14808
|
|
|
14800
|
-
// packages/workit-
|
|
14809
|
+
// packages/workit-core/src/core/task-context.ts
|
|
14801
14810
|
function reconcileResume(view, observations = []) {
|
|
14802
14811
|
if (observations.length > 0)
|
|
14803
14812
|
return failure2("permission_denied", "worker observations require native host verification");
|
|
@@ -14910,61 +14919,7 @@ var init_task_context = __esm(() => {
|
|
|
14910
14919
|
privateKey = /-----BEGIN [^-]*PRIVATE KEY-----[\s\S]*?-----END [^-]*PRIVATE KEY-----/gi;
|
|
14911
14920
|
});
|
|
14912
14921
|
|
|
14913
|
-
// packages/workit-
|
|
14914
|
-
var CONVENTIONAL_RE, TICKET_RE, GITMOJI_RE, matchCommitFlavor = (message, flavor, pattern) => {
|
|
14915
|
-
const subject = message.split(`
|
|
14916
|
-
`, 1)[0] ?? "";
|
|
14917
|
-
switch (flavor) {
|
|
14918
|
-
case "conventional":
|
|
14919
|
-
return CONVENTIONAL_RE.test(subject);
|
|
14920
|
-
case "gitmoji":
|
|
14921
|
-
return GITMOJI_RE.test(subject);
|
|
14922
|
-
case "ticket-prefix":
|
|
14923
|
-
return TICKET_RE.test(subject);
|
|
14924
|
-
case "freeform":
|
|
14925
|
-
return subject.trim().length > 0;
|
|
14926
|
-
case "custom":
|
|
14927
|
-
if (!pattern)
|
|
14928
|
-
return false;
|
|
14929
|
-
try {
|
|
14930
|
-
return new RegExp(pattern).test(subject);
|
|
14931
|
-
} catch {
|
|
14932
|
-
return false;
|
|
14933
|
-
}
|
|
14934
|
-
case "auto":
|
|
14935
|
-
return subject.trim().length > 0;
|
|
14936
|
-
}
|
|
14937
|
-
}, DETECTABLE, detectCommitFlavor = (subjects, threshold = 0.7) => {
|
|
14938
|
-
if (subjects.length === 0)
|
|
14939
|
-
return { flavor: null, confidence: 0 };
|
|
14940
|
-
const votes = new Map;
|
|
14941
|
-
for (const subject of subjects) {
|
|
14942
|
-
const hit = DETECTABLE.find((flavor) => matchCommitFlavor(subject, flavor));
|
|
14943
|
-
if (hit)
|
|
14944
|
-
votes.set(hit, (votes.get(hit) ?? 0) + 1);
|
|
14945
|
-
}
|
|
14946
|
-
let best = null;
|
|
14947
|
-
let count = 0;
|
|
14948
|
-
for (const [flavor, votesFor] of votes) {
|
|
14949
|
-
if (votesFor > count) {
|
|
14950
|
-
best = flavor;
|
|
14951
|
-
count = votesFor;
|
|
14952
|
-
}
|
|
14953
|
-
}
|
|
14954
|
-
const confidence = count / subjects.length;
|
|
14955
|
-
return best !== null && confidence >= threshold ? { flavor: best, confidence } : { flavor: null, confidence };
|
|
14956
|
-
};
|
|
14957
|
-
var init_commit_flavors = __esm(() => {
|
|
14958
|
-
CONVENTIONAL_RE = /^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?(!)?: .+/;
|
|
14959
|
-
TICKET_RE = /^[A-Z]{2,}-\d+\b/;
|
|
14960
|
-
GITMOJI_RE = /^\p{Extended_Pictographic}/u;
|
|
14961
|
-
DETECTABLE = ["conventional", "gitmoji", "ticket-prefix"];
|
|
14962
|
-
});
|
|
14963
|
-
|
|
14964
|
-
// packages/workit-cli/node_modules/@brainervirus/workit-core/src/core/git.ts
|
|
14965
|
-
var init_git = () => {};
|
|
14966
|
-
|
|
14967
|
-
// packages/workit-cli/node_modules/@brainervirus/workit-core/src/core/boundary.ts
|
|
14922
|
+
// packages/workit-core/src/core/boundary.ts
|
|
14968
14923
|
var EVENT, errorDetail = (err) => {
|
|
14969
14924
|
if (err instanceof Error) {
|
|
14970
14925
|
return { error_name: err.name, error: err.message };
|
|
@@ -14987,7 +14942,7 @@ var init_boundary = __esm(() => {
|
|
|
14987
14942
|
};
|
|
14988
14943
|
});
|
|
14989
14944
|
|
|
14990
|
-
// packages/workit-
|
|
14945
|
+
// packages/workit-core/src/core/config.ts
|
|
14991
14946
|
import {
|
|
14992
14947
|
copyFileSync as copyFileSync2,
|
|
14993
14948
|
cpSync as cpSync2,
|
|
@@ -15048,7 +15003,7 @@ var diagnosticLogger, setDiagnosticLogger = (logger) => {
|
|
|
15048
15003
|
if (!migrationFailed)
|
|
15049
15004
|
migratedDir = dir;
|
|
15050
15005
|
return dir;
|
|
15051
|
-
}, configDir = () => ensureConfigDir(), LOCALE_RE, DEFAULTS, readSafe = (p) => {
|
|
15006
|
+
}, configDir = () => ensureConfigDir(), LOCALE_RE, DEFAULTS, unchosenBranchPolicy, readSafe = (p) => {
|
|
15052
15007
|
try {
|
|
15053
15008
|
return readFileSync3(p, "utf8");
|
|
15054
15009
|
} catch {
|
|
@@ -15070,22 +15025,21 @@ var diagnosticLogger, setDiagnosticLogger = (logger) => {
|
|
|
15070
15025
|
const locale = LOCALE_RE.test(String(input.locale ?? "")) ? input.locale : DEFAULTS.locale;
|
|
15071
15026
|
const preset = Object.hasOwn(PRESETS, input.branchPolicy?.preset) ? input.branchPolicy?.preset : "gitflow";
|
|
15072
15027
|
const commitPreset = COMMIT_PRESETS.includes(String(input.commitPolicy?.preset ?? "")) ? input.commitPolicy?.preset : "conventional";
|
|
15073
|
-
|
|
15074
|
-
|
|
15075
|
-
|
|
15076
|
-
|
|
15077
|
-
|
|
15078
|
-
|
|
15079
|
-
|
|
15080
|
-
|
|
15081
|
-
|
|
15082
|
-
}
|
|
15083
|
-
commitPolicy: {
|
|
15084
|
-
preset: commitPreset,
|
|
15085
|
-
...typeof input.commitPolicy?.pattern === "string" ? { pattern: input.commitPolicy.pattern } : {}
|
|
15086
|
-
}
|
|
15028
|
+
const config = {
|
|
15029
|
+
locale,
|
|
15030
|
+
localeOptions: Array.isArray(input.localeOptions) ? input.localeOptions : DEFAULTS.localeOptions,
|
|
15031
|
+
branchPolicy: mergePreset(preset, {
|
|
15032
|
+
allowed: Array.isArray(input.branchPolicy?.allowed) ? input.branchPolicy.allowed : undefined,
|
|
15033
|
+
protectedNames: Array.isArray(input.branchPolicy?.protected) ? input.branchPolicy.protected : undefined
|
|
15034
|
+
}, DEFAULTS),
|
|
15035
|
+
commitPolicy: {
|
|
15036
|
+
preset: commitPreset,
|
|
15037
|
+
...typeof input.commitPolicy?.pattern === "string" ? { pattern: input.commitPolicy.pattern } : {}
|
|
15087
15038
|
}
|
|
15088
15039
|
};
|
|
15040
|
+
if (!Object.hasOwn(PRESETS, input.branchPolicy?.preset))
|
|
15041
|
+
unchosenBranchPolicy.add(config);
|
|
15042
|
+
return { status: "valid", path: file, config };
|
|
15089
15043
|
}, readConfigTyped = (dir) => {
|
|
15090
15044
|
const file = path13.join(dir ?? configDir(), "config.json");
|
|
15091
15045
|
return parseConfigResult(readSafe(file), file);
|
|
@@ -15099,9 +15053,11 @@ var diagnosticLogger, setDiagnosticLogger = (logger) => {
|
|
|
15099
15053
|
if (result.status === "malformed")
|
|
15100
15054
|
throw new Error(result.error);
|
|
15101
15055
|
return result.config ?? DEFAULTS;
|
|
15102
|
-
}, vcsConfigPath = () => process.env.WORKFLOW_VCS_CONFIG ?? path13.join(configDir(), "vcs.json"), branchGlobPattern = (glob) => new RegExp(`^${glob.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*")}$`, "i"), resolveBranchPolicy = (config, workspace) => {
|
|
15056
|
+
}, vcsConfigPath = () => process.env.WORKFLOW_VCS_CONFIG ?? path13.join(configDir(), "vcs.json"), branchGlobPattern = (glob) => new RegExp(`^${glob.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*")}$`, "i"), resolveBranchPolicy = (config, workspace, repoPreset) => {
|
|
15103
15057
|
const wp = workspace?.branchPolicy ?? {};
|
|
15104
|
-
const
|
|
15058
|
+
const workspacePreset = Object.hasOwn(PRESETS, wp.preset);
|
|
15059
|
+
const detected = !workspacePreset && unchosenBranchPolicy.has(config) ? repoPreset?.() ?? null : null;
|
|
15060
|
+
const preset = workspacePreset ? wp.preset : detected ?? config.branchPolicy?.preset ?? "gitflow";
|
|
15105
15061
|
const merged = mergePreset(preset, {
|
|
15106
15062
|
allowed: wp.allowed,
|
|
15107
15063
|
protectedNames: wp.protected
|
|
@@ -15110,9 +15066,10 @@ var diagnosticLogger, setDiagnosticLogger = (logger) => {
|
|
|
15110
15066
|
return {
|
|
15111
15067
|
preset,
|
|
15112
15068
|
allowed,
|
|
15113
|
-
protected: new Set(merged.protected.map((p) => p.toLowerCase())),
|
|
15069
|
+
protected: new Set([...merged.protected, ...detected ? PRESETS.gitflow.protected : []].map((p) => p.toLowerCase())),
|
|
15114
15070
|
integration: wp.integration === "merge" ? "merge" : "pr",
|
|
15115
|
-
defaultTargetBranch: preset === "github-flow" ? "main" : preset === "trunk-based" ? "master" : "develop"
|
|
15071
|
+
defaultTargetBranch: preset === "github-flow" ? "main" : preset === "trunk-based" ? "master" : "develop",
|
|
15072
|
+
detected: detected !== null
|
|
15116
15073
|
};
|
|
15117
15074
|
}, COMMIT_PRESETS, resolveCommitPolicy = (config, workspace) => {
|
|
15118
15075
|
const wp = workspace?.commitPolicy ?? {};
|
|
@@ -15146,6 +15103,7 @@ var init_config = __esm(() => {
|
|
|
15146
15103
|
},
|
|
15147
15104
|
commitPolicy: { preset: "conventional" }
|
|
15148
15105
|
};
|
|
15106
|
+
unchosenBranchPolicy = new WeakSet([DEFAULTS]);
|
|
15149
15107
|
COMMIT_PRESETS = [
|
|
15150
15108
|
"conventional",
|
|
15151
15109
|
"gitmoji",
|
|
@@ -15156,7 +15114,127 @@ var init_config = __esm(() => {
|
|
|
15156
15114
|
];
|
|
15157
15115
|
});
|
|
15158
15116
|
|
|
15159
|
-
// packages/workit-
|
|
15117
|
+
// packages/workit-core/src/core/branch-policy.ts
|
|
15118
|
+
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
15119
|
+
var PREFIXES, branchNames = (workspaceRoot) => {
|
|
15120
|
+
const r = spawnSync7("git", ["for-each-ref", "--format=%(refname)", "refs/heads", "refs/remotes/origin"], { cwd: workspaceRoot, encoding: "utf8" });
|
|
15121
|
+
if (r.status !== 0)
|
|
15122
|
+
return new Set;
|
|
15123
|
+
return new Set((r.stdout ?? "").split(`
|
|
15124
|
+
`).filter(Boolean).map((ref) => ref.startsWith("refs/heads/") ? ref.slice("refs/heads/".length) : ref.slice("refs/remotes/origin/".length)));
|
|
15125
|
+
}, detectBranchPolicy = (workspaceRoot) => {
|
|
15126
|
+
const names = branchNames(workspaceRoot);
|
|
15127
|
+
const develop = names.has("develop");
|
|
15128
|
+
const main = names.has("main");
|
|
15129
|
+
const master = names.has("master");
|
|
15130
|
+
const root = main ? "main" : master ? "master" : null;
|
|
15131
|
+
if (develop) {
|
|
15132
|
+
return {
|
|
15133
|
+
preset: "gitflow",
|
|
15134
|
+
developBranch: "develop",
|
|
15135
|
+
integration: "merge",
|
|
15136
|
+
protected: root ? [root, "develop"] : ["develop"],
|
|
15137
|
+
allowed: [...PRESETS.gitflow.allowed],
|
|
15138
|
+
prefixes: PREFIXES
|
|
15139
|
+
};
|
|
15140
|
+
}
|
|
15141
|
+
if (root === "main") {
|
|
15142
|
+
return {
|
|
15143
|
+
preset: "github-flow",
|
|
15144
|
+
developBranch: null,
|
|
15145
|
+
integration: "pr",
|
|
15146
|
+
protected: [root],
|
|
15147
|
+
allowed: ["*"],
|
|
15148
|
+
prefixes: PREFIXES
|
|
15149
|
+
};
|
|
15150
|
+
}
|
|
15151
|
+
if (root === "master") {
|
|
15152
|
+
return {
|
|
15153
|
+
preset: "trunk-based",
|
|
15154
|
+
developBranch: null,
|
|
15155
|
+
integration: "pr",
|
|
15156
|
+
protected: [root],
|
|
15157
|
+
allowed: ["*"],
|
|
15158
|
+
prefixes: PREFIXES
|
|
15159
|
+
};
|
|
15160
|
+
}
|
|
15161
|
+
return {
|
|
15162
|
+
preset: "gitflow",
|
|
15163
|
+
developBranch: null,
|
|
15164
|
+
integration: "merge",
|
|
15165
|
+
protected: [],
|
|
15166
|
+
allowed: [],
|
|
15167
|
+
prefixes: PREFIXES
|
|
15168
|
+
};
|
|
15169
|
+
}, repoBranchPreset = (workspaceRoot) => {
|
|
15170
|
+
const detected = detectBranchPolicy(workspaceRoot);
|
|
15171
|
+
return detected.developBranch || detected.allowed.length ? detected.preset : null;
|
|
15172
|
+
};
|
|
15173
|
+
var init_branch_policy = __esm(() => {
|
|
15174
|
+
init_config();
|
|
15175
|
+
PREFIXES = {
|
|
15176
|
+
feature: "feature/*",
|
|
15177
|
+
bugfix: "bugfix/*",
|
|
15178
|
+
release: "release/*",
|
|
15179
|
+
hotfix: "hotfix/*"
|
|
15180
|
+
};
|
|
15181
|
+
});
|
|
15182
|
+
|
|
15183
|
+
// packages/workit-core/src/core/commit-flavors.ts
|
|
15184
|
+
var CONVENTIONAL_RE, TICKET_RE, GITMOJI_RE, matchCommitFlavor = (message, flavor, pattern) => {
|
|
15185
|
+
const subject = message.split(`
|
|
15186
|
+
`, 1)[0] ?? "";
|
|
15187
|
+
switch (flavor) {
|
|
15188
|
+
case "conventional":
|
|
15189
|
+
return CONVENTIONAL_RE.test(subject);
|
|
15190
|
+
case "gitmoji":
|
|
15191
|
+
return GITMOJI_RE.test(subject);
|
|
15192
|
+
case "ticket-prefix":
|
|
15193
|
+
return TICKET_RE.test(subject);
|
|
15194
|
+
case "freeform":
|
|
15195
|
+
return subject.trim().length > 0;
|
|
15196
|
+
case "custom":
|
|
15197
|
+
if (!pattern)
|
|
15198
|
+
return false;
|
|
15199
|
+
try {
|
|
15200
|
+
return new RegExp(pattern).test(subject);
|
|
15201
|
+
} catch {
|
|
15202
|
+
return false;
|
|
15203
|
+
}
|
|
15204
|
+
case "auto":
|
|
15205
|
+
return subject.trim().length > 0;
|
|
15206
|
+
}
|
|
15207
|
+
}, DETECTABLE, detectCommitFlavor = (subjects, threshold = 0.7) => {
|
|
15208
|
+
if (subjects.length === 0)
|
|
15209
|
+
return { flavor: null, confidence: 0 };
|
|
15210
|
+
const votes = new Map;
|
|
15211
|
+
for (const subject of subjects) {
|
|
15212
|
+
const hit = DETECTABLE.find((flavor) => matchCommitFlavor(subject, flavor));
|
|
15213
|
+
if (hit)
|
|
15214
|
+
votes.set(hit, (votes.get(hit) ?? 0) + 1);
|
|
15215
|
+
}
|
|
15216
|
+
let best = null;
|
|
15217
|
+
let count = 0;
|
|
15218
|
+
for (const [flavor, votesFor] of votes) {
|
|
15219
|
+
if (votesFor > count) {
|
|
15220
|
+
best = flavor;
|
|
15221
|
+
count = votesFor;
|
|
15222
|
+
}
|
|
15223
|
+
}
|
|
15224
|
+
const confidence = count / subjects.length;
|
|
15225
|
+
return best !== null && confidence >= threshold ? { flavor: best, confidence } : { flavor: null, confidence };
|
|
15226
|
+
};
|
|
15227
|
+
var init_commit_flavors = __esm(() => {
|
|
15228
|
+
CONVENTIONAL_RE = /^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?(!)?: .+/;
|
|
15229
|
+
TICKET_RE = /^[A-Z]{2,}-\d+\b/;
|
|
15230
|
+
GITMOJI_RE = /^\p{Extended_Pictographic}/u;
|
|
15231
|
+
DETECTABLE = ["conventional", "gitmoji", "ticket-prefix"];
|
|
15232
|
+
});
|
|
15233
|
+
|
|
15234
|
+
// packages/workit-core/src/core/git.ts
|
|
15235
|
+
var init_git = () => {};
|
|
15236
|
+
|
|
15237
|
+
// packages/workit-core/src/core/workspaces.ts
|
|
15160
15238
|
import { createHash as createHash8 } from "node:crypto";
|
|
15161
15239
|
import { readFileSync as readFileSync4, realpathSync as realpathSync3 } from "node:fs";
|
|
15162
15240
|
import path14 from "node:path";
|
|
@@ -15165,7 +15243,7 @@ function workspaceDefaultTarget(cwd, globalDefault) {
|
|
|
15165
15243
|
const wp = ws?.branchPolicy ?? {};
|
|
15166
15244
|
const hasWorkspacePolicy = typeof wp.preset === "string" && Object.hasOwn(PRESETS, wp.preset);
|
|
15167
15245
|
const selected = resolveRuntimeWorkspacePolicy(cwd, "branch", process.env.WORKFLOW_PROFILE?.trim() || undefined);
|
|
15168
|
-
const policyDefault = resolveBranchPolicy(readConfig(), selected.policy ? { branchPolicy: selected.policy } : null).defaultTargetBranch;
|
|
15246
|
+
const policyDefault = resolveBranchPolicy(readConfig(), selected.policy ? { branchPolicy: selected.policy } : null, () => repoBranchPreset(cwd)).defaultTargetBranch;
|
|
15169
15247
|
return String(ws?.vcs?.defaultTargetBranch ?? (hasWorkspacePolicy ? policyDefault : globalDefault ?? policyDefault) ?? "develop");
|
|
15170
15248
|
}
|
|
15171
15249
|
var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspaceCommitPolicySchema, workspaceProfileSchema, versionSourceSchema, releaseTrackSchema, workspaceConfigSchema, workspacesFileSchema, workspacesRevision = (contents) => createHash8("sha256").update(contents ?? "<missing>").digest("hex"), validateWorkspacesDocument = (parsed, file) => {
|
|
@@ -15447,7 +15525,7 @@ var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspace
|
|
|
15447
15525
|
commitPolicy: profile?.commitPolicy ? `profile:${profileName}` : workspace.commitPolicy ? `workspace:${workspace.name}` : "user-default"
|
|
15448
15526
|
}
|
|
15449
15527
|
};
|
|
15450
|
-
}, resolveWorkspacePolicy = (config, workspace, profileName) => {
|
|
15528
|
+
}, resolveWorkspacePolicy = (config, workspace, profileName, repoPreset) => {
|
|
15451
15529
|
const selected = workspace ? resolveWorkspaceProfile(workspace, profileName) : {
|
|
15452
15530
|
status: "resolved",
|
|
15453
15531
|
profileName: null,
|
|
@@ -15460,7 +15538,7 @@ var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspace
|
|
|
15460
15538
|
status: "resolved",
|
|
15461
15539
|
workspace: selected.workspace,
|
|
15462
15540
|
profileName: selected.profileName,
|
|
15463
|
-
branchPolicy: resolveBranchPolicy(config, selected.workspace),
|
|
15541
|
+
branchPolicy: resolveBranchPolicy(config, selected.workspace, repoPreset),
|
|
15464
15542
|
commitPolicy: resolveCommitPolicy(config, selected.workspace),
|
|
15465
15543
|
provenance: selected.provenance
|
|
15466
15544
|
};
|
|
@@ -15468,6 +15546,7 @@ var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspace
|
|
|
15468
15546
|
var init_workspaces = __esm(() => {
|
|
15469
15547
|
init_zod();
|
|
15470
15548
|
init_config();
|
|
15549
|
+
init_branch_policy();
|
|
15471
15550
|
nonBlank = string2().refine((value) => value.trim().length > 0, "must not be blank");
|
|
15472
15551
|
branchPreset = custom((value) => typeof value === "string" && Object.hasOwn(PRESETS, value), "unsupported branch preset");
|
|
15473
15552
|
commitPreset = custom((value) => typeof value === "string" && COMMIT_PRESETS.includes(value), "unsupported commit preset");
|
|
@@ -15592,9 +15671,9 @@ var init_workspaces = __esm(() => {
|
|
|
15592
15671
|
}).passthrough();
|
|
15593
15672
|
});
|
|
15594
15673
|
|
|
15595
|
-
// packages/workit-
|
|
15674
|
+
// packages/workit-core/src/core/release-tracks.ts
|
|
15596
15675
|
import { createHash as createHash9 } from "node:crypto";
|
|
15597
|
-
import { spawnSync as
|
|
15676
|
+
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
15598
15677
|
import { readFileSync as readFileSync5 } from "node:fs";
|
|
15599
15678
|
function readReleaseTracks(raw) {
|
|
15600
15679
|
const out = { tracks: [], issues: [], error: null, protectedBranches: [] };
|
|
@@ -15996,7 +16075,7 @@ var ReleaseTrackError, KNOWN_FIELDS, BRANCH_FIELDS, PLACEHOLDER, HAS_PLACEHOLDER
|
|
|
15996
16075
|
const remote = remotes.find((name) => bare.startsWith(`${name}/`));
|
|
15997
16076
|
return remote ? bare.slice(remote.length + 1) : bare;
|
|
15998
16077
|
}, MAX_RECORDED_HOPS = 10, git4 = (cwd, args) => {
|
|
15999
|
-
const run =
|
|
16078
|
+
const run = spawnSync8("git", args, {
|
|
16000
16079
|
cwd,
|
|
16001
16080
|
encoding: "utf8",
|
|
16002
16081
|
timeout: 20000,
|
|
@@ -16054,10 +16133,10 @@ var init_release_tracks = __esm(() => {
|
|
|
16054
16133
|
memo3 = new Map;
|
|
16055
16134
|
});
|
|
16056
16135
|
|
|
16057
|
-
// packages/workit-
|
|
16136
|
+
// packages/workit-core/src/core/vcs-config.ts
|
|
16058
16137
|
import fs12 from "node:fs";
|
|
16059
16138
|
import path15 from "node:path";
|
|
16060
|
-
import { spawnSync as
|
|
16139
|
+
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
16061
16140
|
function vcsConfig(mode, cwd, options = {}) {
|
|
16062
16141
|
const ws = resolveRuntimeWorkspaceVcs(vcsCwd(cwd));
|
|
16063
16142
|
const wsVcs = ws?.vcs ?? {};
|
|
@@ -16140,7 +16219,7 @@ function vcsConfig(mode, cwd, options = {}) {
|
|
|
16140
16219
|
return out;
|
|
16141
16220
|
}
|
|
16142
16221
|
var workspacesPath = () => path15.join(configDir(), "workspaces.json"), vcsCwd = (cwd) => cwd ?? process.env.WORKFLOW_WORKSPACE_ROOT ?? process.cwd(), remoteProvider = (cwd) => {
|
|
16143
|
-
const r =
|
|
16222
|
+
const r = spawnSync9("git", ["remote", "get-url", "origin"], { cwd, encoding: "utf8" });
|
|
16144
16223
|
if (r.status !== 0)
|
|
16145
16224
|
return null;
|
|
16146
16225
|
const url = (r.stdout ?? "").trim();
|
|
@@ -16182,7 +16261,7 @@ var init_vcs_config = __esm(() => {
|
|
|
16182
16261
|
init_release_tracks();
|
|
16183
16262
|
});
|
|
16184
16263
|
|
|
16185
|
-
// packages/workit-
|
|
16264
|
+
// packages/workit-core/src/core/branch.ts
|
|
16186
16265
|
import { execFileSync } from "node:child_process";
|
|
16187
16266
|
import { createHash as createHash10 } from "node:crypto";
|
|
16188
16267
|
import path16 from "node:path";
|
|
@@ -16190,7 +16269,7 @@ function effectiveWorkspacePolicy(workspaceRoot, kind, profileName) {
|
|
|
16190
16269
|
const selected = resolveRuntimeWorkspacePolicy(workspaceRoot, kind, profileName?.trim() || process.env.WORKFLOW_PROFILE?.trim() || undefined);
|
|
16191
16270
|
const config = readConfig();
|
|
16192
16271
|
return kind === "branch" ? {
|
|
16193
|
-
branchPolicy: withReleaseTracks(workspaceRoot, resolveBranchPolicy(config, selected.policy ? { branchPolicy: selected.policy } : null)),
|
|
16272
|
+
branchPolicy: withReleaseTracks(workspaceRoot, resolveBranchPolicy(config, selected.policy ? { branchPolicy: selected.policy } : null, () => repoBranchPreset(workspaceRoot))),
|
|
16194
16273
|
provenance: { branchPolicy: selected.source }
|
|
16195
16274
|
} : {
|
|
16196
16275
|
commitPolicy: resolveCommitPolicy(config, selected.policy ? { commitPolicy: selected.policy } : null),
|
|
@@ -16347,6 +16426,7 @@ var withReleaseTracks = (workspaceRoot, policy) => {
|
|
|
16347
16426
|
return dirty ? "carry" : "clean";
|
|
16348
16427
|
};
|
|
16349
16428
|
var init_branch = __esm(() => {
|
|
16429
|
+
init_branch_policy();
|
|
16350
16430
|
init_commit_flavors();
|
|
16351
16431
|
init_git();
|
|
16352
16432
|
init_config();
|
|
@@ -16355,12 +16435,12 @@ var init_branch = __esm(() => {
|
|
|
16355
16435
|
init_release_tracks();
|
|
16356
16436
|
});
|
|
16357
16437
|
|
|
16358
|
-
// packages/workit-
|
|
16438
|
+
// packages/workit-core/src/core/route-intent.ts
|
|
16359
16439
|
var init_route_intent = __esm(() => {
|
|
16360
16440
|
init_branch();
|
|
16361
16441
|
});
|
|
16362
16442
|
|
|
16363
|
-
// packages/workit-
|
|
16443
|
+
// packages/workit-core/src/core/runtime-identity.ts
|
|
16364
16444
|
import { createHash as createHash11 } from "node:crypto";
|
|
16365
16445
|
import { readFileSync as readFileSync6 } from "node:fs";
|
|
16366
16446
|
var sha256Hex = (bytes) => createHash11("sha256").update(bytes).digest("hex"), bundleHashOfFile = (file) => {
|
|
@@ -16385,7 +16465,7 @@ var init_runtime_identity = __esm(() => {
|
|
|
16385
16465
|
];
|
|
16386
16466
|
});
|
|
16387
16467
|
|
|
16388
|
-
// packages/workit-
|
|
16468
|
+
// packages/workit-core/src/core/policy-resolver.ts
|
|
16389
16469
|
function resolvePolicy(input) {
|
|
16390
16470
|
const ids = input.constraints.map((constraint) => constraint.id);
|
|
16391
16471
|
if (new Set(ids).size !== ids.length)
|
|
@@ -16445,7 +16525,7 @@ var init_policy_resolver = __esm(() => {
|
|
|
16445
16525
|
init_derive();
|
|
16446
16526
|
});
|
|
16447
16527
|
|
|
16448
|
-
// packages/workit-
|
|
16528
|
+
// packages/workit-core/src/core/safe-write.ts
|
|
16449
16529
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
16450
16530
|
import {
|
|
16451
16531
|
closeSync as closeSync2,
|
|
@@ -16523,7 +16603,7 @@ function writeFileAtomic(file, content, mode) {
|
|
|
16523
16603
|
}
|
|
16524
16604
|
var init_safe_write = () => {};
|
|
16525
16605
|
|
|
16526
|
-
// packages/workit-
|
|
16606
|
+
// packages/workit-core/src/autonomy.ts
|
|
16527
16607
|
import { copyFileSync as copyFileSync3, existsSync as existsSync6 } from "node:fs";
|
|
16528
16608
|
import os3 from "node:os";
|
|
16529
16609
|
import path18 from "node:path";
|
|
@@ -16656,7 +16736,7 @@ function requireGrant(cwd, kind, options = {}) {
|
|
|
16656
16736
|
allowed: true,
|
|
16657
16737
|
kind,
|
|
16658
16738
|
source: configured ? autonomy.source : "default",
|
|
16659
|
-
|
|
16739
|
+
allowUnverified: kind === "merge" && value === true,
|
|
16660
16740
|
workspace
|
|
16661
16741
|
};
|
|
16662
16742
|
}
|
|
@@ -16804,7 +16884,7 @@ var init_autonomy = __esm(() => {
|
|
|
16804
16884
|
DEFAULT_ENDPOINTS = ["commit", "pr", "green", "merged"];
|
|
16805
16885
|
});
|
|
16806
16886
|
|
|
16807
|
-
// packages/workit-
|
|
16887
|
+
// packages/workit-core/src/core/task-engine.ts
|
|
16808
16888
|
import { realpathSync as realpathSync4 } from "node:fs";
|
|
16809
16889
|
|
|
16810
16890
|
class WorkitCore {
|
|
@@ -18386,13 +18466,13 @@ var init_task_engine = __esm(() => {
|
|
|
18386
18466
|
retryPause = new Int32Array(new SharedArrayBuffer(4));
|
|
18387
18467
|
});
|
|
18388
18468
|
|
|
18389
|
-
// packages/workit-
|
|
18469
|
+
// packages/workit-core/src/core/repo-context.ts
|
|
18390
18470
|
var init_repo_context = __esm(() => {
|
|
18391
18471
|
init_vcs_config();
|
|
18392
18472
|
init_core3();
|
|
18393
18473
|
});
|
|
18394
18474
|
|
|
18395
|
-
// packages/workit-
|
|
18475
|
+
// packages/workit-core/src/forge/pr-body.ts
|
|
18396
18476
|
function parseGhIssue(value) {
|
|
18397
18477
|
const m = /issues\/(\d+)/.exec(value);
|
|
18398
18478
|
return m ? m[1] : String(value).trim().replace(/^#/, "");
|
|
@@ -18453,9 +18533,9 @@ var init_pr_body = __esm(() => {
|
|
|
18453
18533
|
init_vcs_config();
|
|
18454
18534
|
});
|
|
18455
18535
|
|
|
18456
|
-
// packages/workit-
|
|
18536
|
+
// packages/workit-core/src/core/pr-create.ts
|
|
18457
18537
|
import path19 from "node:path";
|
|
18458
|
-
import { spawnSync as
|
|
18538
|
+
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
18459
18539
|
import { pathToFileURL } from "node:url";
|
|
18460
18540
|
var safePushUrl = (remote) => {
|
|
18461
18541
|
const raw = remote.trim();
|
|
@@ -18483,7 +18563,7 @@ var safePushUrl = (remote) => {
|
|
|
18483
18563
|
const target = safePushUrl(remote);
|
|
18484
18564
|
if (!target)
|
|
18485
18565
|
return false;
|
|
18486
|
-
const result =
|
|
18566
|
+
const result = spawnSync10("git", ["config", "--get-regexp", "^url\\..*\\.(insteadof|pushinsteadof)$"], { cwd, encoding: "utf8" });
|
|
18487
18567
|
if (result.status !== 0 && result.status !== 1)
|
|
18488
18568
|
return false;
|
|
18489
18569
|
const prefixes = (result.stdout ?? "").split(/\r?\n/u).map((line) => line.trim().slice(line.trim().indexOf(" ") + 1)).filter(Boolean);
|
|
@@ -18496,13 +18576,13 @@ var init_pr_create = __esm(() => {
|
|
|
18496
18576
|
init_pr_body();
|
|
18497
18577
|
});
|
|
18498
18578
|
|
|
18499
|
-
// packages/workit-
|
|
18579
|
+
// packages/workit-core/src/core/tracker-issues.ts
|
|
18500
18580
|
var init_tracker_issues = __esm(() => {
|
|
18501
18581
|
init_pr_create();
|
|
18502
18582
|
init_vcs_config();
|
|
18503
18583
|
});
|
|
18504
18584
|
|
|
18505
|
-
// packages/workit-
|
|
18585
|
+
// packages/workit-core/src/core/templates.ts
|
|
18506
18586
|
var repoRoot;
|
|
18507
18587
|
var init_templates = __esm(() => {
|
|
18508
18588
|
init_config();
|
|
@@ -18510,7 +18590,7 @@ var init_templates = __esm(() => {
|
|
|
18510
18590
|
repoRoot = assetRoot();
|
|
18511
18591
|
});
|
|
18512
18592
|
|
|
18513
|
-
// packages/workit-
|
|
18593
|
+
// packages/workit-core/src/core/scripts.ts
|
|
18514
18594
|
var PLUGIN_ROOT, ASSET_ROOT, resolveWorkspaceRoot = (explicit) => explicit || process.cwd();
|
|
18515
18595
|
var init_scripts = __esm(() => {
|
|
18516
18596
|
init_package_root();
|
|
@@ -18518,7 +18598,7 @@ var init_scripts = __esm(() => {
|
|
|
18518
18598
|
ASSET_ROOT = assetRoot();
|
|
18519
18599
|
});
|
|
18520
18600
|
|
|
18521
|
-
// packages/workit-
|
|
18601
|
+
// packages/workit-core/src/core/youtrack.ts
|
|
18522
18602
|
import fs13 from "node:fs";
|
|
18523
18603
|
import path20 from "node:path";
|
|
18524
18604
|
function readYouTrackConfig(required) {
|
|
@@ -18990,7 +19070,7 @@ var init_youtrack = __esm(() => {
|
|
|
18990
19070
|
};
|
|
18991
19071
|
});
|
|
18992
19072
|
|
|
18993
|
-
// packages/workit-
|
|
19073
|
+
// packages/workit-core/src/core/context-read.ts
|
|
18994
19074
|
var contextReadSchema;
|
|
18995
19075
|
var init_context_read = __esm(() => {
|
|
18996
19076
|
init_zod();
|
|
@@ -19021,7 +19101,7 @@ var init_context_read = __esm(() => {
|
|
|
19021
19101
|
}).strict();
|
|
19022
19102
|
});
|
|
19023
19103
|
|
|
19024
|
-
// packages/workit-
|
|
19104
|
+
// packages/workit-core/src/core.ts
|
|
19025
19105
|
import { existsSync as existsSync7, realpathSync as realpathSync5 } from "node:fs";
|
|
19026
19106
|
import path21 from "node:path";
|
|
19027
19107
|
function resolveInside(root, candidate) {
|
|
@@ -19123,20 +19203,30 @@ async function parseTaskArgs(argv, deps) {
|
|
|
19123
19203
|
const judge = [];
|
|
19124
19204
|
const seen = new Set;
|
|
19125
19205
|
for (let i = 2;i < argv.length; i += 1) {
|
|
19126
|
-
|
|
19206
|
+
if (argv[i] === "--") {
|
|
19207
|
+
const extra = argv.slice(i + 1);
|
|
19208
|
+
if (extra.length)
|
|
19209
|
+
return parseUsage(`${family} ${actionName} takes no positional arguments (got: ${extra.join(" ")})`, json);
|
|
19210
|
+
break;
|
|
19211
|
+
}
|
|
19212
|
+
const eq = argv[i].startsWith("--") ? argv[i].indexOf("=") : -1;
|
|
19213
|
+
const token = eq > 0 ? argv[i].slice(0, eq) : argv[i];
|
|
19214
|
+
const inline = eq > 0 ? argv[i].slice(eq + 1) : undefined;
|
|
19127
19215
|
if (family === "policy" && (token === "--judge" || token === "--ref")) {
|
|
19128
19216
|
if (token === "--ref") {
|
|
19129
|
-
const value = argv[++i];
|
|
19217
|
+
const value = inline ?? argv[++i];
|
|
19130
19218
|
if (value === undefined || !value.trim())
|
|
19131
19219
|
return parseUsage("--ref requires a value", json);
|
|
19132
19220
|
judge.push(`ref=${value}`);
|
|
19133
19221
|
continue;
|
|
19134
19222
|
}
|
|
19223
|
+
if (inline !== undefined)
|
|
19224
|
+
judge.push(inline);
|
|
19135
19225
|
while (argv[i + 1] !== undefined && !argv[i + 1].startsWith("--"))
|
|
19136
19226
|
judge.push(argv[++i]);
|
|
19137
19227
|
continue;
|
|
19138
19228
|
}
|
|
19139
|
-
if (token === "--json" || token === "--confirm") {
|
|
19229
|
+
if ((token === "--json" || token === "--confirm") && inline === undefined) {
|
|
19140
19230
|
if (seen.has(token))
|
|
19141
19231
|
return parseUsage(`duplicate argument: ${token}`, json);
|
|
19142
19232
|
seen.add(token);
|
|
@@ -19145,8 +19235,8 @@ async function parseTaskArgs(argv, deps) {
|
|
|
19145
19235
|
continue;
|
|
19146
19236
|
}
|
|
19147
19237
|
if (!["--payload", "--task", "--revision", "--workspace-revision", "--view", "--actor"].includes(token))
|
|
19148
|
-
return parseUsage(`unknown argument: ${
|
|
19149
|
-
const value = argv[++i];
|
|
19238
|
+
return parseUsage(`unknown argument: ${argv[i]}`, json);
|
|
19239
|
+
const value = inline ?? argv[++i];
|
|
19150
19240
|
if (value === undefined || value.trim() === "" && token !== "--workspace-revision")
|
|
19151
19241
|
return parseUsage(`${token} requires a value`, json);
|
|
19152
19242
|
if (seen.has(token))
|
|
@@ -19205,6 +19295,12 @@ async function parseHandoffArgs(argv, deps) {
|
|
|
19205
19295
|
const seen = new Set;
|
|
19206
19296
|
for (let i = 0;i < argv.length; i += 1) {
|
|
19207
19297
|
const token = argv[i];
|
|
19298
|
+
if (token === "--") {
|
|
19299
|
+
const extra = argv.slice(i + 1);
|
|
19300
|
+
if (extra.length)
|
|
19301
|
+
return parseUsage(`handoff takes no positional arguments (got: ${extra.join(" ")})`, json);
|
|
19302
|
+
break;
|
|
19303
|
+
}
|
|
19208
19304
|
if (token === "--json") {
|
|
19209
19305
|
if (seen.has(token))
|
|
19210
19306
|
return parseUsage(`duplicate argument: ${token}`, json);
|
|
@@ -19212,14 +19308,18 @@ async function parseHandoffArgs(argv, deps) {
|
|
|
19212
19308
|
json = true;
|
|
19213
19309
|
continue;
|
|
19214
19310
|
}
|
|
19215
|
-
|
|
19311
|
+
const inline = token.startsWith("--task=") ? token.slice("--task=".length) : undefined;
|
|
19312
|
+
if (token !== "--task" && inline === undefined)
|
|
19216
19313
|
return parseUsage(`unknown argument: ${token}`, json);
|
|
19217
|
-
|
|
19314
|
+
const value = inline ?? argv[i + 1];
|
|
19315
|
+
if (taskId !== undefined || value === undefined || value.trim() === "")
|
|
19218
19316
|
return parseUsage("--task requires one non-empty value", json);
|
|
19219
|
-
if (seen.has(
|
|
19220
|
-
return parseUsage(
|
|
19221
|
-
seen.add(
|
|
19222
|
-
taskId =
|
|
19317
|
+
if (seen.has("--task"))
|
|
19318
|
+
return parseUsage("duplicate argument: --task", json);
|
|
19319
|
+
seen.add("--task");
|
|
19320
|
+
taskId = value;
|
|
19321
|
+
if (inline === undefined)
|
|
19322
|
+
i += 1;
|
|
19223
19323
|
}
|
|
19224
19324
|
if (!taskId)
|
|
19225
19325
|
return parseUsage("handoff requires --task <id>", json);
|
|
@@ -19406,13 +19506,14 @@ var init_task = __esm(() => {
|
|
|
19406
19506
|
|
|
19407
19507
|
// packages/workit-cli/src/verbs/task.ts
|
|
19408
19508
|
function isImplicitTaskForm(argv) {
|
|
19409
|
-
const [action,
|
|
19509
|
+
const [action, ...rest] = argv;
|
|
19410
19510
|
if (!action)
|
|
19411
19511
|
return false;
|
|
19412
19512
|
if (IMPLICIT2.has(action))
|
|
19413
19513
|
return true;
|
|
19514
|
+
const first = rest.find((arg) => arg !== "--json");
|
|
19414
19515
|
if (action === "start")
|
|
19415
|
-
return first !== undefined && !first.startsWith("--");
|
|
19516
|
+
return first !== undefined && (first === "--" || !first.startsWith("--"));
|
|
19416
19517
|
if (action === "close")
|
|
19417
19518
|
return !argv.includes("--task") && !argv.includes("--payload");
|
|
19418
19519
|
return false;
|
|
@@ -19421,6 +19522,10 @@ function parse4(argv) {
|
|
|
19421
19522
|
const flags = { positionals: [], values: new Map, switches: new Set };
|
|
19422
19523
|
for (let index = 0;index < argv.length; index += 1) {
|
|
19423
19524
|
const arg = argv[index];
|
|
19525
|
+
if (arg === "--") {
|
|
19526
|
+
flags.positionals.push(...argv.slice(index + 1));
|
|
19527
|
+
break;
|
|
19528
|
+
}
|
|
19424
19529
|
const [flag, inline] = arg.startsWith("--") && arg.includes("=") ? arg.split(/=(.*)/su) : [arg];
|
|
19425
19530
|
if (SWITCHES.has(flag)) {
|
|
19426
19531
|
flags.switches.add(flag);
|
|
@@ -34280,7 +34385,7 @@ function getSgrPrefix(code) {
|
|
|
34280
34385
|
if (code.startsWith("")) {
|
|
34281
34386
|
return "";
|
|
34282
34387
|
}
|
|
34283
|
-
return `${
|
|
34388
|
+
return `${ESCAPE2}${ANSI_CSI2}`;
|
|
34284
34389
|
}
|
|
34285
34390
|
function createSgrCode(prefix, values) {
|
|
34286
34391
|
return `${prefix}${values.join(";")}${ANSI_SGR_TERMINATOR2}`;
|
|
@@ -34289,7 +34394,7 @@ function getSgrFragments(code) {
|
|
|
34289
34394
|
const fragments = [];
|
|
34290
34395
|
const sgrPrefix = getSgrPrefix(code);
|
|
34291
34396
|
let parameterString;
|
|
34292
|
-
if (code.startsWith(`${
|
|
34397
|
+
if (code.startsWith(`${ESCAPE2}${ANSI_CSI2}`)) {
|
|
34293
34398
|
parameterString = code.slice(2, -1);
|
|
34294
34399
|
} else if (code.startsWith("")) {
|
|
34295
34400
|
parameterString = code.slice(1, -1);
|
|
@@ -34450,7 +34555,7 @@ function parseHyperlinkCode(string, index) {
|
|
|
34450
34555
|
endIndex: sequenceIndex + 1
|
|
34451
34556
|
};
|
|
34452
34557
|
}
|
|
34453
|
-
if (character ===
|
|
34558
|
+
if (character === ESCAPE2 && string[sequenceIndex + 1] === ANSI_OSC_TERMINATOR) {
|
|
34454
34559
|
const code = string.slice(index, sequenceIndex + 2);
|
|
34455
34560
|
const action = sequenceIndex === uriStart + 1 ? "close" : "open";
|
|
34456
34561
|
return {
|
|
@@ -34533,7 +34638,7 @@ function parseControlStringCode(string, index) {
|
|
|
34533
34638
|
if (supportsBellTerminator && string[sequenceIndex] === ANSI_BELL) {
|
|
34534
34639
|
return createControlParseResult(string.slice(index, sequenceIndex + 1), sequenceIndex + 1);
|
|
34535
34640
|
}
|
|
34536
|
-
if (string[sequenceIndex] ===
|
|
34641
|
+
if (string[sequenceIndex] === ESCAPE2 && string[sequenceIndex + 1] === ANSI_OSC_TERMINATOR) {
|
|
34537
34642
|
return createControlParseResult(string.slice(index, sequenceIndex + 2), sequenceIndex + 2);
|
|
34538
34643
|
}
|
|
34539
34644
|
if (string[sequenceIndex] === C1_STRING_TERMINATOR) {
|
|
@@ -34758,7 +34863,7 @@ function tokenizeAnsi(string, { endCharacter = Number.POSITIVE_INFINITY } = {})
|
|
|
34758
34863
|
}
|
|
34759
34864
|
return tokens;
|
|
34760
34865
|
}
|
|
34761
|
-
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,
|
|
34866
|
+
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, ESCAPE2 = "\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;
|
|
34762
34867
|
var init_tokenize_ansi = __esm(() => {
|
|
34763
34868
|
init_ansi_styles();
|
|
34764
34869
|
init_is_fullwidth_code_point();
|
|
@@ -34772,8 +34877,8 @@ var init_tokenize_ansi = __esm(() => {
|
|
|
34772
34877
|
C1_PM_CODE_POINT,
|
|
34773
34878
|
C1_APC_CODE_POINT
|
|
34774
34879
|
]);
|
|
34775
|
-
ANSI_STRING_TERMINATOR = `${
|
|
34776
|
-
ANSI_HYPERLINK_ESC_PREFIX = `${
|
|
34880
|
+
ANSI_STRING_TERMINATOR = `${ESCAPE2}${ANSI_OSC_TERMINATOR}`;
|
|
34881
|
+
ANSI_HYPERLINK_ESC_PREFIX = `${ESCAPE2}${ANSI_OSC2}8;`;
|
|
34777
34882
|
ANSI_HYPERLINK_C1_PREFIX = `${C1_OSC}8;`;
|
|
34778
34883
|
ANSI_HYPERLINK_ESC_CLOSE = `${ANSI_HYPERLINK_ESC_PREFIX};`;
|
|
34779
34884
|
ANSI_HYPERLINK_C1_CLOSE = `${ANSI_HYPERLINK_C1_PREFIX};`;
|
|
@@ -62177,7 +62282,7 @@ var init_build3 = __esm(async () => {
|
|
|
62177
62282
|
init_types();
|
|
62178
62283
|
});
|
|
62179
62284
|
|
|
62180
|
-
// packages/workit-
|
|
62285
|
+
// packages/workit-core/src/core/gitignore.ts
|
|
62181
62286
|
var GITIGNORE_ENTRIES;
|
|
62182
62287
|
var init_gitignore = __esm(() => {
|
|
62183
62288
|
GITIGNORE_ENTRIES = [
|
|
@@ -62198,7 +62303,7 @@ var init_gitignore = __esm(() => {
|
|
|
62198
62303
|
];
|
|
62199
62304
|
});
|
|
62200
62305
|
|
|
62201
|
-
// packages/workit-
|
|
62306
|
+
// packages/workit-core/src/core/changelog.ts
|
|
62202
62307
|
import fs16 from "node:fs";
|
|
62203
62308
|
import path23 from "node:path";
|
|
62204
62309
|
import { createHash as createHash12 } from "node:crypto";
|
|
@@ -62527,7 +62632,7 @@ var init_changelog = __esm(() => {
|
|
|
62527
62632
|
HEADING_RE = /^###\s+/;
|
|
62528
62633
|
});
|
|
62529
62634
|
|
|
62530
|
-
// packages/workit-
|
|
62635
|
+
// packages/workit-core/src/core/hygiene.ts
|
|
62531
62636
|
import { existsSync as existsSync9, readFileSync as readFileSync9, writeFileSync as writeFileSync4 } from "node:fs";
|
|
62532
62637
|
import path24 from "node:path";
|
|
62533
62638
|
var repoRoot2, templatesDir = () => path24.join(repoRoot2, "templates", "hygiene"), packageJson = (root) => {
|
|
@@ -62732,7 +62837,7 @@ var init_registration = __esm(() => {
|
|
|
62732
62837
|
CURSOR_HOOK_RUN_COMMAND = `npx -y --prefer-online --min-release-age=0 --package=${CURSOR_RUNTIME_PACKAGE} workit-cursor-hook`;
|
|
62733
62838
|
});
|
|
62734
62839
|
|
|
62735
|
-
// packages/workit-
|
|
62840
|
+
// packages/workit-core/src/core/support-matrix.ts
|
|
62736
62841
|
var SUPPORT_MATRIX;
|
|
62737
62842
|
var init_support_matrix = __esm(() => {
|
|
62738
62843
|
SUPPORT_MATRIX = {
|
|
@@ -62746,7 +62851,7 @@ var init_support_matrix = __esm(() => {
|
|
|
62746
62851
|
});
|
|
62747
62852
|
|
|
62748
62853
|
// packages/workit-cli/src/admin/host-install.ts
|
|
62749
|
-
import { spawnSync as
|
|
62854
|
+
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
62750
62855
|
import {
|
|
62751
62856
|
accessSync,
|
|
62752
62857
|
constants as constants2,
|
|
@@ -63017,7 +63122,7 @@ function runHostCommand(step, context = {}) {
|
|
|
63017
63122
|
stderr: `Cannot safely execute batch shim ${step.command}; resolve its Node.js CLI entrypoint and retry`
|
|
63018
63123
|
};
|
|
63019
63124
|
}
|
|
63020
|
-
const result =
|
|
63125
|
+
const result = spawnSync11(step.command, step.args, {
|
|
63021
63126
|
cwd: step.cwd,
|
|
63022
63127
|
env: (() => {
|
|
63023
63128
|
const home = context.home ?? context.env?.HOME ?? os6.homedir();
|
|
@@ -63176,7 +63281,7 @@ var init_host_install = __esm(() => {
|
|
|
63176
63281
|
CLAUDE_SCOPES = new Set(["user", "project", "local"]);
|
|
63177
63282
|
});
|
|
63178
63283
|
|
|
63179
|
-
// packages/workit-
|
|
63284
|
+
// packages/workit-core/src/core/skill-manifests.ts
|
|
63180
63285
|
import { cpSync as cpSync3, existsSync as existsSync12, readFileSync as readFileSync12, readdirSync as readdirSync5, statSync as statSync3, writeFileSync as writeFileSync5 } from "node:fs";
|
|
63181
63286
|
import path28 from "node:path";
|
|
63182
63287
|
var WORKIT_METHOD_SKILLS, skillManifestNames = (root) => existsSync12(root) ? readdirSync5(root).filter((name) => existsSync12(path28.join(root, name, "SKILL.md"))).toSorted() : [], validateSkillManifests = (root, expected, label) => {
|
|
@@ -63222,7 +63327,7 @@ var init_skill_manifests = __esm(() => {
|
|
|
63222
63327
|
});
|
|
63223
63328
|
|
|
63224
63329
|
// packages/workit-cli/src/admin/doctor.ts
|
|
63225
|
-
import { spawnSync as
|
|
63330
|
+
import { spawnSync as spawnSync12 } from "node:child_process";
|
|
63226
63331
|
import {
|
|
63227
63332
|
existsSync as existsSync13,
|
|
63228
63333
|
lstatSync as lstatSync4,
|
|
@@ -63306,7 +63411,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
63306
63411
|
}
|
|
63307
63412
|
return false;
|
|
63308
63413
|
}, versionOf = (bin, env, timeout) => {
|
|
63309
|
-
const r =
|
|
63414
|
+
const r = spawnSync12(bin, ["--version"], { encoding: "utf8", env, timeout });
|
|
63310
63415
|
if (r.error)
|
|
63311
63416
|
return null;
|
|
63312
63417
|
return (r.stdout ?? "").trim();
|
|
@@ -63555,7 +63660,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
63555
63660
|
`)) {
|
|
63556
63661
|
return false;
|
|
63557
63662
|
}
|
|
63558
|
-
return
|
|
63663
|
+
return spawnSync12(runtime, ["--check", entry], { encoding: "utf8", env }).status === 0;
|
|
63559
63664
|
} catch {
|
|
63560
63665
|
return false;
|
|
63561
63666
|
}
|
|
@@ -63769,7 +63874,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
63769
63874
|
if (!cmd)
|
|
63770
63875
|
return null;
|
|
63771
63876
|
try {
|
|
63772
|
-
const r =
|
|
63877
|
+
const r = spawnSync12(cmd, ["view", pkgName, "version"], {
|
|
63773
63878
|
encoding: "utf8",
|
|
63774
63879
|
timeout: 20000,
|
|
63775
63880
|
env: res.env
|
|
@@ -64053,6 +64158,16 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
64053
64158
|
detail: `malformed config: ${bad.join(", ")}`,
|
|
64054
64159
|
fix: `Repair the malformed config in ${bad[0]}`
|
|
64055
64160
|
};
|
|
64161
|
+
}, branchPresetLine = (res, workspace) => {
|
|
64162
|
+
try {
|
|
64163
|
+
const resolved = resolveWorkspacePolicy(readConfigFromDir(res.configDir), workspace, undefined, () => repoBranchPreset(res.cwd));
|
|
64164
|
+
if (resolved.status === "invalid")
|
|
64165
|
+
return [];
|
|
64166
|
+
const { preset, detected } = resolved.branchPolicy;
|
|
64167
|
+
return [`preset: ${detected ? `detected (${preset})` : preset}`];
|
|
64168
|
+
} catch {
|
|
64169
|
+
return [];
|
|
64170
|
+
}
|
|
64056
64171
|
}, checkWorkspaceMismatch = (res) => {
|
|
64057
64172
|
const result = readWorkspacesResult(res.configDir);
|
|
64058
64173
|
const file = result.path;
|
|
@@ -64060,7 +64175,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
64060
64175
|
return {
|
|
64061
64176
|
id: "workspace_mismatch",
|
|
64062
64177
|
status: "pass",
|
|
64063
|
-
detail: "no workspaces configured"
|
|
64178
|
+
detail: ["no workspaces configured", ...branchPresetLine(res, null)].join("; ")
|
|
64064
64179
|
};
|
|
64065
64180
|
if (result.status === "malformed" || result.status === "invalid")
|
|
64066
64181
|
return {
|
|
@@ -64084,7 +64199,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
64084
64199
|
const matched = `current directory matches workspace "${match.name}"`;
|
|
64085
64200
|
const tracks = releaseTracksReport(res.cwd);
|
|
64086
64201
|
const lines = describeReleaseTracks(tracks);
|
|
64087
|
-
const detail = [matched, ...lines].join("; ");
|
|
64202
|
+
const detail = [matched, ...branchPresetLine(res, match), ...lines].join("; ");
|
|
64088
64203
|
if (tracks.error)
|
|
64089
64204
|
return {
|
|
64090
64205
|
id: "workspace_mismatch",
|
|
@@ -64198,7 +64313,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
64198
64313
|
}, defaultIdentityProbes = (env) => ({
|
|
64199
64314
|
origin: (cwd) => {
|
|
64200
64315
|
try {
|
|
64201
|
-
const out =
|
|
64316
|
+
const out = spawnSync12("git", ["remote", "get-url", "origin"], {
|
|
64202
64317
|
cwd,
|
|
64203
64318
|
encoding: "utf8",
|
|
64204
64319
|
env
|
|
@@ -64210,7 +64325,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
64210
64325
|
},
|
|
64211
64326
|
ghLogin: (e) => {
|
|
64212
64327
|
try {
|
|
64213
|
-
const out =
|
|
64328
|
+
const out = spawnSync12("gh", ["api", "user", "--jq", ".login"], { encoding: "utf8", env: e });
|
|
64214
64329
|
const login = (out.stdout ?? "").trim();
|
|
64215
64330
|
return out.status === 0 && login ? login : null;
|
|
64216
64331
|
} catch {
|
|
@@ -64219,7 +64334,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
64219
64334
|
},
|
|
64220
64335
|
glabLogin: (e) => {
|
|
64221
64336
|
try {
|
|
64222
|
-
const out =
|
|
64337
|
+
const out = spawnSync12("glab", ["api", "user", "--jq", ".username"], {
|
|
64223
64338
|
encoding: "utf8",
|
|
64224
64339
|
env: e
|
|
64225
64340
|
});
|
|
@@ -64231,7 +64346,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
64231
64346
|
},
|
|
64232
64347
|
sshLogin: (host) => {
|
|
64233
64348
|
try {
|
|
64234
|
-
const out =
|
|
64349
|
+
const out = spawnSync12("ssh", ["-o", "BatchMode=yes", "-o", "ConnectTimeout=5", "-T", `git@${host}`], {
|
|
64235
64350
|
encoding: "utf8",
|
|
64236
64351
|
env
|
|
64237
64352
|
});
|
|
@@ -64426,6 +64541,7 @@ var init_doctor = __esm(() => {
|
|
|
64426
64541
|
init_runtime_identity();
|
|
64427
64542
|
init_boundary();
|
|
64428
64543
|
init_release_tracks();
|
|
64544
|
+
init_branch_policy();
|
|
64429
64545
|
init_config();
|
|
64430
64546
|
init_package_root();
|
|
64431
64547
|
init_registration();
|
|
@@ -65439,70 +65555,7 @@ var init_setup = __esm(() => {
|
|
|
65439
65555
|
SETUP_OVERRIDES = [...YT_OVERRIDES, ...VCS_OVERRIDES];
|
|
65440
65556
|
});
|
|
65441
65557
|
|
|
65442
|
-
// packages/workit-
|
|
65443
|
-
import { spawnSync as spawnSync12 } from "node:child_process";
|
|
65444
|
-
var PREFIXES, detectBranchPolicy = (workspaceRoot) => {
|
|
65445
|
-
const branchExists = (name) => {
|
|
65446
|
-
const r = spawnSync12("git", ["branch", "--list", name], {
|
|
65447
|
-
cwd: workspaceRoot,
|
|
65448
|
-
encoding: "utf8"
|
|
65449
|
-
});
|
|
65450
|
-
return r.status === 0 && (r.stdout ?? "").trim() !== "";
|
|
65451
|
-
};
|
|
65452
|
-
const develop = branchExists("develop");
|
|
65453
|
-
const main = branchExists("main");
|
|
65454
|
-
const master = branchExists("master");
|
|
65455
|
-
const root = main ? "main" : master ? "master" : null;
|
|
65456
|
-
if (develop) {
|
|
65457
|
-
return {
|
|
65458
|
-
preset: "gitflow",
|
|
65459
|
-
developBranch: "develop",
|
|
65460
|
-
integration: "merge",
|
|
65461
|
-
protected: root ? [root, "develop"] : ["develop"],
|
|
65462
|
-
allowed: [...PRESETS.gitflow.allowed],
|
|
65463
|
-
prefixes: PREFIXES
|
|
65464
|
-
};
|
|
65465
|
-
}
|
|
65466
|
-
if (root === "main") {
|
|
65467
|
-
return {
|
|
65468
|
-
preset: "github-flow",
|
|
65469
|
-
developBranch: null,
|
|
65470
|
-
integration: "pr",
|
|
65471
|
-
protected: [root],
|
|
65472
|
-
allowed: ["*"],
|
|
65473
|
-
prefixes: PREFIXES
|
|
65474
|
-
};
|
|
65475
|
-
}
|
|
65476
|
-
if (root === "master") {
|
|
65477
|
-
return {
|
|
65478
|
-
preset: "trunk-based",
|
|
65479
|
-
developBranch: null,
|
|
65480
|
-
integration: "pr",
|
|
65481
|
-
protected: [root],
|
|
65482
|
-
allowed: ["*"],
|
|
65483
|
-
prefixes: PREFIXES
|
|
65484
|
-
};
|
|
65485
|
-
}
|
|
65486
|
-
return {
|
|
65487
|
-
preset: "gitflow",
|
|
65488
|
-
developBranch: null,
|
|
65489
|
-
integration: "merge",
|
|
65490
|
-
protected: [],
|
|
65491
|
-
allowed: [],
|
|
65492
|
-
prefixes: PREFIXES
|
|
65493
|
-
};
|
|
65494
|
-
};
|
|
65495
|
-
var init_branch_policy = __esm(() => {
|
|
65496
|
-
init_config();
|
|
65497
|
-
PREFIXES = {
|
|
65498
|
-
feature: "feature/*",
|
|
65499
|
-
bugfix: "bugfix/*",
|
|
65500
|
-
release: "release/*",
|
|
65501
|
-
hotfix: "hotfix/*"
|
|
65502
|
-
};
|
|
65503
|
-
});
|
|
65504
|
-
|
|
65505
|
-
// packages/workit-cli/node_modules/@brainervirus/workit-core/src/core/workspace-branch-policy.ts
|
|
65558
|
+
// packages/workit-core/src/core/workspace-branch-policy.ts
|
|
65506
65559
|
import { mkdirSync as mkdirSync6, readFileSync as readFileSync15, renameSync as renameSync4, rmSync as rmSync4, writeFileSync as writeFileSync8 } from "node:fs";
|
|
65507
65560
|
import path31 from "node:path";
|
|
65508
65561
|
import { isDeepStrictEqual as isDeepStrictEqual3 } from "node:util";
|
|
@@ -68590,7 +68643,7 @@ function Screen({
|
|
|
68590
68643
|
};
|
|
68591
68644
|
const checkout = resolveBasePath(draft.values);
|
|
68592
68645
|
const workspace = resolveWorkspaceFromEntries(checkout, draft.values.workspaces);
|
|
68593
|
-
const resolved = resolveWorkspacePolicy(config, workspace);
|
|
68646
|
+
const resolved = resolveWorkspacePolicy(config, workspace, undefined, () => repoBranchPreset(checkout));
|
|
68594
68647
|
if (resolved.status === "invalid")
|
|
68595
68648
|
return { error: resolved.error };
|
|
68596
68649
|
return {
|
|
@@ -68980,7 +69033,7 @@ var init_steps = __esm(async () => {
|
|
|
68980
69033
|
];
|
|
68981
69034
|
});
|
|
68982
69035
|
|
|
68983
|
-
// packages/workit-
|
|
69036
|
+
// packages/workit-core/src/core/logger.ts
|
|
68984
69037
|
import { appendFileSync, mkdirSync as mkdirSync7, readdirSync as readdirSync7, unlinkSync as unlinkSync3 } from "node:fs";
|
|
68985
69038
|
import os11 from "node:os";
|
|
68986
69039
|
import path34 from "node:path";
|
|
@@ -69988,7 +70041,7 @@ var init_launch = __esm(() => {
|
|
|
69988
70041
|
init_upgrade();
|
|
69989
70042
|
});
|
|
69990
70043
|
|
|
69991
|
-
// packages/workit-
|
|
70044
|
+
// packages/workit-core/src/knowledge.ts
|
|
69992
70045
|
import { spawnSync as spawnSync14 } from "node:child_process";
|
|
69993
70046
|
import fs17 from "node:fs";
|
|
69994
70047
|
import path36 from "node:path";
|
|
@@ -70385,7 +70438,7 @@ var init_doctor2 = __esm(() => {
|
|
|
70385
70438
|
init_task();
|
|
70386
70439
|
});
|
|
70387
70440
|
|
|
70388
|
-
// packages/workit-
|
|
70441
|
+
// packages/workit-core/src/forge/redact.ts
|
|
70389
70442
|
function redactText(value) {
|
|
70390
70443
|
let out = stripAnsi2(value).replace(PRIVATE_KEY, "[REDACTED PRIVATE KEY]");
|
|
70391
70444
|
out = out.replace(WEBHOOK, `$1/${R}`);
|
|
@@ -70488,7 +70541,7 @@ var init_redact = __esm(() => {
|
|
|
70488
70541
|
NOT_FIRST_ERROR = /^\s*(?:\(pass\)|\(skip\)|\(todo\)|✓|✔|ok\b|PASS\b)|^\s*\d+ fail\b|##\[error\]Process completed|^\s*0 (?:errors?|fail)/u;
|
|
70489
70542
|
});
|
|
70490
70543
|
|
|
70491
|
-
// packages/workit-
|
|
70544
|
+
// packages/workit-core/src/checks.ts
|
|
70492
70545
|
import { spawn, spawnSync as spawnSync15 } from "node:child_process";
|
|
70493
70546
|
import { createHash as createHash14 } from "node:crypto";
|
|
70494
70547
|
import fs18 from "node:fs";
|
|
@@ -71015,18 +71068,14 @@ async function change(verb, argv, io, deps) {
|
|
|
71015
71068
|
]);
|
|
71016
71069
|
}
|
|
71017
71070
|
async function runGrant(argv, io, deps = defaultDeps) {
|
|
71018
|
-
const
|
|
71071
|
+
const end = argv.indexOf("--");
|
|
71072
|
+
const [sub, ...rest] = end < 0 ? argv : [...argv.slice(0, end), ...argv.slice(end + 1)];
|
|
71019
71073
|
if (sub === "show")
|
|
71020
71074
|
return show(rest, io);
|
|
71021
|
-
if (sub === undefined || sub.startsWith("--")
|
|
71075
|
+
if (sub === undefined || sub.startsWith("--"))
|
|
71022
71076
|
return show(argv, io);
|
|
71023
71077
|
if (sub === "set" || sub === "unset")
|
|
71024
71078
|
return change(sub, rest, io, deps);
|
|
71025
|
-
if (sub === "--help" || sub === "-h") {
|
|
71026
|
-
io.stdout(`usage: ${USAGE2}
|
|
71027
|
-
`);
|
|
71028
|
-
return 0;
|
|
71029
|
-
}
|
|
71030
71079
|
return usage2(io, `unknown subcommand "${sub}"`);
|
|
71031
71080
|
}
|
|
71032
71081
|
var USAGE2 = "workit grant show [<workspace>] [--all] | grant set <workspace> <kind>=<true|false|verified>… [defaultEndpoint=commit|pr|green|merged] [verification=self|independent] | grant unset <workspace> <kind>… (kinds: push, pr, merge, release, rerun, defaultEndpoint, verification)", AGENT_ENV, agentMarker = (env) => AGENT_ENV.find((name) => env[name]) ?? Object.keys(env).find((name) => name.startsWith("CODEX_") && env[name]), defaultDeps, parseValue = (raw) => raw === "true" || raw === "yes" || raw === "on" ? true : raw === "false" || raw === "no" || raw === "off" ? false : raw === "verified" ? "verified" : null, STOPS_AT, endpointLabel = (view) => view.effectiveEndpoint === view.defaultEndpoint ? view.defaultEndpoint : `${view.defaultEndpoint} (effective: ${view.effectiveEndpoint}${view.endpointReason ? `, ${view.endpointReason}` : ""})`, describe2 = (grants, configured, endpoint, verification) => [
|
|
@@ -71390,11 +71439,51 @@ var init_check = __esm(() => {
|
|
|
71390
71439
|
FINGERPRINT_VARS = ["CI", "NODE_ENV", "npm_config_script_shell", "NODE_OPTIONS", "SHELL"];
|
|
71391
71440
|
});
|
|
71392
71441
|
|
|
71393
|
-
// packages/workit-
|
|
71442
|
+
// packages/workit-core/src/forge/types.ts
|
|
71394
71443
|
var success2 = (data) => ({ ok: true, data }), failure3 = (code, error, unblock) => ({ ok: false, code, error, ...unblock ? { unblock } : {} });
|
|
71395
71444
|
|
|
71396
|
-
// packages/workit-
|
|
71445
|
+
// packages/workit-core/src/git/ops.ts
|
|
71397
71446
|
import { spawnSync as spawnSync16 } from "node:child_process";
|
|
71447
|
+
import { existsSync as existsSync18, readFileSync as readFileSync18 } from "node:fs";
|
|
71448
|
+
import path39 from "node:path";
|
|
71449
|
+
function operationInProgress(cwd) {
|
|
71450
|
+
const markers = [
|
|
71451
|
+
["rebase-merge", "rebase"],
|
|
71452
|
+
["rebase-apply", "rebase"],
|
|
71453
|
+
["MERGE_HEAD", "merge"],
|
|
71454
|
+
["CHERRY_PICK_HEAD", "cherry-pick"],
|
|
71455
|
+
["REVERT_HEAD", "revert"]
|
|
71456
|
+
];
|
|
71457
|
+
const run = git5(cwd, ["rev-parse", ...markers.flatMap(([name]) => ["--git-path", name])]);
|
|
71458
|
+
if (!run.ok)
|
|
71459
|
+
return null;
|
|
71460
|
+
const found = run.stdout.split(`
|
|
71461
|
+
`).map((line) => path39.resolve(cwd, line.trim()));
|
|
71462
|
+
const conflicted = () => git5(cwd, ["ls-files", "-u"]).stdout.trim() !== "";
|
|
71463
|
+
for (const [index, [, operation]] of markers.entries()) {
|
|
71464
|
+
const marker = found[index];
|
|
71465
|
+
if (!marker || !existsSync18(marker))
|
|
71466
|
+
continue;
|
|
71467
|
+
if (index === 1 && existsSync18(path39.join(marker, "applying")))
|
|
71468
|
+
return { operation: "am", commitAllowed: false, branch: null };
|
|
71469
|
+
if (index === 0 && existsSync18(path39.join(marker, "amend")) && !conflicted()) {
|
|
71470
|
+
let headName = "";
|
|
71471
|
+
try {
|
|
71472
|
+
headName = readFileSync18(path39.join(marker, "head-name"), "utf8").trim();
|
|
71473
|
+
} catch {}
|
|
71474
|
+
const branch = headName.startsWith("refs/heads/") ? headName.slice("refs/heads/".length) : null;
|
|
71475
|
+
return { operation, commitAllowed: branch !== null, branch };
|
|
71476
|
+
}
|
|
71477
|
+
if ((operation === "revert" || operation === "merge") && !conflicted())
|
|
71478
|
+
return { operation, commitAllowed: true, branch: null };
|
|
71479
|
+
return { operation, commitAllowed: false, branch: null };
|
|
71480
|
+
}
|
|
71481
|
+
return null;
|
|
71482
|
+
}
|
|
71483
|
+
function inProgressFailure(operation, verb) {
|
|
71484
|
+
const command = operation === "am" ? "git am" : `git ${operation}`;
|
|
71485
|
+
return failure3("blocked", `${operation.replace("-", "_")}_in_progress: a ${operation === "am" ? "git am" : operation} is in progress; finish or abort it before workit can ${verb}`, `resolve the conflicts, git add <files>, then ${command} --continue # or ${command} --abort to return to where you started`);
|
|
71486
|
+
}
|
|
71398
71487
|
function dirtEntries(cwd) {
|
|
71399
71488
|
const run = git5(cwd, ["status", "--porcelain=v1", "-z", "--untracked-files=all"]);
|
|
71400
71489
|
if (!run.ok)
|
|
@@ -71414,6 +71503,9 @@ function dirtEntries(cwd) {
|
|
|
71414
71503
|
function gitBranch(cwd, input) {
|
|
71415
71504
|
if (!headSha(cwd) && currentBranch(cwd) === null)
|
|
71416
71505
|
return failure3("invalid_input", "not inside a git repository with a commit");
|
|
71506
|
+
const progress = operationInProgress(cwd);
|
|
71507
|
+
if (progress)
|
|
71508
|
+
return inProgressFailure(progress.operation, "create a branch");
|
|
71417
71509
|
const explicitBase = input.base?.trim() || null;
|
|
71418
71510
|
const resolved = vcsConfig("resolve", cwd, {
|
|
71419
71511
|
track: input.track ?? null,
|
|
@@ -71518,53 +71610,156 @@ function lintCommitMessage(cwd, message) {
|
|
|
71518
71610
|
correction: `use a ${detected} commit subject`
|
|
71519
71611
|
};
|
|
71520
71612
|
}
|
|
71613
|
+
function messageTrailers(cwd, message) {
|
|
71614
|
+
const run = git5(cwd, [...TRAILER_CONFIG, "interpret-trailers", "--parse", "--no-divider"], {
|
|
71615
|
+
input: `${message}
|
|
71616
|
+
`
|
|
71617
|
+
});
|
|
71618
|
+
return run.ok ? run.stdout.split(`
|
|
71619
|
+
`).filter((line) => line.trim()) : [];
|
|
71620
|
+
}
|
|
71621
|
+
function withTrailers(cwd, message, trailers) {
|
|
71622
|
+
if (!trailers.length)
|
|
71623
|
+
return message;
|
|
71624
|
+
const run = git5(cwd, [
|
|
71625
|
+
...TRAILER_CONFIG,
|
|
71626
|
+
"interpret-trailers",
|
|
71627
|
+
"--no-divider",
|
|
71628
|
+
"--if-exists",
|
|
71629
|
+
"addIfDifferent",
|
|
71630
|
+
...trailers.flatMap((trailer) => ["--trailer", trailer])
|
|
71631
|
+
], { input: `${message}
|
|
71632
|
+
` });
|
|
71633
|
+
return run.ok ? run.stdout.trim() : `${message}
|
|
71634
|
+
|
|
71635
|
+
${trailers.join(`
|
|
71636
|
+
`)}`;
|
|
71637
|
+
}
|
|
71638
|
+
function branchesContaining(cwd, sha) {
|
|
71639
|
+
const run = git5(cwd, [
|
|
71640
|
+
"for-each-ref",
|
|
71641
|
+
"--format=%(refname)",
|
|
71642
|
+
"--contains",
|
|
71643
|
+
sha,
|
|
71644
|
+
"refs/heads",
|
|
71645
|
+
"refs/remotes"
|
|
71646
|
+
]);
|
|
71647
|
+
const names = new Set;
|
|
71648
|
+
for (const ref of run.ok ? run.stdout.split(`
|
|
71649
|
+
`) : []) {
|
|
71650
|
+
if (ref.startsWith("refs/heads/"))
|
|
71651
|
+
names.add(ref.slice("refs/heads/".length));
|
|
71652
|
+
else if (ref.startsWith("refs/remotes/")) {
|
|
71653
|
+
const name = ref.split("/").slice(3).join("/");
|
|
71654
|
+
if (name && name !== "HEAD")
|
|
71655
|
+
names.add(name);
|
|
71656
|
+
}
|
|
71657
|
+
}
|
|
71658
|
+
return names;
|
|
71659
|
+
}
|
|
71660
|
+
function sharedBranchContaining(cwd, sha, branch) {
|
|
71661
|
+
const resolved = vcsConfig("resolve", cwd);
|
|
71662
|
+
const defaults = new Set(resolved.ok === false ? [] : [resolved.defaultTargetBranch, resolved.baseBranch].map((value) => String(value ?? "")).filter(Boolean));
|
|
71663
|
+
for (const name of branchesContaining(cwd, sha))
|
|
71664
|
+
if (name !== branch && (defaults.has(name) || isProtectedTarget(cwd, name)))
|
|
71665
|
+
return name;
|
|
71666
|
+
return null;
|
|
71667
|
+
}
|
|
71521
71668
|
function gitCommit(cwd, input) {
|
|
71522
|
-
const
|
|
71523
|
-
if (!
|
|
71524
|
-
return failure3("invalid_input", "a commit message is required (-m <msg>)");
|
|
71669
|
+
const given = input.message?.trim() ?? "";
|
|
71670
|
+
if (!given && !input.amend)
|
|
71671
|
+
return failure3("invalid_input", "a commit message is required (-m <msg> or -F <file>)");
|
|
71525
71672
|
const paths = input.paths ?? [];
|
|
71526
71673
|
if (input.all && paths.length)
|
|
71527
71674
|
return failure3("invalid_input", "pass --all or paths, not both");
|
|
71528
|
-
const
|
|
71675
|
+
const progress = operationInProgress(cwd);
|
|
71676
|
+
if (progress && !progress.commitAllowed)
|
|
71677
|
+
return inProgressFailure(progress.operation, "commit");
|
|
71678
|
+
const branch = progress?.branch ?? currentBranch(cwd);
|
|
71529
71679
|
if (!branch)
|
|
71530
71680
|
return failure3("invalid_input", "HEAD is detached; commit on a branch (workit git branch <name>)");
|
|
71531
71681
|
if (isProtectedTarget(cwd, branch))
|
|
71532
71682
|
return failure3("blocked", `protected_branch: ${branch} is protected by the workspace branch policy; workit never commits to it`, "workit git branch <feature/name> # then commit there");
|
|
71533
|
-
const
|
|
71534
|
-
if (!
|
|
71535
|
-
return failure3("
|
|
71683
|
+
const previous = input.amend ? headSha(cwd) : null;
|
|
71684
|
+
if (input.amend && !previous)
|
|
71685
|
+
return failure3("invalid_input", `nothing to amend: ${branch} has no commit yet`);
|
|
71686
|
+
if (previous) {
|
|
71687
|
+
const shared = sharedBranchContaining(cwd, previous, branch);
|
|
71688
|
+
if (shared)
|
|
71689
|
+
return failure3("blocked", `amend_shared_commit: ${previous.slice(0, 12)} is already on ${shared}, so it is not ${branch}'s own commit; workit never rewrites it`, "workit git commit -m '<msg>' -- <paths> # add a new commit instead");
|
|
71690
|
+
}
|
|
71691
|
+
let message = given;
|
|
71692
|
+
let carried = [];
|
|
71693
|
+
if (given) {
|
|
71694
|
+
const lint = lintCommitMessage(cwd, given);
|
|
71695
|
+
if (!lint.ok)
|
|
71696
|
+
return failure3("blocked", lint.error, lint.correction);
|
|
71697
|
+
}
|
|
71698
|
+
if (previous) {
|
|
71699
|
+
const kept = git5(cwd, ["log", "-1", "--format=%B", previous]);
|
|
71700
|
+
if (!kept.ok)
|
|
71701
|
+
return failure3("failed", `could not read the message of ${branch}: ${gitError(kept)}`);
|
|
71702
|
+
if (given)
|
|
71703
|
+
carried = messageTrailers(cwd, kept.stdout.trim());
|
|
71704
|
+
else
|
|
71705
|
+
message = kept.stdout.trim();
|
|
71706
|
+
}
|
|
71536
71707
|
const session = input.actor.session;
|
|
71537
71708
|
if (session && !SESSION_SAFE.test(session))
|
|
71538
71709
|
return failure3("invalid_input", "WORKIT_SESSION_ID must be 1-128 characters of [A-Za-z0-9_.:@/+-]");
|
|
71539
|
-
const
|
|
71540
|
-
|
|
71541
|
-
|
|
71710
|
+
const changeRequired = !input.amend && !input.allowEmpty;
|
|
71711
|
+
const emptyAmend = previous !== null && git5(cwd, ["rev-parse", "--verify", "-q", `${previous}^{tree}`]).stdout.trim() === git5(cwd, ["rev-parse", "--verify", "-q", `${previous}~1^{tree}`]).stdout.trim();
|
|
71712
|
+
const args = ["commit", "--no-edit"];
|
|
71713
|
+
if (input.amend)
|
|
71714
|
+
args.push("--amend");
|
|
71715
|
+
if (input.allowEmpty || emptyAmend)
|
|
71716
|
+
args.push("--allow-empty");
|
|
71717
|
+
args.push("-m", withTrailers(cwd, message, [...carried, ...session ? [`Workit-Session: ${session}`] : []]));
|
|
71542
71718
|
if (paths.length) {
|
|
71543
71719
|
if (paths.some((value) => value.startsWith("-") || !value.trim()))
|
|
71544
71720
|
return failure3("invalid_input", "paths must not be empty or start with -");
|
|
71545
|
-
const
|
|
71546
|
-
|
|
71547
|
-
|
|
71721
|
+
const tracked = new Set(nulList(git5(cwd, ["ls-files", "-z", "--", ...paths]).stdout));
|
|
71722
|
+
const addable = paths.filter((value) => existsSync18(path39.resolve(cwd, value)) || [...tracked].some((file) => file === value || file.startsWith(`${value}/`)));
|
|
71723
|
+
if (addable.length) {
|
|
71724
|
+
const added = git5(cwd, ["add", "-A", "--", ...addable]);
|
|
71725
|
+
if (!added.ok)
|
|
71726
|
+
return failure3("failed", `git add failed: ${gitError(added)}`);
|
|
71727
|
+
}
|
|
71728
|
+
if (changeRequired && git5(cwd, ["diff", "--cached", "--quiet", "HEAD", "--", ...paths]).ok)
|
|
71729
|
+
return nothingToCommit(`${paths.join(", ")} has no change to commit`);
|
|
71548
71730
|
args.push("--", ...paths);
|
|
71549
71731
|
} else if (input.all) {
|
|
71550
71732
|
const added = git5(cwd, ["add", "-A"]);
|
|
71551
71733
|
if (!added.ok)
|
|
71552
71734
|
return failure3("failed", `git add failed: ${gitError(added)}`);
|
|
71553
|
-
|
|
71735
|
+
if (changeRequired && git5(cwd, ["diff", "--cached", "--quiet"]).ok)
|
|
71736
|
+
return nothingToCommit("the working tree is clean");
|
|
71737
|
+
} else if (changeRequired) {
|
|
71554
71738
|
const staged = git5(cwd, ["diff", "--cached", "--name-only", "-z"]);
|
|
71555
71739
|
if (staged.ok && !staged.stdout.replaceAll("\x00", "")) {
|
|
71556
71740
|
const dirt = dirtEntries(cwd);
|
|
71557
|
-
|
|
71741
|
+
if (!dirt.length)
|
|
71742
|
+
return nothingToCommit("the working tree is clean");
|
|
71743
|
+
return failure3("blocked", `nothing_staged: nothing is staged and workit never commits unrelated changes implicitly (${dirt.length} changed: ${dirt.slice(0, 5).map((entry) => entry.slice(3)).join(", ")}${dirt.length > 5 ? ", …" : ""})`, `workit git commit -m '<msg>' -- <paths> # or --all to commit every change`);
|
|
71558
71744
|
}
|
|
71559
71745
|
}
|
|
71560
|
-
const committed = git5(cwd, args, {
|
|
71746
|
+
const committed = git5(cwd, args, {
|
|
71747
|
+
timeoutMs: COMMIT_TIMEOUT_MS,
|
|
71748
|
+
env: input.env
|
|
71749
|
+
});
|
|
71561
71750
|
if (!committed.ok)
|
|
71562
|
-
return failure3("failed", `git commit failed
|
|
71751
|
+
return failure3("failed", `git commit failed (a hook or git refused it):
|
|
71752
|
+
${gitOutput(committed)}`);
|
|
71563
71753
|
const sha = headSha(cwd);
|
|
71564
71754
|
if (!sha)
|
|
71565
71755
|
return failure3("failed", "the commit did not resolve");
|
|
71566
|
-
const
|
|
71756
|
+
const merge = git5(cwd, ["rev-parse", "-q", "--verify", `${sha}^2`]).ok;
|
|
71757
|
+
const files = nulList(git5(cwd, merge ? ["diff", "--name-only", "-z", `${sha}^1`, sha] : ["diff-tree", "--root", "--no-commit-id", "--name-only", "-r", "-z", sha]).stdout);
|
|
71567
71758
|
const leftDirty = dirtEntries(cwd).length;
|
|
71759
|
+
const notes = [];
|
|
71760
|
+
const upstream = `refs/remotes/${pushRemoteName(cwd, branch) ?? "origin"}/${branch}`;
|
|
71761
|
+
if (previous && git5(cwd, ["merge-base", "--is-ancestor", previous, upstream]).ok)
|
|
71762
|
+
notes.push(`the amended commit ${previous.slice(0, 12)} was already pushed (${upstream.slice("refs/remotes/".length)}); publish the rewrite with: workit git push --force-with-lease`);
|
|
71568
71763
|
const listed = [];
|
|
71569
71764
|
let size = 0;
|
|
71570
71765
|
for (const file of files) {
|
|
@@ -71584,7 +71779,8 @@ function gitCommit(cwd, input) {
|
|
|
71584
71779
|
subject: (message.split(`
|
|
71585
71780
|
`, 1)[0] ?? "").slice(0, 200),
|
|
71586
71781
|
files: listed,
|
|
71587
|
-
fileCount: files.length
|
|
71782
|
+
fileCount: files.length,
|
|
71783
|
+
...previous ? { amended: previous } : {}
|
|
71588
71784
|
});
|
|
71589
71785
|
return success2({
|
|
71590
71786
|
sha,
|
|
@@ -71593,10 +71789,15 @@ function gitCommit(cwd, input) {
|
|
|
71593
71789
|
files,
|
|
71594
71790
|
leftDirty,
|
|
71595
71791
|
session,
|
|
71792
|
+
amended: previous,
|
|
71793
|
+
notes,
|
|
71596
71794
|
recorded: row.ok ? { id: String(row.value.id) } : { error: row.error }
|
|
71597
71795
|
});
|
|
71598
71796
|
}
|
|
71599
71797
|
function pushPreflight(cwd, options = {}) {
|
|
71798
|
+
const progress = operationInProgress(cwd);
|
|
71799
|
+
if (progress)
|
|
71800
|
+
return inProgressFailure(progress.operation, "push");
|
|
71600
71801
|
const branch = options.branch ?? currentBranch(cwd);
|
|
71601
71802
|
if (!branch)
|
|
71602
71803
|
return failure3("invalid_input", "HEAD is detached; push a branch");
|
|
@@ -71635,11 +71836,35 @@ function recordedRemoteTip(cwd, plan) {
|
|
|
71635
71836
|
return;
|
|
71636
71837
|
}
|
|
71637
71838
|
function includesRemoteTip(cwd, branch, tip) {
|
|
71638
|
-
|
|
71839
|
+
const ref = `refs/heads/${branch}`;
|
|
71840
|
+
if (git5(cwd, ["merge-base", "--is-ancestor", tip, ref]).ok)
|
|
71841
|
+
return true;
|
|
71842
|
+
const reflog = git5(cwd, ["reflog", "show", "--format=%H", ref, "--"]);
|
|
71843
|
+
const former = [
|
|
71844
|
+
...new Set((reflog.ok ? reflog.stdout : "").split(`
|
|
71845
|
+
`).map((line) => line.trim()).filter(Boolean))
|
|
71846
|
+
];
|
|
71847
|
+
if (former.includes(tip))
|
|
71639
71848
|
return true;
|
|
71640
|
-
|
|
71641
|
-
|
|
71642
|
-
|
|
71849
|
+
if (!former.length)
|
|
71850
|
+
return false;
|
|
71851
|
+
const outside = git5(cwd, ["rev-list", "-n", "1", "--stdin"], {
|
|
71852
|
+
input: `${tip}
|
|
71853
|
+
${former.map((sha) => `^${sha}`).join(`
|
|
71854
|
+
`)}
|
|
71855
|
+
`
|
|
71856
|
+
});
|
|
71857
|
+
return outside.ok && !outside.stdout.trim();
|
|
71858
|
+
}
|
|
71859
|
+
function patchEquivalent(cwd, branch, tip) {
|
|
71860
|
+
const ref = `refs/heads/${branch}`;
|
|
71861
|
+
const merges = git5(cwd, ["rev-list", "--count", "--merges", `${ref}..${tip}`]);
|
|
71862
|
+
if (!merges.ok || merges.stdout.trim() !== "0")
|
|
71863
|
+
return false;
|
|
71864
|
+
const cherry = git5(cwd, ["cherry", ref, tip]);
|
|
71865
|
+
const lines = cherry.ok ? cherry.stdout.split(`
|
|
71866
|
+
`).filter(Boolean) : [];
|
|
71867
|
+
return lines.length > 0 && lines.every((line) => line.startsWith("-"));
|
|
71643
71868
|
}
|
|
71644
71869
|
function executePush(cwd, plan, input) {
|
|
71645
71870
|
const before = remoteRefTip(cwd, plan.rawUrl, `refs/heads/${plan.branch}`);
|
|
@@ -71674,9 +71899,17 @@ ${run.stdout}`;
|
|
|
71674
71899
|
return failure3("unavailable", `git push to ${plan.url} timed out`);
|
|
71675
71900
|
if (/stale info/iu.test(text))
|
|
71676
71901
|
return failure3("blocked", `lease_mismatch: ${plan.remote}/${plan.branch} moved while pushing`, `git fetch ${plan.remote} ${plan.branch} && git rebase ${plan.remote}/${plan.branch} # or merge it; then: workit git push`);
|
|
71902
|
+
const rejected = /non-fast-forward|fetch first|\[rejected\]/iu.test(text);
|
|
71903
|
+
const integrated = rejected && before.sha !== null && includesRemoteTip(cwd, plan.branch, before.sha);
|
|
71904
|
+
const equivalent = rejected && !integrated && before.sha !== null && patchEquivalent(cwd, plan.branch, before.sha);
|
|
71905
|
+
if (before.sha !== null && (integrated || equivalent)) {
|
|
71906
|
+
const lease = recordedRemoteTip(cwd, plan) === before.sha ? "workit git push --force-with-lease" : `workit git push --force-with-lease --expect ${before.sha}`;
|
|
71907
|
+
return failure3("failed", integrated ? `non_fast_forward: local ${plan.branch} was rewritten (amend or rebase) after ${plan.remote}/${plan.branch} (${before.sha.slice(0, 12)}) was pushed; that tip is already part of the local history, so do not fetch and rebase` : `non_fast_forward: every commit on ${plan.remote}/${plan.branch} (${before.sha.slice(0, 12)}) has a patch-equivalent commit in local ${plan.branch} (rebased elsewhere); fetching and rebasing would apply them twice`, integrated ? lease : `${lease} --overwrite-unintegrated # after checking ${plan.remote}/${plan.branch} holds nothing else`);
|
|
71908
|
+
}
|
|
71677
71909
|
if (/non-fast-forward|fetch first|\[rejected\]/iu.test(text))
|
|
71678
71910
|
return failure3("failed", `non_fast_forward: ${plan.remote}/${plan.branch} has commits this branch does not`, `git fetch ${plan.remote} && git rebase ${plan.remote}/${plan.branch} # or, if the rewrite is intended: workit git push --force-with-lease`);
|
|
71679
|
-
return failure3("failed", `git push to ${plan.url} failed:
|
|
71911
|
+
return failure3("failed", `git push to ${plan.url} failed:
|
|
71912
|
+
${gitOutput(run)}`);
|
|
71680
71913
|
}
|
|
71681
71914
|
pushed = true;
|
|
71682
71915
|
}
|
|
@@ -71735,7 +71968,11 @@ function deleteRemoteBranch(cwd, target, branch, expectedTip, options = {}) {
|
|
|
71735
71968
|
return { ok: true };
|
|
71736
71969
|
const text = `${run.stderr}
|
|
71737
71970
|
${run.stdout}`;
|
|
71738
|
-
return /stale info|cannot lock ref|fetch first|non-fast-forward/iu.test(text) ? {
|
|
71971
|
+
return /stale info|cannot lock ref|fetch first|non-fast-forward/iu.test(text) ? {
|
|
71972
|
+
ok: false,
|
|
71973
|
+
lease: true,
|
|
71974
|
+
error: "the remote branch tip changed before deletion"
|
|
71975
|
+
} : { ok: false, lease: false, error: gitError(run) };
|
|
71739
71976
|
}
|
|
71740
71977
|
var COMMIT_TIMEOUT_MS, PUSH_TIMEOUT_MS = 120000, git5 = (cwd, args, options = {}) => {
|
|
71741
71978
|
const result = spawnSync16("git", args, {
|
|
@@ -71746,7 +71983,7 @@ var COMMIT_TIMEOUT_MS, PUSH_TIMEOUT_MS = 120000, git5 = (cwd, args, options = {}
|
|
|
71746
71983
|
timeout: options.timeoutMs ?? GIT_TIMEOUTS.local,
|
|
71747
71984
|
killSignal: "SIGKILL",
|
|
71748
71985
|
windowsHide: true,
|
|
71749
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
71986
|
+
...options.input === undefined ? { stdio: ["ignore", "pipe", "pipe"] } : { input: options.input, stdio: ["pipe", "pipe", "pipe"] }
|
|
71750
71987
|
});
|
|
71751
71988
|
return {
|
|
71752
71989
|
ok: result.status === 0,
|
|
@@ -71758,7 +71995,22 @@ var COMMIT_TIMEOUT_MS, PUSH_TIMEOUT_MS = 120000, git5 = (cwd, args, options = {}
|
|
|
71758
71995
|
const lines = redactText(`${run.stderr}
|
|
71759
71996
|
${run.stdout ?? ""}`).split(/\r?\n/u).map((value) => value.trim()).filter((value) => value && !value.startsWith("hint:"));
|
|
71760
71997
|
return lines.slice(-max).join(" / ").slice(0, 400) || "git failed";
|
|
71761
|
-
},
|
|
71998
|
+
}, OUTPUT_LINES = 200, OUTPUT_LINE_CHARS = 1000, gitOutput = (run) => {
|
|
71999
|
+
const lines = redactText(`${run.stderr}
|
|
72000
|
+
${run.stdout ?? ""}`).split(/\r?\n/u).map((value) => value.trimEnd()).filter((value) => value.trim() && !value.trimStart().startsWith("hint:")).map((value) => value.length > OUTPUT_LINE_CHARS ? `${value.slice(0, OUTPUT_LINE_CHARS)}…` : value);
|
|
72001
|
+
if (!lines.length)
|
|
72002
|
+
return "git failed";
|
|
72003
|
+
if (lines.length <= OUTPUT_LINES)
|
|
72004
|
+
return lines.join(`
|
|
72005
|
+
`);
|
|
72006
|
+
const half = OUTPUT_LINES / 2;
|
|
72007
|
+
return [
|
|
72008
|
+
...lines.slice(0, half),
|
|
72009
|
+
`… ${lines.length - OUTPUT_LINES} lines omitted …`,
|
|
72010
|
+
...lines.slice(-half)
|
|
72011
|
+
].join(`
|
|
72012
|
+
`);
|
|
72013
|
+
}, validRefName = (cwd, name) => !name.startsWith("-") && git5(cwd, ["check-ref-format", "--branch", name]).ok, nulList = (text) => text.split("\x00").filter(Boolean), SESSION_SAFE, TRAILER_CONFIG, nothingToCommit = (what) => failure3("failed", `nothing_to_commit: ${what}`, "workit git commit --allow-empty -m '<msg>' # only to record an empty commit on purpose"), SHA;
|
|
71762
72014
|
var init_ops = __esm(() => {
|
|
71763
72015
|
init_branch();
|
|
71764
72016
|
init_commit_flavors();
|
|
@@ -71770,15 +72022,16 @@ var init_ops = __esm(() => {
|
|
|
71770
72022
|
init_rev();
|
|
71771
72023
|
COMMIT_TIMEOUT_MS = 10 * 60000;
|
|
71772
72024
|
SESSION_SAFE = /^[\w.:@/+-]{1,128}$/u;
|
|
72025
|
+
TRAILER_CONFIG = ["-c", "trailer.separators=:", "-c", "trailer.where=end"];
|
|
71773
72026
|
SHA = /^[0-9a-f]{40,64}$/u;
|
|
71774
72027
|
});
|
|
71775
72028
|
|
|
71776
|
-
// packages/workit-
|
|
72029
|
+
// packages/workit-core/src/forge/reruns.ts
|
|
71777
72030
|
import fs19 from "node:fs";
|
|
71778
|
-
import
|
|
72031
|
+
import path40 from "node:path";
|
|
71779
72032
|
function rerunLogPath(cwd) {
|
|
71780
72033
|
const common = gitCommonDir(cwd);
|
|
71781
|
-
return common ?
|
|
72034
|
+
return common ? path40.join(common, "workit", "ci-reruns.jsonl") : null;
|
|
71782
72035
|
}
|
|
71783
72036
|
function rerunCounts(cwd, key) {
|
|
71784
72037
|
const counts = new Map;
|
|
@@ -71813,7 +72066,7 @@ function recordReruns(cwd, rows) {
|
|
|
71813
72066
|
if (!file)
|
|
71814
72067
|
return false;
|
|
71815
72068
|
try {
|
|
71816
|
-
fs19.mkdirSync(
|
|
72069
|
+
fs19.mkdirSync(path40.dirname(file), { recursive: true });
|
|
71817
72070
|
fs19.appendFileSync(file, rows.map((row) => `${JSON.stringify(row)}
|
|
71818
72071
|
`).join(""));
|
|
71819
72072
|
return true;
|
|
@@ -71826,7 +72079,7 @@ function withRerunLock(cwd, fn) {
|
|
|
71826
72079
|
if (!file)
|
|
71827
72080
|
return fn();
|
|
71828
72081
|
const lock = `${file.slice(0, -".jsonl".length)}.lock`;
|
|
71829
|
-
fs19.mkdirSync(
|
|
72082
|
+
fs19.mkdirSync(path40.dirname(lock), { recursive: true });
|
|
71830
72083
|
const until = Date.now() + LOCK_WAIT_MS2;
|
|
71831
72084
|
for (;; ) {
|
|
71832
72085
|
try {
|
|
@@ -71864,7 +72117,7 @@ var init_reruns = __esm(() => {
|
|
|
71864
72117
|
init_rev();
|
|
71865
72118
|
});
|
|
71866
72119
|
|
|
71867
|
-
// packages/workit-
|
|
72120
|
+
// packages/workit-core/src/forge/report.ts
|
|
71868
72121
|
function gatingChecks(status) {
|
|
71869
72122
|
const required = status.checks.filter((check) => check.required === true);
|
|
71870
72123
|
const protectionNamesChecks = (status.requiredContexts?.length ?? 0) > 0;
|
|
@@ -72218,7 +72471,7 @@ var init_report = __esm(() => {
|
|
|
72218
72471
|
GITHUB_MERGEABLE = new Set(["clean", "unstable", "has_hooks"]);
|
|
72219
72472
|
});
|
|
72220
72473
|
|
|
72221
|
-
// packages/workit-
|
|
72474
|
+
// packages/workit-core/src/forge/pr-ops.ts
|
|
72222
72475
|
import { spawnSync as spawnSync17 } from "node:child_process";
|
|
72223
72476
|
function fillFromCommits(cwd, resolved, base) {
|
|
72224
72477
|
const tracking = `refs/remotes/${resolved.baseRemote}/${base}`;
|
|
@@ -72339,13 +72592,19 @@ async function createPullRequest(cwd, resolved, input, sleep) {
|
|
|
72339
72592
|
head: sha,
|
|
72340
72593
|
created,
|
|
72341
72594
|
draft: input.draft,
|
|
72342
|
-
recorded: row.ok ? { id: String(row.value.id) } : { error: row.error }
|
|
72595
|
+
recorded: row.ok ? { id: String(row.value.id) } : { error: row.error },
|
|
72596
|
+
next: createNext(cwd)
|
|
72343
72597
|
});
|
|
72344
72598
|
}
|
|
72345
72599
|
async function mergePullRequest(cwd, resolved, input, sleep) {
|
|
72346
72600
|
const grant = requireGrant(cwd, "merge");
|
|
72347
72601
|
if (!grant.allowed)
|
|
72348
72602
|
return refuse(grant.error, grant.unblock, { reason: "grant_required" });
|
|
72603
|
+
const bypass = input.unverified ?? null;
|
|
72604
|
+
if (bypass && !bypass.reason.trim())
|
|
72605
|
+
return failure3("invalid_input", "--unverified needs --reason <why the user asked for it>");
|
|
72606
|
+
if (bypass && !grant.allowUnverified)
|
|
72607
|
+
return refuse(`unverified_refused: workspace ${grant.workspace ? `"${grant.workspace}"` : "(none)"} grants merge: "verified", which never merges without an accepted independent verdict`, "a non-author session verifies the head (workit-review), then merge without --unverified", { reason: "unverified_refused" });
|
|
72349
72608
|
const number = selectPr(cwd, resolved, { pr: input.pr });
|
|
72350
72609
|
if (!number.ok)
|
|
72351
72610
|
return number;
|
|
@@ -72379,27 +72638,40 @@ async function mergePullRequest(cwd, resolved, input, sleep) {
|
|
|
72379
72638
|
if (reason)
|
|
72380
72639
|
return refuse(`protected_branch: --delete-branch would delete ${branch}, which ${reason}; workit never deletes it`, `workit pr merge${input.pr ? ` --pr ${doc.number}` : ""} --method ${input.method} # without --delete-branch`, { reason: "protected_branch" });
|
|
72381
72640
|
}
|
|
72641
|
+
const ledger = readLedger(cwd);
|
|
72642
|
+
if (!ledger.ok)
|
|
72643
|
+
return ledger;
|
|
72644
|
+
const check = checkVerdicts(cwd, branch, ledger.value.rows);
|
|
72645
|
+
const summary = { head: check.head, accepted: check.accepted, authors: check.authors };
|
|
72646
|
+
const covered = check.head === head && check.accepted.accepted;
|
|
72382
72647
|
let verdict = {
|
|
72383
|
-
required:
|
|
72384
|
-
accepted:
|
|
72385
|
-
verdictId: null
|
|
72648
|
+
required: true,
|
|
72649
|
+
accepted: covered,
|
|
72650
|
+
verdictId: covered && typeof check.accepted.verdict?.id === "string" ? check.accepted.verdict.id : null
|
|
72386
72651
|
};
|
|
72387
|
-
|
|
72388
|
-
|
|
72389
|
-
|
|
72390
|
-
|
|
72391
|
-
const
|
|
72392
|
-
const
|
|
72393
|
-
|
|
72394
|
-
|
|
72395
|
-
|
|
72396
|
-
|
|
72397
|
-
|
|
72398
|
-
|
|
72399
|
-
|
|
72400
|
-
|
|
72401
|
-
};
|
|
72402
|
-
|
|
72652
|
+
let unverified = null;
|
|
72653
|
+
if (!covered && bypass && check.accepted.reasons.includes("failing_verdict"))
|
|
72654
|
+
return refuse(`failed_verdict: ${label} has a current independent failed verdict${typeof check.accepted.verdict?.id === "string" ? ` (${check.accepted.verdict.id})` : ""}; --unverified never merges over a rejection`, "a new independent verdict on the head supersedes it", { reason: "failed_verdict", verdict: summary });
|
|
72655
|
+
if (!covered && bypass) {
|
|
72656
|
+
const reason = bypass.reason.trim();
|
|
72657
|
+
const recorded = appendObserved(cwd, {
|
|
72658
|
+
type: "merge.unverified",
|
|
72659
|
+
actor: input.actor,
|
|
72660
|
+
branch,
|
|
72661
|
+
head,
|
|
72662
|
+
pr: doc.number,
|
|
72663
|
+
base: doc.base,
|
|
72664
|
+
reason,
|
|
72665
|
+
grant: grant.source
|
|
72666
|
+
});
|
|
72667
|
+
if (!recorded.ok)
|
|
72668
|
+
return failure3("failed", `unverified_unrecorded: the --unverified bypass could not be recorded (${recorded.error}); nothing was merged`);
|
|
72669
|
+
verdict = { required: false, accepted: false, verdictId: null };
|
|
72670
|
+
unverified = { reason, recorded: String(recorded.value.id) };
|
|
72671
|
+
} else if (check.head !== head)
|
|
72672
|
+
return refuse(`head_mismatch: the verdict check reads ${branch} at ${check.head?.slice(0, 12) ?? "(missing)"} but ${label} is at ${head.slice(0, 12)}`, `git fetch && git switch ${branch} && git merge --ff-only @{u} # then re-verify that head`, { reason: "head_mismatch", verdict: summary });
|
|
72673
|
+
else if (!covered)
|
|
72674
|
+
return refuse(`NEEDS_VERDICT: ${label} has no accepted independent verdict for ${head.slice(0, 12)} (${check.accepted.reasons.join(", ")})`, `an independent session verifies the head and runs: workit ledger verdict verified --how "<what was exercised>" --branch ${branch}${grant.allowUnverified ? `; or, only if the user asks to merge unverified: workit pr merge --unverified --reason "<why>"` : ""}`, { reason: "needs_verdict", verdict: summary });
|
|
72403
72675
|
const merged = resolved.forge.merge(doc.number, { sha: head, method: input.method });
|
|
72404
72676
|
if (!merged.ok)
|
|
72405
72677
|
return merged;
|
|
@@ -72437,6 +72709,7 @@ async function mergePullRequest(cwd, resolved, input, sleep) {
|
|
|
72437
72709
|
mergeSha: merged.data.mergeSha,
|
|
72438
72710
|
method: input.method,
|
|
72439
72711
|
verdictId: verdict.verdictId,
|
|
72712
|
+
...unverified ? { unverified: unverified.recorded } : {},
|
|
72440
72713
|
grant: grant.source
|
|
72441
72714
|
});
|
|
72442
72715
|
return {
|
|
@@ -72450,6 +72723,7 @@ async function mergePullRequest(cwd, resolved, input, sleep) {
|
|
|
72450
72723
|
method: input.method,
|
|
72451
72724
|
mergeSha: merged.data.mergeSha,
|
|
72452
72725
|
verdict,
|
|
72726
|
+
unverified,
|
|
72453
72727
|
grant: { source: grant.source },
|
|
72454
72728
|
deletedBranch,
|
|
72455
72729
|
recorded: row.ok ? { id: String(row.value.id) } : { error: row.error },
|
|
@@ -72458,7 +72732,10 @@ async function mergePullRequest(cwd, resolved, input, sleep) {
|
|
|
72458
72732
|
}
|
|
72459
72733
|
};
|
|
72460
72734
|
}
|
|
72461
|
-
var VERIFY_DELAYS_MS, noun = (resolved) => resolved.forge.kind === "github" ? "pull request" : "merge request", grantBlocked = (decision) => failure3("blocked", decision.error, decision.unblock),
|
|
72735
|
+
var VERIFY_DELAYS_MS, noun = (resolved) => resolved.forge.kind === "github" ? "pull request" : "merge request", grantBlocked = (decision) => failure3("blocked", decision.error, decision.unblock), AFTER_REVIEW, createNext = (cwd) => {
|
|
72736
|
+
const endpoint = resolveAutonomy(cwd).effectiveEndpoint;
|
|
72737
|
+
return `a non-author verifies the head (workit-review); the endpoint is ${endpoint}, so ${AFTER_REVIEW[endpoint]}`;
|
|
72738
|
+
}, mergeBackFor = (cwd, base) => {
|
|
72462
72739
|
try {
|
|
72463
72740
|
const owners = workspaceReleaseTracks(cwd).tracks.filter((track) => track.productionBranch === base);
|
|
72464
72741
|
if (owners.length !== 1)
|
|
@@ -72487,6 +72764,12 @@ var init_pr_ops = __esm(() => {
|
|
|
72487
72764
|
init_ledger();
|
|
72488
72765
|
init_report();
|
|
72489
72766
|
VERIFY_DELAYS_MS = [1000, 2000, 4000];
|
|
72767
|
+
AFTER_REVIEW = {
|
|
72768
|
+
commit: "stop here; review comes when the user asks",
|
|
72769
|
+
pr: "stop here; review comes when the user asks",
|
|
72770
|
+
green: "babysit it to merge-ready, never merging",
|
|
72771
|
+
merged: "babysit it, then land it after verification"
|
|
72772
|
+
};
|
|
72490
72773
|
NEXT_HINTS = {
|
|
72491
72774
|
RESOLVE_CONFLICTS: "rebase onto the base, resolve, then workit git push --force-with-lease",
|
|
72492
72775
|
REBASE: "rebase onto the base, then workit git push --force-with-lease",
|
|
@@ -72501,16 +72784,16 @@ var init_pr_ops = __esm(() => {
|
|
|
72501
72784
|
};
|
|
72502
72785
|
});
|
|
72503
72786
|
|
|
72504
|
-
// packages/workit-
|
|
72787
|
+
// packages/workit-core/src/forge/exec.ts
|
|
72505
72788
|
import { spawnSync as spawnSync18 } from "node:child_process";
|
|
72506
72789
|
import fs20 from "node:fs";
|
|
72507
|
-
import
|
|
72790
|
+
import path41 from "node:path";
|
|
72508
72791
|
function findExecutable(bin, env) {
|
|
72509
|
-
const dirs = (env.PATH ?? env.Path ?? "").split(
|
|
72792
|
+
const dirs = (env.PATH ?? env.Path ?? "").split(path41.delimiter).filter(Boolean);
|
|
72510
72793
|
const exts = process.platform === "win32" ? [".exe"] : [""];
|
|
72511
72794
|
for (const dir of dirs)
|
|
72512
72795
|
for (const ext of exts) {
|
|
72513
|
-
const candidate =
|
|
72796
|
+
const candidate = path41.join(dir, `${bin}${ext}`);
|
|
72514
72797
|
try {
|
|
72515
72798
|
const stat = fs20.statSync(candidate);
|
|
72516
72799
|
if (stat.isFile())
|
|
@@ -72619,7 +72902,7 @@ var init_exec = __esm(() => {
|
|
|
72619
72902
|
MAX_BUFFER2 = 64 * 1024 * 1024;
|
|
72620
72903
|
});
|
|
72621
72904
|
|
|
72622
|
-
// packages/workit-
|
|
72905
|
+
// packages/workit-core/src/forge/github.ts
|
|
72623
72906
|
function checkFromContext(node) {
|
|
72624
72907
|
const required = node.isRequired ?? null;
|
|
72625
72908
|
if (node.__typename === "StatusContext") {
|
|
@@ -72918,7 +73201,7 @@ var init_github = __esm(() => {
|
|
|
72918
73201
|
]);
|
|
72919
73202
|
});
|
|
72920
73203
|
|
|
72921
|
-
// packages/workit-
|
|
73204
|
+
// packages/workit-core/src/forge/gitlab.ts
|
|
72922
73205
|
function checkFromBridge(bridge, pipelineId, scope) {
|
|
72923
73206
|
const status = bridge.downstream_pipeline?.status ?? bridge.status;
|
|
72924
73207
|
const allow = bridge.allow_failure === true;
|
|
@@ -73206,7 +73489,7 @@ var init_gitlab = __esm(() => {
|
|
|
73206
73489
|
UNSETTLED = new Set(["checking", "unchecked", "preparing", "approvals_syncing"]);
|
|
73207
73490
|
});
|
|
73208
73491
|
|
|
73209
|
-
// packages/workit-
|
|
73492
|
+
// packages/workit-core/src/forge/resolve.ts
|
|
73210
73493
|
import fs21 from "node:fs";
|
|
73211
73494
|
function resolveForge(cwd, options = {}) {
|
|
73212
73495
|
let workspace;
|
|
@@ -73326,7 +73609,7 @@ var init_resolve = __esm(() => {
|
|
|
73326
73609
|
init_gitlab();
|
|
73327
73610
|
});
|
|
73328
73611
|
|
|
73329
|
-
// packages/workit-
|
|
73612
|
+
// packages/workit-core/src/duration.ts
|
|
73330
73613
|
function parseDuration2(value) {
|
|
73331
73614
|
const text = value.trim().toLowerCase();
|
|
73332
73615
|
if (/^\d+(?:\.\d+)?$/u.test(text))
|
|
@@ -73358,6 +73641,10 @@ function parseFlags(argv, spec) {
|
|
|
73358
73641
|
const parsed = { values: {}, booleans: new Set, lists: {}, positionals: [] };
|
|
73359
73642
|
for (let index = 0;index < argv.length; index += 1) {
|
|
73360
73643
|
const arg = argv[index];
|
|
73644
|
+
if (arg === "--") {
|
|
73645
|
+
parsed.positionals.push(...argv.slice(index + 1));
|
|
73646
|
+
break;
|
|
73647
|
+
}
|
|
73361
73648
|
if (arg === "--json")
|
|
73362
73649
|
continue;
|
|
73363
73650
|
if (!arg.startsWith("--")) {
|
|
@@ -73495,8 +73782,8 @@ var exports_pr = {};
|
|
|
73495
73782
|
__export(exports_pr, {
|
|
73496
73783
|
run: () => run10
|
|
73497
73784
|
});
|
|
73498
|
-
import { readFileSync as
|
|
73499
|
-
import
|
|
73785
|
+
import { readFileSync as readFileSync19 } from "node:fs";
|
|
73786
|
+
import path42 from "node:path";
|
|
73500
73787
|
async function status(argv, io) {
|
|
73501
73788
|
const flags = parseFlags(argv, { pr: "value", branch: "value", "log-lines": "value" });
|
|
73502
73789
|
if (typeof flags === "string")
|
|
@@ -73567,7 +73854,7 @@ async function create4(argv, io) {
|
|
|
73567
73854
|
let body = flags.values.body ?? null;
|
|
73568
73855
|
if (flags.values["body-file"] !== undefined) {
|
|
73569
73856
|
try {
|
|
73570
|
-
body =
|
|
73857
|
+
body = readFileSync19(path42.resolve(io.cwd, flags.values["body-file"]), "utf8");
|
|
73571
73858
|
} catch {
|
|
73572
73859
|
return usage3(io, `cannot read --body-file ${flags.values["body-file"]}`, CREATE_USAGE);
|
|
73573
73860
|
}
|
|
@@ -73912,6 +74199,8 @@ var exports_git = {};
|
|
|
73912
74199
|
__export(exports_git, {
|
|
73913
74200
|
run: () => run12
|
|
73914
74201
|
});
|
|
74202
|
+
import { readFileSync as readFileSync20 } from "node:fs";
|
|
74203
|
+
import path43 from "node:path";
|
|
73915
74204
|
async function branch(argv, io) {
|
|
73916
74205
|
const flags = parseFlags(argv, {
|
|
73917
74206
|
base: "value",
|
|
@@ -73948,7 +74237,15 @@ async function branch(argv, io) {
|
|
|
73948
74237
|
]);
|
|
73949
74238
|
}
|
|
73950
74239
|
function parseCommit(argv) {
|
|
73951
|
-
const out = {
|
|
74240
|
+
const out = {
|
|
74241
|
+
messages: [],
|
|
74242
|
+
files: [],
|
|
74243
|
+
all: false,
|
|
74244
|
+
amend: false,
|
|
74245
|
+
noEdit: false,
|
|
74246
|
+
allowEmpty: false,
|
|
74247
|
+
paths: []
|
|
74248
|
+
};
|
|
73952
74249
|
for (let index = 0;index < argv.length; index += 1) {
|
|
73953
74250
|
const arg = argv[index];
|
|
73954
74251
|
if (arg === "--") {
|
|
@@ -73957,23 +74254,24 @@ function parseCommit(argv) {
|
|
|
73957
74254
|
}
|
|
73958
74255
|
if (arg === "--json")
|
|
73959
74256
|
continue;
|
|
73960
|
-
|
|
73961
|
-
|
|
74257
|
+
const flag = COMMIT_SWITCHES[arg];
|
|
74258
|
+
if (flag) {
|
|
74259
|
+
out[flag] = true;
|
|
73962
74260
|
continue;
|
|
73963
74261
|
}
|
|
73964
|
-
|
|
73965
|
-
|
|
73966
|
-
|
|
73967
|
-
|
|
73968
|
-
|
|
73969
|
-
|
|
73970
|
-
|
|
73971
|
-
|
|
73972
|
-
|
|
73973
|
-
|
|
73974
|
-
|
|
73975
|
-
|
|
73976
|
-
|
|
74262
|
+
const valued = [
|
|
74263
|
+
["-m", "--message", out.messages],
|
|
74264
|
+
["-F", "--file", out.files]
|
|
74265
|
+
].find(([shortName, longName]) => arg === shortName || arg === longName || arg.startsWith(`${longName}=`) || arg.startsWith(shortName) && arg.length > 2);
|
|
74266
|
+
if (valued) {
|
|
74267
|
+
const [shortName, longName, into] = valued;
|
|
74268
|
+
if (arg === shortName || arg === longName) {
|
|
74269
|
+
const value = argv[++index];
|
|
74270
|
+
if (value === undefined)
|
|
74271
|
+
return `${arg} requires a ${shortName === "-m" ? "message" : "file"}`;
|
|
74272
|
+
into.push(value);
|
|
74273
|
+
} else
|
|
74274
|
+
into.push(arg.startsWith(`${longName}=`) ? arg.slice(longName.length + 1) : arg.slice(2));
|
|
73977
74275
|
continue;
|
|
73978
74276
|
}
|
|
73979
74277
|
if (arg.startsWith("-"))
|
|
@@ -73982,20 +74280,48 @@ function parseCommit(argv) {
|
|
|
73982
74280
|
}
|
|
73983
74281
|
return out;
|
|
73984
74282
|
}
|
|
74283
|
+
function commitMessage(parsed, io) {
|
|
74284
|
+
if (parsed.messages.length && parsed.files.length)
|
|
74285
|
+
return { error: "pass -m or -F, not both" };
|
|
74286
|
+
if (parsed.files.length > 1)
|
|
74287
|
+
return { error: "-F takes one file" };
|
|
74288
|
+
const [file] = parsed.files;
|
|
74289
|
+
if (file === undefined)
|
|
74290
|
+
return parsed.messages.join(`
|
|
74291
|
+
|
|
74292
|
+
`);
|
|
74293
|
+
try {
|
|
74294
|
+
return file === "-" ? readFileSync20(0, "utf8") : readFileSync20(path43.resolve(io.cwd, file), "utf8");
|
|
74295
|
+
} catch (error) {
|
|
74296
|
+
return {
|
|
74297
|
+
error: `cannot read -F ${file}: ${error instanceof Error ? error.message : String(error)}`
|
|
74298
|
+
};
|
|
74299
|
+
}
|
|
74300
|
+
}
|
|
73985
74301
|
async function commit(argv, io) {
|
|
73986
74302
|
const parsed = parseCommit(argv);
|
|
73987
74303
|
if (typeof parsed === "string")
|
|
73988
74304
|
return usage3(io, parsed, COMMIT_USAGE);
|
|
73989
|
-
if (!parsed.messages.length)
|
|
73990
|
-
return usage3(io, "missing -m <msg>", COMMIT_USAGE);
|
|
73991
74305
|
if (parsed.all && parsed.paths.length)
|
|
73992
74306
|
return usage3(io, "pass --all or paths, not both", COMMIT_USAGE);
|
|
74307
|
+
if (parsed.noEdit && !parsed.amend)
|
|
74308
|
+
return usage3(io, "--no-edit only applies with --amend", COMMIT_USAGE);
|
|
74309
|
+
const given = parsed.messages.length + parsed.files.length > 0;
|
|
74310
|
+
if (parsed.noEdit && given)
|
|
74311
|
+
return usage3(io, "--no-edit keeps the message; drop -m/-F or --no-edit", COMMIT_USAGE);
|
|
74312
|
+
if (!given && !parsed.noEdit)
|
|
74313
|
+
return usage3(io, parsed.amend ? "--amend needs -m/-F or --no-edit" : "missing -m <msg> or -F <file>", COMMIT_USAGE);
|
|
74314
|
+
const message = given ? commitMessage(parsed, io) : null;
|
|
74315
|
+
if (message !== null && typeof message !== "string")
|
|
74316
|
+
return usage3(io, message.error, COMMIT_USAGE);
|
|
74317
|
+
if (message !== null && !message.trim())
|
|
74318
|
+
return usage3(io, "the commit message is empty", COMMIT_USAGE);
|
|
73993
74319
|
const result = gitCommit(io.cwd, {
|
|
73994
|
-
message
|
|
73995
|
-
|
|
73996
|
-
`),
|
|
74320
|
+
message,
|
|
73997
74321
|
all: parsed.all,
|
|
73998
74322
|
paths: parsed.paths,
|
|
74323
|
+
amend: parsed.amend,
|
|
74324
|
+
allowEmpty: parsed.allowEmpty,
|
|
73999
74325
|
actor: actorFromEnv(io.env),
|
|
74000
74326
|
env: io.env
|
|
74001
74327
|
});
|
|
@@ -74004,8 +74330,9 @@ async function commit(argv, io) {
|
|
|
74004
74330
|
await ensureImplicitTask(io);
|
|
74005
74331
|
return emit(io, ok(result.data), (data) => [
|
|
74006
74332
|
`${data.branch} ${short2(data.sha)} ${data.message.split(`
|
|
74007
|
-
`, 1)[0]} (${data.files.length} file${data.files.length === 1 ? "" : "s"})`,
|
|
74333
|
+
`, 1)[0]} (${data.files.length ? `${data.files.length} file${data.files.length === 1 ? "" : "s"}` : "empty commit"})${data.amended ? `, amends ${short2(data.amended)}` : ""}`,
|
|
74008
74334
|
...data.leftDirty ? [`${data.leftDirty} change(s) left uncommitted`] : [],
|
|
74335
|
+
...data.notes.map((note) => `note: ${note}`),
|
|
74009
74336
|
..."error" in data.recorded ? [`ledger: not recorded (${data.recorded.error})`] : [],
|
|
74010
74337
|
...data.session ? [] : ["note: WORKIT_SESSION_ID is unset; this commit has no session author"]
|
|
74011
74338
|
]);
|
|
@@ -74039,7 +74366,10 @@ async function push(argv, io) {
|
|
|
74039
74366
|
}
|
|
74040
74367
|
const grant = requireGrant(io.cwd, "push", { forge: !plan.data.local });
|
|
74041
74368
|
if (!grant.allowed)
|
|
74042
|
-
return emit(io, fail("blocked", grant.error, {
|
|
74369
|
+
return emit(io, fail("blocked", grant.error, {
|
|
74370
|
+
unblock: grant.unblock,
|
|
74371
|
+
data: { reason: grant.reason }
|
|
74372
|
+
}));
|
|
74043
74373
|
const result = executePush(io.cwd, plan.data, {
|
|
74044
74374
|
forceWithLease: flags.booleans.has("force-with-lease"),
|
|
74045
74375
|
overwriteUnintegrated: flags.booleans.has("overwrite-unintegrated"),
|
|
@@ -74048,7 +74378,10 @@ async function push(argv, io) {
|
|
|
74048
74378
|
actor: actorFromEnv(io.env)
|
|
74049
74379
|
});
|
|
74050
74380
|
if (!result.ok)
|
|
74051
|
-
return forgeFail(io, result, {
|
|
74381
|
+
return forgeFail(io, result, {
|
|
74382
|
+
branch: plan.data.branch,
|
|
74383
|
+
sha: plan.data.sha
|
|
74384
|
+
});
|
|
74052
74385
|
return emit(io, ok(result.data), (data) => [
|
|
74053
74386
|
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`,
|
|
74054
74387
|
...data.upstream ? [`upstream: ${data.remote}/${data.branch}`] : []
|
|
@@ -74064,7 +74397,7 @@ async function run12(argv, io) {
|
|
|
74064
74397
|
return push(rest, io);
|
|
74065
74398
|
return usage3(io, sub && !sub.startsWith("-") ? `unknown git subcommand "${sub}"` : "missing git subcommand", USAGE5);
|
|
74066
74399
|
}
|
|
74067
|
-
var BRANCH_USAGE = "workit git branch <name> | --kind feature|bugfix|hotfix --slug <s> [--base <b>] [--track <t>] [--carry] [--json]", COMMIT_USAGE = "workit git commit -m <msg
|
|
74400
|
+
var BRANCH_USAGE = "workit git branch <name> | --kind feature|bugfix|hotfix --slug <s> [--base <b>] [--track <t>] [--carry] [--json]", COMMIT_USAGE = "workit git commit -m|--message <msg>… | -F|--file <file|-> [--amend [--no-edit]] [--allow-empty] [-a|--all | [--] <paths…>] [--json]", PUSH_USAGE = "workit git push [--set-upstream] [--force-with-lease [--expect <sha>] [--overwrite-unintegrated]] [--json]", USAGE5 = "workit git branch|commit|push ... (workit help git)", short2 = (sha) => sha ? sha.slice(0, 12) : "(none)", COMMIT_SWITCHES;
|
|
74068
74401
|
var init_git2 = __esm(() => {
|
|
74069
74402
|
init_autonomy();
|
|
74070
74403
|
init_ops();
|
|
@@ -74072,9 +74405,16 @@ var init_git2 = __esm(() => {
|
|
|
74072
74405
|
init_implicit_task();
|
|
74073
74406
|
init_output();
|
|
74074
74407
|
init_forge_common();
|
|
74408
|
+
COMMIT_SWITCHES = {
|
|
74409
|
+
"-a": "all",
|
|
74410
|
+
"--all": "all",
|
|
74411
|
+
"--amend": "amend",
|
|
74412
|
+
"--no-edit": "noEdit",
|
|
74413
|
+
"--allow-empty": "allowEmpty"
|
|
74414
|
+
};
|
|
74075
74415
|
});
|
|
74076
74416
|
|
|
74077
|
-
// packages/workit-
|
|
74417
|
+
// packages/workit-core/src/forge/verify.ts
|
|
74078
74418
|
import { spawnSync as spawnSync19 } from "node:child_process";
|
|
74079
74419
|
function finish(cwd, report, actor) {
|
|
74080
74420
|
const delivered = report.observations.length > 0 && report.observations.every((entry) => entry.ok);
|
|
@@ -74394,11 +74734,11 @@ var init_verify_delivery = __esm(() => {
|
|
|
74394
74734
|
};
|
|
74395
74735
|
});
|
|
74396
74736
|
|
|
74397
|
-
// packages/workit-
|
|
74737
|
+
// packages/workit-core/src/stack.ts
|
|
74398
74738
|
import { spawnSync as spawnSync20 } from "node:child_process";
|
|
74399
74739
|
import { createHash as createHash15, randomBytes as randomBytes3 } from "node:crypto";
|
|
74400
74740
|
import fs22 from "node:fs";
|
|
74401
|
-
import
|
|
74741
|
+
import path44 from "node:path";
|
|
74402
74742
|
function worktreeOf(cwd, branch) {
|
|
74403
74743
|
const list = gitRun3(cwd, ["worktree", "list", "--porcelain"]);
|
|
74404
74744
|
if (!list.ok)
|
|
@@ -74442,7 +74782,7 @@ function gitRestack(cwd, input) {
|
|
|
74442
74782
|
if (!scratch)
|
|
74443
74783
|
return { ok: false, conflict: false, worktree: cwd, error: "no store root" };
|
|
74444
74784
|
fs22.mkdirSync(scratch, { recursive: true });
|
|
74445
|
-
dir =
|
|
74785
|
+
dir = path44.join(scratch, `${input.branch.replace(/[^A-Za-z0-9._-]+/gu, "_").slice(0, 40)}-${randomBytes3(4).toString("hex")}`);
|
|
74446
74786
|
const added = gitRun3(cwd, ["worktree", "add", "-q", dir, input.branch], GIT_TIMEOUTS.worktree);
|
|
74447
74787
|
if (!added.ok)
|
|
74448
74788
|
return { ok: false, conflict: false, worktree: cwd, error: firstLine(added) };
|
|
@@ -74483,7 +74823,7 @@ function pruneScratch(cwd) {
|
|
|
74483
74823
|
if (!scratch || !fs22.existsSync(scratch))
|
|
74484
74824
|
return;
|
|
74485
74825
|
for (const name of fs22.readdirSync(scratch)) {
|
|
74486
|
-
const dir =
|
|
74826
|
+
const dir = path44.join(scratch, name);
|
|
74487
74827
|
if (!rebaseInProgress(dir) && !trackedDirt(dir))
|
|
74488
74828
|
gitRun3(cwd, ["worktree", "remove", "--force", dir]);
|
|
74489
74829
|
}
|
|
@@ -74493,7 +74833,7 @@ function stacksDir(cwd) {
|
|
|
74493
74833
|
const root = storeRoot(cwd);
|
|
74494
74834
|
if (!root.ok)
|
|
74495
74835
|
return stackFail(root.code, root.error, root.unblock);
|
|
74496
|
-
return { ok: true, data:
|
|
74836
|
+
return { ok: true, data: path44.join(root.value.root, "stacks") };
|
|
74497
74837
|
}
|
|
74498
74838
|
function parseStack(raw) {
|
|
74499
74839
|
if (!isRecord7(raw) || !Array.isArray(raw.branches))
|
|
@@ -74545,7 +74885,7 @@ function readStack(cwd, name) {
|
|
|
74545
74885
|
const dir = stacksDir(cwd);
|
|
74546
74886
|
if (!dir.ok)
|
|
74547
74887
|
return dir;
|
|
74548
|
-
const file =
|
|
74888
|
+
const file = path44.join(dir.data, fileFor(name));
|
|
74549
74889
|
let text;
|
|
74550
74890
|
try {
|
|
74551
74891
|
text = fs22.readFileSync(file, "utf8");
|
|
@@ -74566,7 +74906,7 @@ function writeStack(cwd, stack, now = new Date) {
|
|
|
74566
74906
|
const dir = stacksDir(cwd);
|
|
74567
74907
|
if (!dir.ok)
|
|
74568
74908
|
return dir;
|
|
74569
|
-
const file =
|
|
74909
|
+
const file = path44.join(dir.data, fileFor(stack.name));
|
|
74570
74910
|
const temp = `${file}.${process.pid}.tmp`;
|
|
74571
74911
|
try {
|
|
74572
74912
|
fs22.mkdirSync(dir.data, { recursive: true });
|
|
@@ -74594,7 +74934,7 @@ function listStacks(cwd) {
|
|
|
74594
74934
|
for (const name of names) {
|
|
74595
74935
|
let parsed = null;
|
|
74596
74936
|
try {
|
|
74597
|
-
parsed = parseStack(JSON.parse(fs22.readFileSync(
|
|
74937
|
+
parsed = parseStack(JSON.parse(fs22.readFileSync(path44.join(dir.data, name), "utf8")));
|
|
74598
74938
|
} catch {
|
|
74599
74939
|
parsed = null;
|
|
74600
74940
|
}
|
|
@@ -74653,7 +74993,7 @@ function takeLock(lock) {
|
|
|
74653
74993
|
host: localLockHost(),
|
|
74654
74994
|
nonce: randomBytes3(8).toString("hex")
|
|
74655
74995
|
};
|
|
74656
|
-
fs22.writeFileSync(
|
|
74996
|
+
fs22.writeFileSync(path44.join(lock, OWNER), JSON.stringify(owner));
|
|
74657
74997
|
return owner;
|
|
74658
74998
|
}
|
|
74659
74999
|
function reapLock(lock, observed) {
|
|
@@ -74690,7 +75030,7 @@ async function withStackLock(cwd, name, fn, waitMs = LOCK_WAIT_MS3) {
|
|
|
74690
75030
|
return dir;
|
|
74691
75031
|
if (!validName(name))
|
|
74692
75032
|
return stackFail("invalid_input", "a stack name must be 1-200 printable characters");
|
|
74693
|
-
const lock =
|
|
75033
|
+
const lock = path44.join(dir.data, `${fileFor(name)}.lock`);
|
|
74694
75034
|
try {
|
|
74695
75035
|
fs22.mkdirSync(dir.data, { recursive: true });
|
|
74696
75036
|
} catch (error) {
|
|
@@ -74720,7 +75060,7 @@ async function withStackLock(cwd, name, fn, waitMs = LOCK_WAIT_MS3) {
|
|
|
74720
75060
|
const touch = () => {
|
|
74721
75061
|
try {
|
|
74722
75062
|
const now = new Date;
|
|
74723
|
-
fs22.utimesSync(
|
|
75063
|
+
fs22.utimesSync(path44.join(lock, OWNER), now, now);
|
|
74724
75064
|
} catch {}
|
|
74725
75065
|
};
|
|
74726
75066
|
const beat = setInterval(touch, HEARTBEAT_MS);
|
|
@@ -74969,7 +75309,7 @@ function repoMismatch(ctx, stack) {
|
|
|
74969
75309
|
return stackFail("blocked", `repo_mismatch: stack ${stack.name} was planned on ${stack.forge ?? "?"} ${stack.repo ?? "?"}, but this checkout resolves to ${kind} ${repo}`, `workit stack plan --name ${stack.name} <branch…> # re-plan it here, or run from the right checkout`, { planned: { forge: stack.forge, repo: stack.repo }, resolved: { forge: kind, repo } });
|
|
74970
75310
|
return null;
|
|
74971
75311
|
}
|
|
74972
|
-
function qualify(ctx, stack, entry, doc, verdict, grant, binding = null) {
|
|
75312
|
+
function qualify(ctx, stack, entry, doc, verdict, grant, binding = null, bypass = false) {
|
|
74973
75313
|
const label = entry.pr ? noun2(ctx.resolved, entry.pr) : entry.branch;
|
|
74974
75314
|
const stop = (reason, detail, unblock, ready = false) => ({
|
|
74975
75315
|
ok: false,
|
|
@@ -74988,9 +75328,11 @@ function qualify(ctx, stack, entry, doc, verdict, grant, binding = null) {
|
|
|
74988
75328
|
return stop("base_not_trunk", `${label} targets ${doc.base}, not ${stack.trunk}`, "workit stack sync");
|
|
74989
75329
|
if (doc.next !== "READY")
|
|
74990
75330
|
return stop("not_ready", `${label} is ${doc.next}${doc.blockers.length ? ` (${doc.blockers.join(", ")})` : ""}`, doc.next === "WAITING_CI" ? `workit ci wait --pr ${entry.pr}` : `workit pr status --pr ${entry.pr}`);
|
|
74991
|
-
const
|
|
74992
|
-
if (
|
|
74993
|
-
return stop(
|
|
75331
|
+
const allowUnverified = grant.allowed && grant.allowUnverified;
|
|
75332
|
+
if (bypass && allowUnverified && verdict.reasons.includes("failing_verdict"))
|
|
75333
|
+
return stop("failed_verdict", `${label} has a current independent failed verdict for ${doc.head.sha.slice(0, 12)}; --unverified never lands over a rejection`, "a new independent verdict on the head supersedes it");
|
|
75334
|
+
if (!(bypass && allowUnverified) && !verdict.accepted)
|
|
75335
|
+
return stop(verdict.reasons.includes("no_verdict") ? "no_verdict" : "needs_verdict", `${label} has no accepted independent verdict for ${doc.head.sha.slice(0, 12)} (${verdict.reasons.join(", ") || "none"})`, `an independent session verifies ${entry.branch} and runs: workit ledger verdict verified --how "<what was exercised>" --branch ${entry.branch}${allowUnverified ? `; or, only if the user asks to land unverified: workit stack land --unverified --reason "<why>"` : ""}`);
|
|
74994
75336
|
if (!grant.allowed)
|
|
74995
75337
|
return stop("grant_required", `${label} is verified and ready, but ${grant.error}`, grant.unblock, true);
|
|
74996
75338
|
return { ok: true };
|
|
@@ -75408,6 +75750,14 @@ async function landStack(ctx, stack, options) {
|
|
|
75408
75750
|
const mismatch = repoMismatch(ctx, stack);
|
|
75409
75751
|
if (mismatch)
|
|
75410
75752
|
return failWith(mismatch);
|
|
75753
|
+
const bypass = options.unverified ?? null;
|
|
75754
|
+
if (bypass) {
|
|
75755
|
+
const grant = requireGrant(ctx.cwd, "merge");
|
|
75756
|
+
if (!grant.allowed)
|
|
75757
|
+
return failWith(stackFail("blocked", grant.error, grant.unblock, { reason: "grant_required" }));
|
|
75758
|
+
if (!grant.allowUnverified)
|
|
75759
|
+
return failWith(stackFail("blocked", `unverified_refused: workspace ${grant.workspace ? `"${grant.workspace}"` : "(none)"} grants merge: "verified", which never lands without an accepted independent verdict`, "a non-author session verifies each head (workit-review), then land without --unverified", { reason: "unverified_refused" }));
|
|
75760
|
+
}
|
|
75411
75761
|
if (!options.dryRun) {
|
|
75412
75762
|
const synced = syncStack(ctx.cwd, ctx, stack, { publish: true, dryRun: false, limit: 1 }, ctx.actor);
|
|
75413
75763
|
if (!synced.ok)
|
|
@@ -75453,7 +75803,7 @@ async function landStack(ctx, stack, options) {
|
|
|
75453
75803
|
const grant = requireGrant(ctx.cwd, "merge");
|
|
75454
75804
|
const verdict = verdictOf(ctx.cwd, entry.branch, ledgerRows());
|
|
75455
75805
|
const effective = options.dryRun && simulated.size > 0 && doc ? { ...doc, base: stack.trunk } : doc;
|
|
75456
|
-
const q = qualify(ctx, stack, entry, effective, verdict, grant, doc ? prBinding(ctx, entry, doc) : null);
|
|
75806
|
+
const q = qualify(ctx, stack, entry, effective, verdict, grant, doc ? prBinding(ctx, entry, doc) : null, bypass !== null);
|
|
75457
75807
|
if (!q.ok) {
|
|
75458
75808
|
outcome.stoppedAt = {
|
|
75459
75809
|
pr: entry.pr,
|
|
@@ -75476,7 +75826,8 @@ async function landStack(ctx, stack, options) {
|
|
|
75476
75826
|
method: options.method,
|
|
75477
75827
|
deleteBranch: false,
|
|
75478
75828
|
actor: ctx.actor,
|
|
75479
|
-
expect: { base: stack.trunk, branch: entry.branch }
|
|
75829
|
+
expect: { base: stack.trunk, branch: entry.branch },
|
|
75830
|
+
...bypass && !verdict.accepted ? { unverified: bypass } : {}
|
|
75480
75831
|
}, ctx.sleep);
|
|
75481
75832
|
if (!merged.ok) {
|
|
75482
75833
|
if (merged.code === "blocked" && "refusal" in merged && merged.refusal) {
|
|
@@ -75492,7 +75843,12 @@ async function landStack(ctx, stack, options) {
|
|
|
75492
75843
|
}
|
|
75493
75844
|
return failWith(stackFail(merged.code, merged.error, merged.unblock));
|
|
75494
75845
|
}
|
|
75495
|
-
outcome.landed.push({
|
|
75846
|
+
outcome.landed.push({
|
|
75847
|
+
pr,
|
|
75848
|
+
branch: entry.branch,
|
|
75849
|
+
mergeSha: merged.data.mergeSha,
|
|
75850
|
+
unverified: merged.data.unverified?.recorded ?? null
|
|
75851
|
+
});
|
|
75496
75852
|
entry.merged = { pr, mergeSha: merged.data.mergeSha, at: new Date().toISOString() };
|
|
75497
75853
|
const written = writeStack(ctx.cwd, stack);
|
|
75498
75854
|
if (!written.ok)
|
|
@@ -75544,7 +75900,7 @@ var STACK_VERSION = 1, stackFail = (code, error, unblock, data) => ({
|
|
|
75544
75900
|
return !status.ok || status.stdout.trim() !== "";
|
|
75545
75901
|
}, scratchDir = (cwd) => {
|
|
75546
75902
|
const dir = stacksDir(cwd);
|
|
75547
|
-
return dir.ok ?
|
|
75903
|
+
return dir.ok ? path44.join(dir.data, "worktrees") : null;
|
|
75548
75904
|
}, firstLine = (run) => (`${run.stderr}
|
|
75549
75905
|
${run.stdout}`.split(`
|
|
75550
75906
|
`).find((line) => line.trim()) ?? "git failed").trim().slice(0, 300), stackFileName = (name) => `${name.replace(/[^A-Za-z0-9._-]+/gu, "_").replace(/^[._]+/u, "").slice(0, 48).toLowerCase()}-${createHash15("sha256").update(name).digest("hex").slice(0, 12)}.json`, fileFor, validName = (name) => {
|
|
@@ -75559,12 +75915,12 @@ ${run.stdout}`.split(`
|
|
|
75559
75915
|
}, isRecord7 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), str3 = (value) => typeof value === "string" && value ? value : null, LOCK_WAIT_MS3 = 2000, HEARTBEAT_MS = 20000, HEARTBEAT_STALE_MS, OWNERLESS_STALE_MS = 30000, OWNER = "owner", readOwner = (lock) => {
|
|
75560
75916
|
let raw = null;
|
|
75561
75917
|
try {
|
|
75562
|
-
raw = fs22.readFileSync(
|
|
75918
|
+
raw = fs22.readFileSync(path44.join(lock, OWNER), "utf8");
|
|
75563
75919
|
} catch {
|
|
75564
75920
|
raw = null;
|
|
75565
75921
|
}
|
|
75566
75922
|
let age = null;
|
|
75567
|
-
for (const target of [
|
|
75923
|
+
for (const target of [path44.join(lock, OWNER), lock])
|
|
75568
75924
|
try {
|
|
75569
75925
|
age = Date.now() - fs22.statSync(target).mtimeMs;
|
|
75570
75926
|
break;
|
|
@@ -75810,11 +76166,11 @@ var init_stack2 = __esm(() => {
|
|
|
75810
76166
|
METHODS3 = new Set(["squash", "merge", "rebase"]);
|
|
75811
76167
|
});
|
|
75812
76168
|
|
|
75813
|
-
// packages/workit-
|
|
76169
|
+
// packages/workit-core/src/fanout.ts
|
|
75814
76170
|
import { spawnSync as spawnSync21 } from "node:child_process";
|
|
75815
76171
|
import { createHash as createHash16 } from "node:crypto";
|
|
75816
76172
|
import fs23 from "node:fs";
|
|
75817
|
-
import
|
|
76173
|
+
import path45 from "node:path";
|
|
75818
76174
|
function expandBraces(pattern, limit = 64) {
|
|
75819
76175
|
for (let index = 0;index < pattern.length; index += 1) {
|
|
75820
76176
|
if (pattern[index] === "\\") {
|
|
@@ -76048,7 +76404,7 @@ function parsePlan(raw, defaults, name) {
|
|
|
76048
76404
|
id,
|
|
76049
76405
|
branch,
|
|
76050
76406
|
base: optional("base") ?? "",
|
|
76051
|
-
worktree:
|
|
76407
|
+
worktree: path45.resolve(defaults.root, optional("worktree") ?? path45.join(defaults.worktreeRoot, id)),
|
|
76052
76408
|
tier,
|
|
76053
76409
|
dependsOn: [...new Set(dependsOn ?? [])],
|
|
76054
76410
|
scope,
|
|
@@ -76277,11 +76633,11 @@ function defaultTrunk(cwd) {
|
|
|
76277
76633
|
}
|
|
76278
76634
|
function mainCheckout(cwd) {
|
|
76279
76635
|
const common = gitCommonDir(cwd);
|
|
76280
|
-
return common &&
|
|
76636
|
+
return common && path45.basename(common) === ".git" ? path45.dirname(common) : path45.resolve(cwd);
|
|
76281
76637
|
}
|
|
76282
76638
|
function worktreeRoot(cwd) {
|
|
76283
76639
|
const main = mainCheckout(cwd);
|
|
76284
|
-
return
|
|
76640
|
+
return path45.join(path45.dirname(main), `${path45.basename(main)}-wt`);
|
|
76285
76641
|
}
|
|
76286
76642
|
function sliceHash(slice) {
|
|
76287
76643
|
const {
|
|
@@ -76299,7 +76655,7 @@ function fanoutsDir(cwd) {
|
|
|
76299
76655
|
const root = storeRoot(cwd);
|
|
76300
76656
|
if (!root.ok)
|
|
76301
76657
|
return fanoutFail(root.code, root.error, root.unblock);
|
|
76302
|
-
return { ok: true, data:
|
|
76658
|
+
return { ok: true, data: path45.join(root.value.root, "fanouts") };
|
|
76303
76659
|
}
|
|
76304
76660
|
function parseStored(raw) {
|
|
76305
76661
|
if (!isRecord8(raw) || typeof raw.name !== "string" || typeof raw.trunk !== "string")
|
|
@@ -76365,7 +76721,7 @@ function readFanout(cwd, name) {
|
|
|
76365
76721
|
const dir = fanoutsDir(cwd);
|
|
76366
76722
|
if (!dir.ok)
|
|
76367
76723
|
return dir;
|
|
76368
|
-
const file =
|
|
76724
|
+
const file = path45.join(dir.data, stackFileName(name));
|
|
76369
76725
|
let parsed = null;
|
|
76370
76726
|
try {
|
|
76371
76727
|
parsed = parseStored(JSON.parse(fs23.readFileSync(file, "utf8")));
|
|
@@ -76390,7 +76746,7 @@ function listFanouts(cwd) {
|
|
|
76390
76746
|
for (const entry of names) {
|
|
76391
76747
|
let parsed = null;
|
|
76392
76748
|
try {
|
|
76393
|
-
parsed = parseStored(JSON.parse(fs23.readFileSync(
|
|
76749
|
+
parsed = parseStored(JSON.parse(fs23.readFileSync(path45.join(dir.data, entry), "utf8")));
|
|
76394
76750
|
} catch {
|
|
76395
76751
|
parsed = null;
|
|
76396
76752
|
}
|
|
@@ -76420,7 +76776,7 @@ function writeFanout(cwd, plan) {
|
|
|
76420
76776
|
const dir = fanoutsDir(cwd);
|
|
76421
76777
|
if (!dir.ok)
|
|
76422
76778
|
return dir;
|
|
76423
|
-
const file =
|
|
76779
|
+
const file = path45.join(dir.data, stackFileName(plan.name));
|
|
76424
76780
|
const temp = `${file}.${process.pid}.tmp`;
|
|
76425
76781
|
try {
|
|
76426
76782
|
fs23.mkdirSync(dir.data, { recursive: true });
|
|
@@ -76621,10 +76977,10 @@ var init_fanout = __esm(() => {
|
|
|
76621
76977
|
ID = /^[a-z0-9][a-z0-9._-]{0,63}$/u;
|
|
76622
76978
|
});
|
|
76623
76979
|
|
|
76624
|
-
// packages/workit-
|
|
76980
|
+
// packages/workit-core/src/fanout-worktree.ts
|
|
76625
76981
|
import { randomBytes as randomBytes4 } from "node:crypto";
|
|
76626
76982
|
import fs24 from "node:fs";
|
|
76627
|
-
import
|
|
76983
|
+
import path46 from "node:path";
|
|
76628
76984
|
function rowSample(lines) {
|
|
76629
76985
|
const out = [];
|
|
76630
76986
|
let bytes = 0;
|
|
@@ -76684,7 +77040,7 @@ function adminDir(worktree) {
|
|
|
76684
77040
|
const file = dir.stdout.trim();
|
|
76685
77041
|
let token = null;
|
|
76686
77042
|
try {
|
|
76687
|
-
token = fs24.readFileSync(
|
|
77043
|
+
token = fs24.readFileSync(path46.join(file, TOKEN_FILE), "utf8").trim() || null;
|
|
76688
77044
|
} catch {
|
|
76689
77045
|
token = null;
|
|
76690
77046
|
}
|
|
@@ -76692,7 +77048,7 @@ function adminDir(worktree) {
|
|
|
76692
77048
|
const stat = worktreeDeps.stat(file);
|
|
76693
77049
|
return {
|
|
76694
77050
|
path: file,
|
|
76695
|
-
id:
|
|
77051
|
+
id: path46.basename(file),
|
|
76696
77052
|
ino: stat.ino.toString(),
|
|
76697
77053
|
token,
|
|
76698
77054
|
birthMs: stat.birthtimeNs > 0n ? Number(stat.birthtimeMs) : null,
|
|
@@ -76708,7 +77064,7 @@ function markAdminDir(worktree) {
|
|
|
76708
77064
|
return null;
|
|
76709
77065
|
const token = randomBytes4(16).toString("hex");
|
|
76710
77066
|
try {
|
|
76711
|
-
fs24.writeFileSync(
|
|
77067
|
+
fs24.writeFileSync(path46.join(admin.path, TOKEN_FILE), `${token}
|
|
76712
77068
|
`);
|
|
76713
77069
|
} catch {
|
|
76714
77070
|
return null;
|
|
@@ -76723,7 +77079,7 @@ function excludeScratch(cwd) {
|
|
|
76723
77079
|
const common = gitCommonDir(cwd);
|
|
76724
77080
|
if (!common)
|
|
76725
77081
|
return;
|
|
76726
|
-
const file =
|
|
77082
|
+
const file = path46.join(common, "info", "exclude");
|
|
76727
77083
|
let text = "";
|
|
76728
77084
|
try {
|
|
76729
77085
|
text = fs24.readFileSync(file, "utf8");
|
|
@@ -76732,7 +77088,7 @@ function excludeScratch(cwd) {
|
|
|
76732
77088
|
}
|
|
76733
77089
|
if (text.split(/\r?\n/u).includes(EXCLUDE_LINE))
|
|
76734
77090
|
return;
|
|
76735
|
-
fs24.mkdirSync(
|
|
77091
|
+
fs24.mkdirSync(path46.dirname(file), { recursive: true });
|
|
76736
77092
|
fs24.appendFileSync(file, `${text && !text.endsWith(`
|
|
76737
77093
|
`) ? `
|
|
76738
77094
|
` : ""}# workit fanout: per-worker scratch dirs
|
|
@@ -76740,7 +77096,7 @@ ${EXCLUDE_LINE}
|
|
|
76740
77096
|
`);
|
|
76741
77097
|
}
|
|
76742
77098
|
function ensureScratch(worktree) {
|
|
76743
|
-
const scratch =
|
|
77099
|
+
const scratch = path46.join(worktree, SCRATCH_DIR);
|
|
76744
77100
|
fs24.mkdirSync(scratch, { recursive: true });
|
|
76745
77101
|
return scratch;
|
|
76746
77102
|
}
|
|
@@ -76958,7 +77314,7 @@ function unpushedCount(cwd, branch) {
|
|
|
76958
77314
|
return count.ok ? Number(count.stdout.trim()) : null;
|
|
76959
77315
|
}
|
|
76960
77316
|
function removeScratch(worktree) {
|
|
76961
|
-
const scratch =
|
|
77317
|
+
const scratch = path46.join(worktree, SCRATCH_DIR);
|
|
76962
77318
|
let stat;
|
|
76963
77319
|
try {
|
|
76964
77320
|
stat = fs24.lstatSync(scratch);
|
|
@@ -76974,16 +77330,16 @@ var SLOW, SCRATCH_DIR = ".workit-scratch", EXCLUDE_LINE, DIRTY_ROW_BYTES = 2000,
|
|
|
76974
77330
|
try {
|
|
76975
77331
|
return fs24.realpathSync.native(target);
|
|
76976
77332
|
} catch {
|
|
76977
|
-
return
|
|
77333
|
+
return path46.resolve(target);
|
|
76978
77334
|
}
|
|
76979
77335
|
}, samePath = (a, b) => {
|
|
76980
77336
|
const left = canonical2(a);
|
|
76981
77337
|
const right = canonical2(b);
|
|
76982
77338
|
return process.platform === "win32" || process.platform === "darwin" ? left.toLowerCase() === right.toLowerCase() : left === right;
|
|
76983
77339
|
}, inside2 = (child, parent) => {
|
|
76984
|
-
const relative =
|
|
76985
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
76986
|
-
}, slicePath = (cwd, slice) =>
|
|
77340
|
+
const relative = path46.relative(canonical2(parent), canonical2(child));
|
|
77341
|
+
return relative === "" || !relative.startsWith("..") && !path46.isAbsolute(relative);
|
|
77342
|
+
}, slicePath = (cwd, slice) => path46.isAbsolute(slice.worktree) ? slice.worktree : path46.resolve(mainCheckout(cwd), slice.worktree), CLOCK_SLACK_MS = 2000, TOKEN_FILE = "workit-fanout-token", worktreeDeps, worktreeFailed = (stderr) => fanoutFail("failed", `git worktree add failed: ${stderr.trim().split(`
|
|
76987
77343
|
`)[0] || "unknown error"}`);
|
|
76988
77344
|
var init_fanout_worktree = __esm(() => {
|
|
76989
77345
|
init_ops();
|
|
@@ -76997,7 +77353,7 @@ var init_fanout_worktree = __esm(() => {
|
|
|
76997
77353
|
};
|
|
76998
77354
|
});
|
|
76999
77355
|
|
|
77000
|
-
// packages/workit-
|
|
77356
|
+
// packages/workit-core/src/fanout-brief.ts
|
|
77001
77357
|
import { createHash as createHash17 } from "node:crypto";
|
|
77002
77358
|
function workerSession(lead, slice, attempt) {
|
|
77003
77359
|
const tail = attempt === null ? "" : `+try${attempt}`;
|
|
@@ -77103,7 +77459,7 @@ var init_fanout_brief = __esm(() => {
|
|
|
77103
77459
|
];
|
|
77104
77460
|
});
|
|
77105
77461
|
|
|
77106
|
-
// packages/workit-
|
|
77462
|
+
// packages/workit-core/src/fanout-landed.ts
|
|
77107
77463
|
import { spawnSync as spawnSync22 } from "node:child_process";
|
|
77108
77464
|
function forgeBreaker(resolved) {
|
|
77109
77465
|
if (!resolved)
|
|
@@ -77308,7 +77664,7 @@ var init_fanout_landed = __esm(() => {
|
|
|
77308
77664
|
init_fanout();
|
|
77309
77665
|
});
|
|
77310
77666
|
|
|
77311
|
-
// packages/workit-
|
|
77667
|
+
// packages/workit-core/src/fanout-check.ts
|
|
77312
77668
|
function mergeConflicts(cwd, a, b) {
|
|
77313
77669
|
const run = gitRun4(cwd, [
|
|
77314
77670
|
"merge-tree",
|
|
@@ -77566,7 +77922,7 @@ var init_fanout_check = __esm(() => {
|
|
|
77566
77922
|
init_fanout_landed();
|
|
77567
77923
|
});
|
|
77568
77924
|
|
|
77569
|
-
// packages/workit-
|
|
77925
|
+
// packages/workit-core/src/fanout-status.ts
|
|
77570
77926
|
function timeboxMs(text) {
|
|
77571
77927
|
if (!text || /^\s*\d+(?:\.\d+)?\s*$/u.test(text))
|
|
77572
77928
|
return null;
|
|
@@ -77759,7 +78115,7 @@ __export(exports_fanout, {
|
|
|
77759
78115
|
run: () => run15
|
|
77760
78116
|
});
|
|
77761
78117
|
import fs25 from "node:fs";
|
|
77762
|
-
import
|
|
78118
|
+
import path47 from "node:path";
|
|
77763
78119
|
function forgeFor(io, offline) {
|
|
77764
78120
|
if (offline)
|
|
77765
78121
|
return { forge: null, error: "--offline" };
|
|
@@ -77820,7 +78176,7 @@ function plan2(argv, io) {
|
|
|
77820
78176
|
return usage3(io, "pass --trunk or --track, not both (--track picks the trunk)", PLAN_USAGE2);
|
|
77821
78177
|
if (flags.positionals.length !== 1)
|
|
77822
78178
|
return usage3(io, flags.positionals.length ? `unexpected argument ${flags.positionals[1]}` : "missing <plan.json>", PLAN_USAGE2);
|
|
77823
|
-
const file =
|
|
78179
|
+
const file = path47.resolve(io.cwd, flags.positionals[0]);
|
|
77824
78180
|
let raw;
|
|
77825
78181
|
try {
|
|
77826
78182
|
raw = JSON.parse(fs25.readFileSync(file, "utf8"));
|
|
@@ -93252,7 +93608,7 @@ var init_ast = __esm(() => {
|
|
|
93252
93608
|
|
|
93253
93609
|
// packages/workit-cli/src/test-audit/rules.ts
|
|
93254
93610
|
import { builtinModules } from "node:module";
|
|
93255
|
-
import
|
|
93611
|
+
import path48 from "node:path";
|
|
93256
93612
|
function testCallee(call) {
|
|
93257
93613
|
let callee = call.callee;
|
|
93258
93614
|
if (callee.type === "CallExpression")
|
|
@@ -93745,12 +94101,12 @@ function checkConstantsOnly(ctx, emit) {
|
|
|
93745
94101
|
}
|
|
93746
94102
|
function checkOverMocking(ctx, emit) {
|
|
93747
94103
|
const { program } = ctx.parsed;
|
|
93748
|
-
const unit =
|
|
94104
|
+
const unit = path48.basename(ctx.file).replace(/\.(?:[cm]?[jt]sx?)$/, "").replace(/\.(?:test|spec)$/, "");
|
|
93749
94105
|
const mocked = find2(program, (node) => node.type === "CallExpression" && MODULE_MOCK.test(calleeName(node.callee) ?? "") && node.arguments[0]?.type === "StringLiteral");
|
|
93750
94106
|
const internal = mocked.filter((call) => /^(?:\.|@\/|~\/)/.test(call.arguments[0].value));
|
|
93751
94107
|
for (const call of mocked) {
|
|
93752
94108
|
const spec = call.arguments[0].value;
|
|
93753
|
-
const base =
|
|
94109
|
+
const base = path48.basename(spec.replace(/\/index(?:\.[cm]?[jt]sx?)?$/, "")).replace(/\.(?:[cm]?[jt]sx?)$/, "");
|
|
93754
94110
|
if (base === unit)
|
|
93755
94111
|
emit({
|
|
93756
94112
|
rule: "over-mocking",
|
|
@@ -94139,8 +94495,8 @@ var init_rules = __esm(() => {
|
|
|
94139
94495
|
|
|
94140
94496
|
// packages/workit-cli/src/test-audit/audit.ts
|
|
94141
94497
|
import { spawnSync as spawnSync23 } from "node:child_process";
|
|
94142
|
-
import { existsSync as
|
|
94143
|
-
import
|
|
94498
|
+
import { existsSync as existsSync19, readdirSync as readdirSync8, readFileSync as readFileSync21, statSync as statSync7 } from "node:fs";
|
|
94499
|
+
import path49 from "node:path";
|
|
94144
94500
|
function git6(cwd, args) {
|
|
94145
94501
|
const run = spawnSync23("git", ["-c", "core.quotepath=off", ...args], {
|
|
94146
94502
|
cwd,
|
|
@@ -94153,7 +94509,7 @@ function walkTests(dir, out) {
|
|
|
94153
94509
|
for (const entry of readdirSync8(dir, { withFileTypes: true })) {
|
|
94154
94510
|
if (entry.name.startsWith(".") && entry.name !== "." && entry.isDirectory())
|
|
94155
94511
|
continue;
|
|
94156
|
-
const full =
|
|
94512
|
+
const full = path49.join(dir, entry.name);
|
|
94157
94513
|
if (entry.isDirectory()) {
|
|
94158
94514
|
if (!SKIP_DIRS.has(entry.name))
|
|
94159
94515
|
walkTests(full, out);
|
|
@@ -94165,8 +94521,8 @@ function expandPaths(cwd, inputs) {
|
|
|
94165
94521
|
const files = [];
|
|
94166
94522
|
const missing = [];
|
|
94167
94523
|
for (const input of inputs.length > 0 ? inputs : ["."]) {
|
|
94168
|
-
const full =
|
|
94169
|
-
if (!
|
|
94524
|
+
const full = path49.resolve(cwd, input);
|
|
94525
|
+
if (!existsSync19(full))
|
|
94170
94526
|
missing.push(input);
|
|
94171
94527
|
else if (statSync7(full).isDirectory())
|
|
94172
94528
|
walkTests(full, files);
|
|
@@ -94202,11 +94558,11 @@ function changedLines(cwd, base) {
|
|
|
94202
94558
|
for (let offset = 0;offset < count; offset += 1)
|
|
94203
94559
|
lines.add(start + offset);
|
|
94204
94560
|
}
|
|
94205
|
-
changed.set(
|
|
94561
|
+
changed.set(path49.join(root, file), lines);
|
|
94206
94562
|
}
|
|
94207
94563
|
const untracked = git6(root, ["ls-files", "--others", "--exclude-standard", "-z"]);
|
|
94208
94564
|
for (const file of untracked.stdout.split("\x00").filter(Boolean))
|
|
94209
|
-
changed.set(
|
|
94565
|
+
changed.set(path49.join(root, file), "all");
|
|
94210
94566
|
return changed;
|
|
94211
94567
|
}
|
|
94212
94568
|
function auditFiles(files, display) {
|
|
@@ -94219,7 +94575,7 @@ function auditFiles(files, display) {
|
|
|
94219
94575
|
const shown = display(file);
|
|
94220
94576
|
let parsed;
|
|
94221
94577
|
try {
|
|
94222
|
-
parsed = parseSource(
|
|
94578
|
+
parsed = parseSource(readFileSync21(file, "utf8"), file);
|
|
94223
94579
|
} catch (error) {
|
|
94224
94580
|
parseErrors.push({
|
|
94225
94581
|
file: shown,
|
|
@@ -94268,7 +94624,7 @@ function auditFiles(files, display) {
|
|
|
94268
94624
|
durationMs: Math.round(performance.now() - started)
|
|
94269
94625
|
};
|
|
94270
94626
|
}
|
|
94271
|
-
var TEST_FILE, CODE_FILE, SKIP_DIRS, toPosix = (file) => file.split(
|
|
94627
|
+
var TEST_FILE, CODE_FILE, SKIP_DIRS, toPosix = (file) => file.split(path49.sep).join("/"), SEVERITY_ORDER, ruleIds;
|
|
94272
94628
|
var init_audit = __esm(() => {
|
|
94273
94629
|
init_ast();
|
|
94274
94630
|
init_rules();
|
|
@@ -94282,12 +94638,12 @@ var init_audit = __esm(() => {
|
|
|
94282
94638
|
// packages/workit-cli/src/test-audit/mutate.ts
|
|
94283
94639
|
import { spawn as spawn2 } from "node:child_process";
|
|
94284
94640
|
import {
|
|
94285
|
-
existsSync as
|
|
94641
|
+
existsSync as existsSync20,
|
|
94286
94642
|
lstatSync as lstatSync7,
|
|
94287
94643
|
mkdirSync as mkdirSync9,
|
|
94288
94644
|
mkdtempSync as mkdtempSync4,
|
|
94289
94645
|
readdirSync as readdirSync9,
|
|
94290
|
-
readFileSync as
|
|
94646
|
+
readFileSync as readFileSync22,
|
|
94291
94647
|
readlinkSync as readlinkSync3,
|
|
94292
94648
|
realpathSync as realpathSync9,
|
|
94293
94649
|
renameSync as renameSync5,
|
|
@@ -94298,7 +94654,7 @@ import {
|
|
|
94298
94654
|
copyFileSync as copyFileSync6
|
|
94299
94655
|
} from "node:fs";
|
|
94300
94656
|
import os14 from "node:os";
|
|
94301
|
-
import
|
|
94657
|
+
import path50 from "node:path";
|
|
94302
94658
|
function mutantsFor(source, file, lines) {
|
|
94303
94659
|
const parsed = parseSource(source, file);
|
|
94304
94660
|
const out = [];
|
|
@@ -94371,7 +94727,7 @@ function relatedTests(source, testFiles) {
|
|
|
94371
94727
|
for (const match of text.matchAll(SPECIFIER)) {
|
|
94372
94728
|
const spec = match[1];
|
|
94373
94729
|
if (spec.startsWith(".")) {
|
|
94374
|
-
if (stripExt(
|
|
94730
|
+
if (stripExt(path50.posix.join(path50.posix.dirname(file), spec)) === target)
|
|
94375
94731
|
return true;
|
|
94376
94732
|
} else if (spec.includes("/") && stripExt(spec).split("/").slice(-2).join("/") === tail)
|
|
94377
94733
|
return true;
|
|
@@ -94391,12 +94747,12 @@ function removeStaleCopies(tmp = os14.tmpdir()) {
|
|
|
94391
94747
|
for (const name of names) {
|
|
94392
94748
|
if (!name.startsWith(TEMP_PREFIX))
|
|
94393
94749
|
continue;
|
|
94394
|
-
const dir =
|
|
94750
|
+
const dir = path50.join(tmp, name);
|
|
94395
94751
|
try {
|
|
94396
94752
|
const stat = lstatSync7(dir);
|
|
94397
94753
|
if (!stat.isDirectory() || uid !== undefined && stat.uid !== uid)
|
|
94398
94754
|
continue;
|
|
94399
|
-
const pid = Number(
|
|
94755
|
+
const pid = Number(readFileSync22(path50.join(dir, PID_FILE), "utf8"));
|
|
94400
94756
|
if (Number.isInteger(pid) && pid > 0 && alive(pid))
|
|
94401
94757
|
continue;
|
|
94402
94758
|
} catch (error) {
|
|
@@ -94413,8 +94769,8 @@ function removeStaleCopies(tmp = os14.tmpdir()) {
|
|
|
94413
94769
|
function linkNodeModules(origin, target, repo, copy) {
|
|
94414
94770
|
mkdirSync9(target, { recursive: true });
|
|
94415
94771
|
for (const entry of readdirSync9(origin, { withFileTypes: true })) {
|
|
94416
|
-
const from =
|
|
94417
|
-
const to =
|
|
94772
|
+
const from = path50.join(origin, entry.name);
|
|
94773
|
+
const to = path50.join(target, entry.name);
|
|
94418
94774
|
if (entry.name.startsWith("@") && entry.isDirectory()) {
|
|
94419
94775
|
linkNodeModules(from, to, repo, copy);
|
|
94420
94776
|
continue;
|
|
@@ -94430,9 +94786,9 @@ function linkNodeModules(origin, target, repo, copy) {
|
|
|
94430
94786
|
} catch {
|
|
94431
94787
|
continue;
|
|
94432
94788
|
}
|
|
94433
|
-
const relative =
|
|
94434
|
-
if (!relative.startsWith("..") && !
|
|
94435
|
-
symlinkSync(
|
|
94789
|
+
const relative = path50.relative(repo, real);
|
|
94790
|
+
if (!relative.startsWith("..") && !path50.isAbsolute(relative) && !relative.split(path50.sep).includes("node_modules")) {
|
|
94791
|
+
symlinkSync(path50.join(copy, relative), to, "junction");
|
|
94436
94792
|
continue;
|
|
94437
94793
|
}
|
|
94438
94794
|
}
|
|
@@ -94448,7 +94804,7 @@ function copySymlink(repo, tree, from, to) {
|
|
|
94448
94804
|
}
|
|
94449
94805
|
const realRepo = realpathSync9(repo);
|
|
94450
94806
|
if (real && inside3(realRepo, real)) {
|
|
94451
|
-
symlinkSync(
|
|
94807
|
+
symlinkSync(path50.relative(path50.dirname(to), path50.join(tree, path50.relative(realRepo, real))), to);
|
|
94452
94808
|
return;
|
|
94453
94809
|
}
|
|
94454
94810
|
if (real && statSync8(real).isFile())
|
|
@@ -94457,10 +94813,10 @@ function copySymlink(repo, tree, from, to) {
|
|
|
94457
94813
|
symlinkSync(readlinkSync3(from), to);
|
|
94458
94814
|
}
|
|
94459
94815
|
function writeInside(copy, file, content) {
|
|
94460
|
-
const target =
|
|
94816
|
+
const target = path50.join(copy, file);
|
|
94461
94817
|
try {
|
|
94462
94818
|
const stat = lstatSync7(target);
|
|
94463
|
-
if (!stat.isFile() || !inside3(realpathSync9(copy), realpathSync9(
|
|
94819
|
+
if (!stat.isFile() || !inside3(realpathSync9(copy), realpathSync9(path50.dirname(target))))
|
|
94464
94820
|
return false;
|
|
94465
94821
|
} catch {
|
|
94466
94822
|
return false;
|
|
@@ -94471,9 +94827,9 @@ function writeInside(copy, file, content) {
|
|
|
94471
94827
|
return true;
|
|
94472
94828
|
}
|
|
94473
94829
|
function copyWorkingTree(repo) {
|
|
94474
|
-
const dir = mkdtempSync4(
|
|
94475
|
-
writeFileSync10(
|
|
94476
|
-
const tree =
|
|
94830
|
+
const dir = mkdtempSync4(path50.join(os14.tmpdir(), TEMP_PREFIX));
|
|
94831
|
+
writeFileSync10(path50.join(dir, PID_FILE), String(process.pid));
|
|
94832
|
+
const tree = path50.join(dir, "tree");
|
|
94477
94833
|
const head = git6(repo, ["rev-parse", "--verify", "--quiet", "HEAD"]).stdout.trim();
|
|
94478
94834
|
if (head && git6(dir, ["clone", "-q", "--shared", "--no-checkout", repo, tree]).ok) {
|
|
94479
94835
|
const branch = git6(repo, ["symbolic-ref", "--quiet", "--short", "HEAD"]).stdout.trim();
|
|
@@ -94490,29 +94846,29 @@ function copyWorkingTree(repo) {
|
|
|
94490
94846
|
for (const relative of listed) {
|
|
94491
94847
|
if (!relative)
|
|
94492
94848
|
continue;
|
|
94493
|
-
const from =
|
|
94849
|
+
const from = path50.join(repo, relative);
|
|
94494
94850
|
let stat;
|
|
94495
94851
|
try {
|
|
94496
94852
|
stat = lstatSync7(from);
|
|
94497
94853
|
} catch {
|
|
94498
94854
|
continue;
|
|
94499
94855
|
}
|
|
94500
|
-
const to =
|
|
94501
|
-
mkdirSync9(
|
|
94856
|
+
const to = path50.join(tree, relative);
|
|
94857
|
+
mkdirSync9(path50.dirname(to), { recursive: true });
|
|
94502
94858
|
if (stat.isSymbolicLink())
|
|
94503
94859
|
copySymlink(repo, tree, from, to);
|
|
94504
94860
|
else if (stat.isFile())
|
|
94505
94861
|
copyFileSync6(from, to);
|
|
94506
|
-
let parent =
|
|
94862
|
+
let parent = path50.dirname(relative);
|
|
94507
94863
|
while (parent !== "." && !dirs.has(parent)) {
|
|
94508
94864
|
dirs.add(parent);
|
|
94509
|
-
parent =
|
|
94865
|
+
parent = path50.dirname(parent);
|
|
94510
94866
|
}
|
|
94511
94867
|
}
|
|
94512
94868
|
for (const parent of dirs) {
|
|
94513
|
-
const modules =
|
|
94514
|
-
if (
|
|
94515
|
-
linkNodeModules(modules,
|
|
94869
|
+
const modules = path50.join(repo, parent, "node_modules");
|
|
94870
|
+
if (existsSync20(modules) && !existsSync20(path50.join(tree, parent, "node_modules")))
|
|
94871
|
+
linkNodeModules(modules, path50.join(tree, parent, "node_modules"), repo, tree);
|
|
94516
94872
|
}
|
|
94517
94873
|
return { dir, tree };
|
|
94518
94874
|
}
|
|
@@ -94551,20 +94907,20 @@ async function runMutation(options) {
|
|
|
94551
94907
|
const tracked = git6(repo, ["ls-files", "-co", "--exclude-standard", "-z"]).stdout.split("\x00").filter(Boolean);
|
|
94552
94908
|
const testFiles = tracked.filter((file) => TEST_FILE.test(file)).map((file) => {
|
|
94553
94909
|
try {
|
|
94554
|
-
return { file, text:
|
|
94910
|
+
return { file, text: readFileSync22(path50.join(repo, file), "utf8") };
|
|
94555
94911
|
} catch {
|
|
94556
94912
|
return { file, text: "" };
|
|
94557
94913
|
}
|
|
94558
94914
|
});
|
|
94559
94915
|
const candidates = [];
|
|
94560
94916
|
for (const [absolute, lines] of [...options.changed].toSorted(([a], [b]) => a.localeCompare(b))) {
|
|
94561
|
-
const relative = toPosix(
|
|
94917
|
+
const relative = toPosix(path50.relative(repo, absolute));
|
|
94562
94918
|
if (!CODE_FILE.test(relative) || TEST_FILE.test(relative) || relative.endsWith(".d.ts"))
|
|
94563
94919
|
continue;
|
|
94564
|
-
if (NOT_SOURCE.test(relative) || !
|
|
94920
|
+
if (NOT_SOURCE.test(relative) || !existsSync20(absolute))
|
|
94565
94921
|
continue;
|
|
94566
94922
|
try {
|
|
94567
|
-
candidates.push(...mutantsFor(
|
|
94923
|
+
candidates.push(...mutantsFor(readFileSync22(absolute, "utf8"), relative, lines));
|
|
94568
94924
|
} catch {}
|
|
94569
94925
|
}
|
|
94570
94926
|
const mutants = candidates.map((mutant, index) => ({ ...mutant, id: index + 1 }));
|
|
@@ -94572,9 +94928,9 @@ async function runMutation(options) {
|
|
|
94572
94928
|
for (const mutant of mutants)
|
|
94573
94929
|
if (!related.has(mutant.file))
|
|
94574
94930
|
related.set(mutant.file, relatedTests(mutant.file, testFiles));
|
|
94575
|
-
const cwdRelative =
|
|
94931
|
+
const cwdRelative = path50.relative(repo, options.cwd);
|
|
94576
94932
|
const asArg = (file) => {
|
|
94577
|
-
const relative = toPosix(
|
|
94933
|
+
const relative = toPosix(path50.relative(cwdRelative, file));
|
|
94578
94934
|
return shellQuote(relative.startsWith(".") ? relative : `./${relative}`);
|
|
94579
94935
|
};
|
|
94580
94936
|
const commandFor = (tests) => options.command.replaceAll("{files}", () => tests.map(asArg).join(" "));
|
|
@@ -94609,7 +94965,7 @@ async function runMutation(options) {
|
|
|
94609
94965
|
return finish2(options, 0, results, counts, started);
|
|
94610
94966
|
removeStaleCopies();
|
|
94611
94967
|
const { dir: copyDir, tree: copy } = copyWorkingTree(repo);
|
|
94612
|
-
const copyCwd =
|
|
94968
|
+
const copyCwd = path50.join(copy, cwdRelative);
|
|
94613
94969
|
let current = null;
|
|
94614
94970
|
const restore = () => {
|
|
94615
94971
|
if (current)
|
|
@@ -94644,7 +95000,7 @@ async function runMutation(options) {
|
|
|
94644
95000
|
record({ ...mutant, status: "skipped", durationMs: 0, tests, reason: "budget" });
|
|
94645
95001
|
continue;
|
|
94646
95002
|
}
|
|
94647
|
-
const original =
|
|
95003
|
+
const original = readFileSync22(path50.join(copy, mutant.file), "utf8");
|
|
94648
95004
|
const mutated = original.slice(0, mutant.start) + mutant.replacement + original.slice(mutant.end);
|
|
94649
95005
|
current = { file: mutant.file, original };
|
|
94650
95006
|
if (!writeInside(copy, mutant.file, mutated)) {
|
|
@@ -94701,8 +95057,8 @@ var NOT_SOURCE, FLIPS, isStringy = (node) => node.type === "StringLiteral" || no
|
|
|
94701
95057
|
return error.code === "EPERM";
|
|
94702
95058
|
}
|
|
94703
95059
|
}, inside3 = (root, file) => {
|
|
94704
|
-
const relative =
|
|
94705
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
95060
|
+
const relative = path50.relative(root, file);
|
|
95061
|
+
return relative === "" || !relative.startsWith("..") && !path50.isAbsolute(relative);
|
|
94706
95062
|
}, active, killTree = (child) => {
|
|
94707
95063
|
try {
|
|
94708
95064
|
if (child.pid && process.platform !== "win32")
|
|
@@ -94750,8 +95106,8 @@ var exports_test_audit = {};
|
|
|
94750
95106
|
__export(exports_test_audit, {
|
|
94751
95107
|
run: () => run17
|
|
94752
95108
|
});
|
|
94753
|
-
import { existsSync as
|
|
94754
|
-
import
|
|
95109
|
+
import { existsSync as existsSync21 } from "node:fs";
|
|
95110
|
+
import path51 from "node:path";
|
|
94755
95111
|
function parse7(argv) {
|
|
94756
95112
|
const options = {
|
|
94757
95113
|
paths: [],
|
|
@@ -94768,6 +95124,10 @@ function parse7(argv) {
|
|
|
94768
95124
|
};
|
|
94769
95125
|
for (let index = 0;index < argv.length; index += 1) {
|
|
94770
95126
|
const raw = argv[index];
|
|
95127
|
+
if (raw === "--") {
|
|
95128
|
+
options.paths.push(...argv.slice(index + 1));
|
|
95129
|
+
break;
|
|
95130
|
+
}
|
|
94771
95131
|
const [flag, inline] = raw.startsWith("--") && raw.includes("=") ? [raw.slice(0, raw.indexOf("=")), raw.slice(raw.indexOf("=") + 1)] : [raw, undefined];
|
|
94772
95132
|
if (flag === "--json")
|
|
94773
95133
|
continue;
|
|
@@ -94851,8 +95211,8 @@ async function run17(argv, io) {
|
|
|
94851
95211
|
return emit(io, fail("invalid_input", `${options}
|
|
94852
95212
|
usage: ${USAGE10}`));
|
|
94853
95213
|
const top = git6(io.cwd, ["rev-parse", "--show-toplevel"]);
|
|
94854
|
-
const repo = top.ok ?
|
|
94855
|
-
const display = (file) => toPosix(
|
|
95214
|
+
const repo = top.ok ? path51.resolve(top.stdout.trim()) : null;
|
|
95215
|
+
const display = (file) => toPosix(path51.relative(io.cwd, file) || file);
|
|
94856
95216
|
let base = null;
|
|
94857
95217
|
let changed = null;
|
|
94858
95218
|
if (options.diff || options.mutate) {
|
|
@@ -94869,7 +95229,7 @@ usage: ${USAGE10}`));
|
|
|
94869
95229
|
}
|
|
94870
95230
|
let files;
|
|
94871
95231
|
if (options.diff && changed)
|
|
94872
|
-
files = [...changed.keys()].filter((file) => TEST_FILE.test(toPosix(file)) &&
|
|
95232
|
+
files = [...changed.keys()].filter((file) => TEST_FILE.test(toPosix(file)) && existsSync21(file)).toSorted();
|
|
94873
95233
|
else {
|
|
94874
95234
|
const expanded = expandPaths(io.cwd, options.paths);
|
|
94875
95235
|
if (expanded.missing.length > 0)
|
|
@@ -94985,7 +95345,7 @@ var init_knowledge2 = __esm(() => {
|
|
|
94985
95345
|
init_output();
|
|
94986
95346
|
});
|
|
94987
95347
|
|
|
94988
|
-
// packages/workit-
|
|
95348
|
+
// packages/workit-core/src/core/youtrack-tools.ts
|
|
94989
95349
|
async function logTimeUpdate(input, operation = defaultOperations) {
|
|
94990
95350
|
try {
|
|
94991
95351
|
const value = await operation.logTime(input);
|
|
@@ -95034,7 +95394,7 @@ var init_youtrack_tools = __esm(() => {
|
|
|
95034
95394
|
};
|
|
95035
95395
|
});
|
|
95036
95396
|
|
|
95037
|
-
// packages/workit-
|
|
95397
|
+
// packages/workit-core/src/core/youtrack-writes.ts
|
|
95038
95398
|
async function markerPresent(issueId, marker, where) {
|
|
95039
95399
|
const creds = youTrackToken();
|
|
95040
95400
|
if ("error" in creds)
|
|
@@ -95094,8 +95454,8 @@ var exports_youtrack = {};
|
|
|
95094
95454
|
__export(exports_youtrack, {
|
|
95095
95455
|
run: () => run19
|
|
95096
95456
|
});
|
|
95097
|
-
import { readFileSync as
|
|
95098
|
-
import
|
|
95457
|
+
import { readFileSync as readFileSync23 } from "node:fs";
|
|
95458
|
+
import path52 from "node:path";
|
|
95099
95459
|
async function run19(argv, io) {
|
|
95100
95460
|
const [sub, ...rest] = argv;
|
|
95101
95461
|
if (sub !== "note" && sub !== "time" && sub !== "meeting")
|
|
@@ -95141,7 +95501,7 @@ async function run19(argv, io) {
|
|
|
95141
95501
|
let markdown = flags.values.markdown ?? "";
|
|
95142
95502
|
if (flags.values.file)
|
|
95143
95503
|
try {
|
|
95144
|
-
markdown =
|
|
95504
|
+
markdown = readFileSync23(path52.resolve(io.cwd, flags.values.file), "utf8");
|
|
95145
95505
|
} catch (error) {
|
|
95146
95506
|
return usage3(io, `cannot read ${flags.values.file}: ${String(error)}`, USAGE12);
|
|
95147
95507
|
}
|
|
@@ -95209,8 +95569,8 @@ var exports_changelog = {};
|
|
|
95209
95569
|
__export(exports_changelog, {
|
|
95210
95570
|
run: () => run20
|
|
95211
95571
|
});
|
|
95212
|
-
import { readFileSync as
|
|
95213
|
-
import
|
|
95572
|
+
import { readFileSync as readFileSync24 } from "node:fs";
|
|
95573
|
+
import path53 from "node:path";
|
|
95214
95574
|
async function run20(argv, io) {
|
|
95215
95575
|
const [sub, ...rest] = argv;
|
|
95216
95576
|
if (sub !== "apply")
|
|
@@ -95256,7 +95616,7 @@ async function run20(argv, io) {
|
|
|
95256
95616
|
]);
|
|
95257
95617
|
}
|
|
95258
95618
|
var USAGE13 = "workit changelog apply (--entries <JSON|@file|-> | --normalize-only) [--path CHANGELOG.md] [--preview]", readEntries = (raw, cwd) => {
|
|
95259
|
-
const text = raw === "-" ?
|
|
95619
|
+
const text = raw === "-" ? readFileSync24(0, "utf8") : raw.startsWith("@") ? readFileSync24(path53.resolve(cwd, raw.slice(1)), "utf8") : raw;
|
|
95260
95620
|
return JSON.parse(text);
|
|
95261
95621
|
};
|
|
95262
95622
|
var init_changelog2 = __esm(() => {
|
|
@@ -95339,7 +95699,7 @@ async function resumeBrief(argv, io) {
|
|
|
95339
95699
|
return emit(io, ok({ ...data, recorded }), human2);
|
|
95340
95700
|
}
|
|
95341
95701
|
async function run21(argv, io) {
|
|
95342
|
-
if (!argv.
|
|
95702
|
+
if (!argv.some((arg) => arg === "--task" || arg.startsWith("--task=")))
|
|
95343
95703
|
return resumeBrief(argv, io);
|
|
95344
95704
|
await Promise.resolve().then(() => init_task());
|
|
95345
95705
|
return runTaskCommand(["handoff", ...argv]);
|
|
@@ -95352,8 +95712,98 @@ var init_handoff = __esm(() => {
|
|
|
95352
95712
|
|
|
95353
95713
|
// packages/workit-cli/src/main.ts
|
|
95354
95714
|
init_package();
|
|
95715
|
+
import path54 from "node:path";
|
|
95716
|
+
|
|
95717
|
+
// packages/workit-cli/src/help.ts
|
|
95718
|
+
var HELP_FLAGS = new Set(["--help", "-h"]);
|
|
95719
|
+
var ESCAPE = "A value that starts with - goes as --flag=value (or after a bare --).";
|
|
95720
|
+
var options = (args) => {
|
|
95721
|
+
const end = args.indexOf("--");
|
|
95722
|
+
return end < 0 ? args : args.slice(0, end);
|
|
95723
|
+
};
|
|
95724
|
+
var wantsHelp = (args) => options(args).some((arg) => HELP_FLAGS.has(arg));
|
|
95725
|
+
var firstWord = (args) => options(args).find((arg) => !arg.startsWith("-"));
|
|
95726
|
+
var valueFlags = (lines) => {
|
|
95727
|
+
const out = new Map;
|
|
95728
|
+
const group = /(?<![\w-])(--?[a-zA-Z][\w-]*(?:\|--?[a-zA-Z][\w-]*)*) (?=[<"a-z0-9])/gu;
|
|
95729
|
+
for (const line of lines)
|
|
95730
|
+
for (const match of line.matchAll(group)) {
|
|
95731
|
+
const names = match[1].split("|");
|
|
95732
|
+
const long = names.find((name) => name.startsWith("--")) ?? names[0];
|
|
95733
|
+
for (const name of names)
|
|
95734
|
+
out.set(name, long);
|
|
95735
|
+
}
|
|
95736
|
+
return out;
|
|
95737
|
+
};
|
|
95738
|
+
function helpAsValue(args, lines) {
|
|
95739
|
+
const before = options(args);
|
|
95740
|
+
const takes = valueFlags(lines);
|
|
95741
|
+
for (let index = 1;index < before.length; index += 1) {
|
|
95742
|
+
const flag = before[index];
|
|
95743
|
+
const long = takes.get(before[index - 1]);
|
|
95744
|
+
if (HELP_FLAGS.has(flag) && long)
|
|
95745
|
+
return `\`${flag}\` looks like the value of ${before[index - 1]}; use ${long}=${flag} or put it after --`;
|
|
95746
|
+
}
|
|
95747
|
+
return null;
|
|
95748
|
+
}
|
|
95749
|
+
function takesPositionals(lines) {
|
|
95750
|
+
const flag = /(?<![\w-])--?[a-zA-Z][\w-]*(?:\|--?[a-zA-Z][\w-]*)*(?:[ =](?!-)(?:<[^>]*>|"[^"]*"|[\w.,@/|=-]+)…?)?/gu;
|
|
95751
|
+
return lines.some((line) => /<|"|\w…|\s…/u.test(line.replace(flag, "")));
|
|
95752
|
+
}
|
|
95753
|
+
var usageLines = (entry) => entry.subcommands?.length ? entry.subcommands.map((sub) => sub.usage) : [entry.usage];
|
|
95754
|
+
var examplesFor = (entry, sub) => (entry.examples ?? []).filter((example) => sub ? new RegExp(`^workit ${entry.name} ${sub.name}(?![\\w-])`, "u").test(example) : true);
|
|
95755
|
+
var exampleBlock = (examples) => examples.length ? ["", "examples:", ...examples.map((line) => ` ${line}`)] : [];
|
|
95756
|
+
function verbHelp(entry) {
|
|
95757
|
+
const subs = entry.subcommands ?? [];
|
|
95758
|
+
const usages = usageLines(entry);
|
|
95759
|
+
const examples = examplesFor(entry);
|
|
95760
|
+
const text = [
|
|
95761
|
+
...subs.length ? [
|
|
95762
|
+
`workit ${entry.name}: ${entry.summary}`,
|
|
95763
|
+
"",
|
|
95764
|
+
...subs.flatMap((sub) => [`usage: ${sub.usage}`, ` ${sub.summary}`])
|
|
95765
|
+
] : [`usage: ${entry.usage}`, "", entry.summary],
|
|
95766
|
+
...exampleBlock(examples),
|
|
95767
|
+
"",
|
|
95768
|
+
...subs.length ? [`More: workit help ${entry.name} <${subs.map((sub) => sub.name).join("|")}>`] : [],
|
|
95769
|
+
ESCAPE
|
|
95770
|
+
].join(`
|
|
95771
|
+
`);
|
|
95772
|
+
return {
|
|
95773
|
+
name: entry.name,
|
|
95774
|
+
group: entry.group,
|
|
95775
|
+
usage: usages[0],
|
|
95776
|
+
usages,
|
|
95777
|
+
summary: entry.summary,
|
|
95778
|
+
examples,
|
|
95779
|
+
text
|
|
95780
|
+
};
|
|
95781
|
+
}
|
|
95782
|
+
function subcommandHelp(entry, sub) {
|
|
95783
|
+
const examples = examplesFor(entry, sub);
|
|
95784
|
+
return {
|
|
95785
|
+
name: entry.name,
|
|
95786
|
+
group: entry.group,
|
|
95787
|
+
subcommand: sub.name,
|
|
95788
|
+
usage: sub.usage,
|
|
95789
|
+
usages: [sub.usage],
|
|
95790
|
+
summary: sub.summary,
|
|
95791
|
+
examples,
|
|
95792
|
+
text: [
|
|
95793
|
+
`usage: ${sub.usage}`,
|
|
95794
|
+
"",
|
|
95795
|
+
sub.summary,
|
|
95796
|
+
...exampleBlock(examples),
|
|
95797
|
+
"",
|
|
95798
|
+
...sub.aliases?.length ? [`aliases: ${sub.aliases.join(", ")}`] : [],
|
|
95799
|
+
ESCAPE
|
|
95800
|
+
].join(`
|
|
95801
|
+
`)
|
|
95802
|
+
};
|
|
95803
|
+
}
|
|
95804
|
+
|
|
95805
|
+
// packages/workit-cli/src/main.ts
|
|
95355
95806
|
init_output();
|
|
95356
|
-
import path52 from "node:path";
|
|
95357
95807
|
|
|
95358
95808
|
// packages/workit-cli/src/verbs/registry.ts
|
|
95359
95809
|
var TASK_FAMILY_NAMES = [
|
|
@@ -95365,13 +95815,97 @@ var TASK_FAMILY_NAMES = [
|
|
|
95365
95815
|
"worker",
|
|
95366
95816
|
"state"
|
|
95367
95817
|
];
|
|
95368
|
-
var
|
|
95818
|
+
var FAMILY_OPTIONS = "[--task <id>] [--payload <JSON|@file|->] [--revision <r>] [--workspace-revision <r|null>] [--view <v>] [--actor <a>] [--confirm]";
|
|
95819
|
+
var FAMILY_ACTIONS = {
|
|
95820
|
+
task: {
|
|
95821
|
+
list: "List the workspace's tasks",
|
|
95822
|
+
inspect: "Show one task's full state",
|
|
95823
|
+
revise: "Change a task's intent or scope",
|
|
95824
|
+
progress: "Record progress on a task",
|
|
95825
|
+
pause: "Pause a task",
|
|
95826
|
+
resume: "Resume a paused task",
|
|
95827
|
+
start: "Start a task from a full payload",
|
|
95828
|
+
close: "Close a task by id"
|
|
95829
|
+
},
|
|
95830
|
+
policy: {
|
|
95831
|
+
assess: "Judge the branch's work and record the derived checks, verdicts and gates",
|
|
95832
|
+
preview: "Show what a judgment would derive, without recording it",
|
|
95833
|
+
explain: "Explain the policy in force"
|
|
95834
|
+
},
|
|
95835
|
+
evidence: { record: "Record evidence against a task's requirements" },
|
|
95836
|
+
finding: { record: "Record a finding", resolve: "Resolve a finding" },
|
|
95837
|
+
decision: { record: "Record a task decision", revoke: "Revoke a task decision" },
|
|
95838
|
+
worker: {
|
|
95839
|
+
assign: "Assign a worker to a task",
|
|
95840
|
+
report: "Report a worker's result",
|
|
95841
|
+
cancel: "Cancel a worker assignment"
|
|
95842
|
+
},
|
|
95843
|
+
state: { export: "Export a task's state (v1)", import: "Import an exported task state" }
|
|
95844
|
+
};
|
|
95845
|
+
var POLICY_JUDGE = "--judge risk=trivial|normal|high behavior=yes|no product-choice=yes|no plan=yes|no [--ref <path>]…";
|
|
95846
|
+
var TASK_IMPLICIT = [
|
|
95847
|
+
{
|
|
95848
|
+
name: "status",
|
|
95849
|
+
usage: "workit task status [--all]",
|
|
95850
|
+
summary: "The current branch's task, or every task with --all"
|
|
95851
|
+
},
|
|
95852
|
+
{
|
|
95853
|
+
name: "start",
|
|
95854
|
+
usage: `workit task start "<objective>" | task start ${FAMILY_OPTIONS}`,
|
|
95855
|
+
summary: "Start tracking the current branch's task (idempotent per branch)"
|
|
95856
|
+
},
|
|
95857
|
+
{
|
|
95858
|
+
name: "note",
|
|
95859
|
+
usage: 'workit task note [--next "<t>"] [--objective "<t>"] [--] "<text>"',
|
|
95860
|
+
summary: "Add a progress note to the current branch's task (creates it if needed)"
|
|
95861
|
+
},
|
|
95862
|
+
{
|
|
95863
|
+
name: "close",
|
|
95864
|
+
usage: `workit task close [--outcome verified|limited|stopped] [--summary "<t>"] [--confirm] | task close ${FAMILY_OPTIONS}`,
|
|
95865
|
+
summary: "Close the current branch's task, or a task by id"
|
|
95866
|
+
},
|
|
95867
|
+
{
|
|
95868
|
+
name: "adopt",
|
|
95869
|
+
usage: "workit task adopt <id>",
|
|
95870
|
+
summary: "Bind a migrated or other task to the current branch"
|
|
95871
|
+
}
|
|
95872
|
+
];
|
|
95873
|
+
var familySubcommands = (name) => {
|
|
95874
|
+
const implicit = name === "task" ? TASK_IMPLICIT : [];
|
|
95875
|
+
const grammar = Object.entries(FAMILY_ACTIONS[name]).filter(([action]) => !implicit.some((entry) => entry.name === action)).map(([action, summary]) => ({
|
|
95876
|
+
name: action,
|
|
95877
|
+
usage: name === "policy" && action !== "explain" ? `workit policy ${action} ${POLICY_JUDGE} ${FAMILY_OPTIONS}` : `workit ${name} ${action} ${FAMILY_OPTIONS}`,
|
|
95878
|
+
summary
|
|
95879
|
+
}));
|
|
95880
|
+
return [...implicit, ...grammar];
|
|
95881
|
+
};
|
|
95882
|
+
var family = (name) => withSubcommands({
|
|
95369
95883
|
name,
|
|
95370
95884
|
group: "task",
|
|
95371
|
-
usage: name === "task" ? 'workit task status [--all] | task start "<objective>" | task note "<text>" [--next "<t>"] | task close [--outcome verified|limited|stopped] | task adopt <id> | task <action> --payload <JSON>' : name === "policy" ? "workit policy assess|preview --judge risk=trivial|normal|high behavior=yes|no product-choice=yes|no plan=yes|no [--ref <path>] | policy explain" : `workit ${name} <action> [options]`,
|
|
95372
95885
|
summary: name === "task" ? "The current branch's task (created by its first note, check or recording; no ids needed), or the task family" : name === "policy" ? "Judge the branch's work; Workit derives its checks, verdicts, decision and plan gates" : `Inspect and control a Workit task (${name} family)`,
|
|
95886
|
+
subcommands: familySubcommands(name),
|
|
95887
|
+
...name === "task" ? {
|
|
95888
|
+
examples: [
|
|
95889
|
+
'workit task note "parser done; wiring the router" --next "add the router test"',
|
|
95890
|
+
"workit task close --outcome verified"
|
|
95891
|
+
]
|
|
95892
|
+
} : name === "policy" ? {
|
|
95893
|
+
examples: [
|
|
95894
|
+
"workit policy assess --judge risk=normal behavior=yes product-choice=no plan=no"
|
|
95895
|
+
]
|
|
95896
|
+
} : {},
|
|
95373
95897
|
load: async () => (await Promise.resolve().then(() => (init_family(), exports_family))).familyVerb(name)
|
|
95374
95898
|
});
|
|
95899
|
+
function withSubcommands(entry, options = {}) {
|
|
95900
|
+
const names = entry.subcommands.map((sub) => sub.name).join("|");
|
|
95901
|
+
return {
|
|
95902
|
+
...entry,
|
|
95903
|
+
usage: `workit ${entry.name} ${options.optional ? `[${names}]` : names} [options]`,
|
|
95904
|
+
...options.optional ? { optionalSubcommand: true } : {}
|
|
95905
|
+
};
|
|
95906
|
+
}
|
|
95907
|
+
var VERIFY_OPTIONS = "[--expect pushed|pr|merged|released] [--pr <n> | --branch <b>] [--sha <sha>] [--tag <t>] [--package <name[@version]>]";
|
|
95908
|
+
var LEDGER_ACTOR = "[--branch <b> | --pr <n>] [--supersedes <id>] [--session <id> | --as <role>]";
|
|
95375
95909
|
var VERBS = [
|
|
95376
95910
|
{
|
|
95377
95911
|
name: "init",
|
|
@@ -95383,28 +95917,28 @@ var VERBS = [
|
|
|
95383
95917
|
{
|
|
95384
95918
|
name: "upgrade",
|
|
95385
95919
|
group: "setup",
|
|
95386
|
-
usage: "workit upgrade [--hosts=a,b|none] [--cli] [--preview | --apply --confirm]
|
|
95920
|
+
usage: "workit upgrade [--hosts=a,b|none] [--cli] [--preview | --apply --confirm]",
|
|
95387
95921
|
summary: "Preview upgrades (--apply --confirm to apply)",
|
|
95388
95922
|
load: () => Promise.resolve().then(() => (init_upgrade2(), exports_upgrade))
|
|
95389
95923
|
},
|
|
95390
95924
|
{
|
|
95391
95925
|
name: "launch",
|
|
95392
95926
|
group: "setup",
|
|
95393
|
-
usage: "workit launch <host> [--auto-upgrade] [-- args]",
|
|
95927
|
+
usage: "workit launch <host> [--auto-upgrade] [-- <host args…>]",
|
|
95394
95928
|
summary: "Upgrade before host startup, then start the host",
|
|
95395
95929
|
load: () => Promise.resolve().then(() => (init_launch(), exports_launch))
|
|
95396
95930
|
},
|
|
95397
95931
|
{
|
|
95398
95932
|
name: "doctor",
|
|
95399
95933
|
group: "setup",
|
|
95400
|
-
usage: "workit doctor [--
|
|
95934
|
+
usage: "workit doctor [--fix-lock [--force [--yes]]]",
|
|
95401
95935
|
summary: "Verify the offline installation health (--fix-lock clears a stale workit store lock)",
|
|
95402
95936
|
load: () => Promise.resolve().then(() => (init_doctor2(), exports_doctor))
|
|
95403
95937
|
},
|
|
95404
95938
|
{
|
|
95405
95939
|
name: "gc",
|
|
95406
95940
|
group: "setup",
|
|
95407
|
-
usage: "workit gc [--dry-run] [--prune-recovery --yes]
|
|
95941
|
+
usage: "workit gc [--dry-run] [--prune-recovery --yes]",
|
|
95408
95942
|
summary: "Compact long task event logs, drop unreferenced blobs and old check logs; report (or prune) 2.x recovery copies",
|
|
95409
95943
|
load: () => Promise.resolve().then(() => (init_gc(), exports_gc))
|
|
95410
95944
|
},
|
|
@@ -95415,108 +95949,313 @@ var VERBS = [
|
|
|
95415
95949
|
summary: "Remove workit host registrations interactively (~/.config/workit is kept)",
|
|
95416
95950
|
load: () => Promise.resolve().then(() => (init_uninstall2(), exports_uninstall))
|
|
95417
95951
|
},
|
|
95418
|
-
{
|
|
95952
|
+
withSubcommands({
|
|
95419
95953
|
name: "grant",
|
|
95420
95954
|
group: "setup",
|
|
95421
|
-
usage: "workit grant show [<workspace>] [--all] | grant set <workspace> <kind>=<true|false|verified>… | grant unset <workspace> <kind>…",
|
|
95422
95955
|
summary: "Show or change a workspace's autonomy grants (push, pr, merge, release, rerun) and default endpoint; raising needs the user at a terminal",
|
|
95956
|
+
subcommands: [
|
|
95957
|
+
{
|
|
95958
|
+
name: "show",
|
|
95959
|
+
usage: "workit grant show [<workspace>] [--all]",
|
|
95960
|
+
summary: "Show the grants of the current (or named) workspace, or of every workspace"
|
|
95961
|
+
},
|
|
95962
|
+
{
|
|
95963
|
+
name: "set",
|
|
95964
|
+
usage: "workit grant set <workspace> <kind>=<true|false|verified>… [defaultEndpoint=commit|pr|green|merged] [verification=self|independent]",
|
|
95965
|
+
summary: "Change grants (kinds: push, pr, merge, release, rerun); raising one asks the user to confirm at a terminal"
|
|
95966
|
+
},
|
|
95967
|
+
{
|
|
95968
|
+
name: "unset",
|
|
95969
|
+
usage: "workit grant unset <workspace> <kind>…",
|
|
95970
|
+
summary: "Remove grants, falling back to the defaults"
|
|
95971
|
+
}
|
|
95972
|
+
],
|
|
95973
|
+
examples: ["workit grant show", "workit grant set my-repo push=true pr=true"],
|
|
95423
95974
|
load: () => Promise.resolve().then(() => (init_grant(), exports_grant))
|
|
95424
|
-
},
|
|
95975
|
+
}, { optional: true }),
|
|
95425
95976
|
...TASK_FAMILY_NAMES.map(family),
|
|
95426
95977
|
{
|
|
95427
95978
|
name: "check",
|
|
95428
95979
|
group: "delivery",
|
|
95429
|
-
usage: "workit check <name> | workit check [--name <n>] [--shell] [--timeout <s>] [--task <id>] -- <cmd…>",
|
|
95980
|
+
usage: "workit check <name> [--task <id>] [--base <ref>] | workit check [--name <n>] [--shell] [--timeout <s>] [--task <id>] [--base <ref>] -- <cmd…>",
|
|
95430
95981
|
summary: "Run a configured or ad-hoc check and record CLI-observed evidence (exit = the command's)",
|
|
95982
|
+
examples: ["workit check test", "workit check --name unit -- bun test test/unit"],
|
|
95431
95983
|
load: () => Promise.resolve().then(() => (init_check(), exports_check))
|
|
95432
95984
|
},
|
|
95433
|
-
{
|
|
95985
|
+
withSubcommands({
|
|
95434
95986
|
name: "pr",
|
|
95435
95987
|
group: "delivery",
|
|
95436
|
-
usage: "workit pr status [--pr <n>] | pr create [--base <b> | --track <t>] (--title <t> | --fill) [--draft] | pr merge [--pr <n>] [--method squash|merge|rebase] [--delete-branch] [--unverified --reason <why>]",
|
|
95437
95988
|
summary: "PR/MR state with failing log tails and next action; open a SHA-verified PR; merge only when READY, verified and granted",
|
|
95989
|
+
subcommands: [
|
|
95990
|
+
{
|
|
95991
|
+
name: "status",
|
|
95992
|
+
usage: "workit pr status [--pr <n> | --branch <b>] [--log-lines 60]",
|
|
95993
|
+
summary: "PR/MR state, failing check log tails and the next action"
|
|
95994
|
+
},
|
|
95995
|
+
{
|
|
95996
|
+
name: "create",
|
|
95997
|
+
usage: "workit pr create [--base <b> | --track <t>] (--title <t> [--body <text> | --body-file <f>] | --fill) [--draft]",
|
|
95998
|
+
summary: "Open a PR/MR for the pushed branch, verified against the local HEAD"
|
|
95999
|
+
},
|
|
96000
|
+
{
|
|
96001
|
+
name: "merge",
|
|
96002
|
+
usage: "workit pr merge [--pr <n>] [--method squash|merge|rebase] [--delete-branch] [--unverified --reason <why>]",
|
|
96003
|
+
summary: "Merge when READY, verified by a non-author and granted"
|
|
96004
|
+
}
|
|
96005
|
+
],
|
|
96006
|
+
examples: [
|
|
96007
|
+
'workit pr create --title "fix(cli): answer help flags first" --body-file pr.md',
|
|
96008
|
+
"workit pr merge --method squash --delete-branch"
|
|
96009
|
+
],
|
|
95438
96010
|
load: () => Promise.resolve().then(() => (init_pr(), exports_pr))
|
|
95439
|
-
},
|
|
95440
|
-
{
|
|
96011
|
+
}),
|
|
96012
|
+
withSubcommands({
|
|
95441
96013
|
name: "ci",
|
|
95442
96014
|
group: "delivery",
|
|
95443
|
-
usage: "workit ci wait [--pr <n>] [--head <sha>] [--timeout 20m] | ci rerun [--failed | --check <name>…] --reason flake|infra [--force]",
|
|
95444
96015
|
summary: "Wait for CI on the PR head (exit 0/1/3/4), or rerun failed jobs once per head",
|
|
96016
|
+
subcommands: [
|
|
96017
|
+
{
|
|
96018
|
+
name: "wait",
|
|
96019
|
+
usage: "workit ci wait [--pr <n> | --branch <b>] [--head <sha>] [--timeout 20m] [--interval 30s]",
|
|
96020
|
+
summary: "Wait for CI on the PR head; exit 0 green, 1 red, 3 blocked, 4 still pending"
|
|
96021
|
+
},
|
|
96022
|
+
{
|
|
96023
|
+
name: "rerun",
|
|
96024
|
+
usage: "workit ci rerun [--pr <n> | --branch <b>] [--check <name>… | --failed] --reason flake|infra [--force]",
|
|
96025
|
+
summary: "Rerun failed jobs once per head, with a recorded reason"
|
|
96026
|
+
}
|
|
96027
|
+
],
|
|
96028
|
+
examples: ["workit ci wait --timeout 30m", "workit ci rerun --failed --reason flake"],
|
|
95445
96029
|
load: () => Promise.resolve().then(() => (init_ci(), exports_ci))
|
|
95446
|
-
},
|
|
95447
|
-
{
|
|
96030
|
+
}),
|
|
96031
|
+
withSubcommands({
|
|
95448
96032
|
name: "git",
|
|
95449
96033
|
group: "delivery",
|
|
95450
|
-
usage: "workit git branch <name> [--base <b>] [--track <t>] | git commit -m <msg> [--all | -- <paths…>] | git push [--set-upstream] [--force-with-lease]",
|
|
95451
96034
|
summary: "Policy-checked branch and commit (Workit-Session trailer); push with a lease and a verified remote tip",
|
|
96035
|
+
subcommands: [
|
|
96036
|
+
{
|
|
96037
|
+
name: "branch",
|
|
96038
|
+
usage: "workit git branch <name> | git branch --kind feature|bugfix|hotfix --slug <s> [--base <b>] [--track <t>] [--carry]",
|
|
96039
|
+
summary: "Create and switch to a branch from the trunk or a release track"
|
|
96040
|
+
},
|
|
96041
|
+
{
|
|
96042
|
+
name: "commit",
|
|
96043
|
+
usage: "workit git commit -m|--message <msg>… | -F|--file <file|-> [--amend [--no-edit]] [--allow-empty] [-a|--all | [--] <paths…>]",
|
|
96044
|
+
summary: "Commit (or --amend) with a linted Conventional Commit message and the session trailer"
|
|
96045
|
+
},
|
|
96046
|
+
{
|
|
96047
|
+
name: "push",
|
|
96048
|
+
usage: "workit git push [-u|--set-upstream] [--force-with-lease [--expect <sha>] [--overwrite-unintegrated]]",
|
|
96049
|
+
summary: "Push the current branch and verify the remote tip (never a blind --force)"
|
|
96050
|
+
}
|
|
96051
|
+
],
|
|
96052
|
+
examples: [
|
|
96053
|
+
"workit git branch --kind feature --slug help-everywhere",
|
|
96054
|
+
'workit git commit -m "fix(cli): answer help flags first" --all',
|
|
96055
|
+
"workit git commit --amend --no-edit -- src/forgotten.ts",
|
|
96056
|
+
"workit git push --set-upstream"
|
|
96057
|
+
],
|
|
95452
96058
|
load: () => Promise.resolve().then(() => (init_git2(), exports_git))
|
|
95453
|
-
},
|
|
95454
|
-
{
|
|
96059
|
+
}),
|
|
96060
|
+
withSubcommands({
|
|
95455
96061
|
name: "verify-delivery",
|
|
95456
96062
|
group: "delivery",
|
|
95457
|
-
usage: "workit verify-delivery [push|pr|merge|release] [--pr <n> | --branch <b>] [--sha <s>] [--tag <t>] [--package <p>]",
|
|
95458
96063
|
summary: "Observe that a push, PR head, merge or release really landed on the remote (exit 1 when not)",
|
|
96064
|
+
subcommands: [
|
|
96065
|
+
["push", "pushed", "the branch's remote tip is the local HEAD"],
|
|
96066
|
+
["pr", null, "the PR head is the local HEAD"],
|
|
96067
|
+
["merge", "merged", "the PR merged into its base"],
|
|
96068
|
+
["release", "released", "the release tag and package exist"]
|
|
96069
|
+
].map(([name, alias, what]) => ({
|
|
96070
|
+
name,
|
|
96071
|
+
...alias ? { aliases: [alias] } : {},
|
|
96072
|
+
usage: `workit verify-delivery ${name} ${VERIFY_OPTIONS}`,
|
|
96073
|
+
summary: `Observe that ${what}`
|
|
96074
|
+
})),
|
|
96075
|
+
examples: ["workit verify-delivery push", "workit verify-delivery merge --pr 42"],
|
|
95459
96076
|
load: () => Promise.resolve().then(() => (init_verify_delivery(), exports_verify_delivery))
|
|
95460
|
-
},
|
|
95461
|
-
{
|
|
96077
|
+
}, { optional: true }),
|
|
96078
|
+
withSubcommands({
|
|
95462
96079
|
name: "stack",
|
|
95463
96080
|
group: "delivery",
|
|
95464
|
-
usage: "workit stack plan [<bottom> … <top>] | status | sync [--local] | land [--dry-run] [--max <n>] [--unverified --reason <why>] [--json]",
|
|
95465
96081
|
summary: "Plan, restack (lease push + retarget) and land a base-branch stack of PRs, root first",
|
|
96082
|
+
subcommands: [
|
|
96083
|
+
{
|
|
96084
|
+
name: "plan",
|
|
96085
|
+
usage: "workit stack plan [--name <n>] [--trunk <b> | --track <t>] [<bottom> … <top>]",
|
|
96086
|
+
summary: "Record the stack's branches, bottom first"
|
|
96087
|
+
},
|
|
96088
|
+
{
|
|
96089
|
+
name: "status",
|
|
96090
|
+
usage: "workit stack status [--name <n>]",
|
|
96091
|
+
summary: "Each stacked PR's base, head, CI and verdict"
|
|
96092
|
+
},
|
|
96093
|
+
{
|
|
96094
|
+
name: "sync",
|
|
96095
|
+
usage: "workit stack sync [--name <n>] [--local] [--dry-run] [--force <branch>]…",
|
|
96096
|
+
summary: "Restack onto the moved bases, lease-push and retarget the PRs"
|
|
96097
|
+
},
|
|
96098
|
+
{
|
|
96099
|
+
name: "land",
|
|
96100
|
+
usage: "workit stack land [--name <n>] [--dry-run] [--max <n>] [--method squash|merge|rebase] [--unverified --reason <why>] [--timeout 20m] [--interval 30s]",
|
|
96101
|
+
summary: "Merge the stack root first, restacking the rest as each lands"
|
|
96102
|
+
}
|
|
96103
|
+
],
|
|
96104
|
+
examples: ["workit stack plan feature/a feature/b feature/c", "workit stack land --dry-run"],
|
|
95466
96105
|
load: () => Promise.resolve().then(() => (init_stack2(), exports_stack))
|
|
95467
|
-
},
|
|
95468
|
-
{
|
|
96106
|
+
}),
|
|
96107
|
+
withSubcommands({
|
|
95469
96108
|
name: "fanout",
|
|
95470
96109
|
group: "delivery",
|
|
95471
|
-
usage: "workit fanout plan <plan.json> [--name <n>] [--trunk <b> | --track <t>] [--take-lead] | fanout brief <slice> [--mode new|resume] [--attempt <n>] | fanout check [<slice>…] [--name <n>] [--base <ref>] [--offline] | fanout status [--name <n>] [--stuck-after 30m] [--offline] | fanout worktree create|release <slice> [--force] [--json]",
|
|
95472
96110
|
summary: "Register parallel slices (complete briefs, disjoint scopes, shared-file owners), render each worker's brief with the standing orders, watch them (STUCK, PR, CI, verdict, landed, landing order), make and release slice worktrees, and gate fan-in: out-of-scope edits, trunk and sibling merge conflicts",
|
|
96111
|
+
subcommands: [
|
|
96112
|
+
{
|
|
96113
|
+
name: "plan",
|
|
96114
|
+
usage: "workit fanout plan <plan.json> [--name <n>] [--trunk <b> | --track <t>] [--take-lead]",
|
|
96115
|
+
summary: "Register the slices of a plan file"
|
|
96116
|
+
},
|
|
96117
|
+
{
|
|
96118
|
+
name: "brief",
|
|
96119
|
+
usage: "workit fanout brief <slice> [--mode new|resume] [--attempt <n>] [--name <n>]",
|
|
96120
|
+
summary: "Render one worker's brief with the standing orders"
|
|
96121
|
+
},
|
|
96122
|
+
{
|
|
96123
|
+
name: "check",
|
|
96124
|
+
usage: "workit fanout check [<slice>…] [--name <n>] [--base <ref>] [--offline]",
|
|
96125
|
+
summary: "Gate fan-in: out-of-scope edits, trunk and sibling merge conflicts"
|
|
96126
|
+
},
|
|
96127
|
+
{
|
|
96128
|
+
name: "status",
|
|
96129
|
+
usage: "workit fanout status [--name <n>] [--stuck-after 30m] [--offline]",
|
|
96130
|
+
summary: "Each slice's state: STUCK, PR, CI, verdict, landed, landing order"
|
|
96131
|
+
},
|
|
96132
|
+
{
|
|
96133
|
+
name: "worktree",
|
|
96134
|
+
usage: "workit fanout worktree create|release <slice> [--name <n>] [--force]",
|
|
96135
|
+
summary: "Make or release a slice's worktree (--force applies to release only)"
|
|
96136
|
+
}
|
|
96137
|
+
],
|
|
96138
|
+
examples: [
|
|
96139
|
+
"workit fanout plan plan.json --take-lead",
|
|
96140
|
+
"workit fanout status --stuck-after 20m"
|
|
96141
|
+
],
|
|
95473
96142
|
load: () => Promise.resolve().then(() => (init_fanout2(), exports_fanout))
|
|
95474
|
-
},
|
|
95475
|
-
{
|
|
96143
|
+
}),
|
|
96144
|
+
withSubcommands({
|
|
95476
96145
|
name: "ledger",
|
|
95477
96146
|
group: "delivery",
|
|
95478
|
-
usage: "workit ledger decision|ruling|verdict|standing|list|check ...",
|
|
95479
96147
|
summary: "Record and query decisions, rulings, SHA-keyed verdicts (patch-id carry-over across rebases) and a fanout's standing orders",
|
|
96148
|
+
subcommands: [
|
|
96149
|
+
{
|
|
96150
|
+
name: "decision",
|
|
96151
|
+
usage: `workit ledger decision "<what>" --why "<why>" [--ref <path|url>]… ${LEDGER_ACTOR}`,
|
|
96152
|
+
summary: "Record a decision and why"
|
|
96153
|
+
},
|
|
96154
|
+
{
|
|
96155
|
+
name: "ruling",
|
|
96156
|
+
usage: `workit ledger ruling "<what>" --why "<why>" --cost-if-wrong "<cost>" [--ref <path|url>]… ${LEDGER_ACTOR}`,
|
|
96157
|
+
summary: "Record a ruling on an open choice, with the cost of being wrong"
|
|
96158
|
+
},
|
|
96159
|
+
{
|
|
96160
|
+
name: "verdict",
|
|
96161
|
+
usage: `workit ledger verdict <result> --how "<method/evidence>" [--kind unit|live|perf|review] [--base <ref>] [--surface ui|cli|api] [--evidence <ref>]… [--self] ${LEDGER_ACTOR} | ledger verdict [<branch>]`,
|
|
96162
|
+
summary: "Record a SHA-keyed verdict on the branch head (result: verified, tests-verified, type-check-only, blocked, failed), or show the current verdicts"
|
|
96163
|
+
},
|
|
96164
|
+
{
|
|
96165
|
+
name: "list",
|
|
96166
|
+
aliases: ["show"],
|
|
96167
|
+
usage: "workit ledger list|show [--branch <b>] [--pr <n>] [--type <t>] [--last <n>]",
|
|
96168
|
+
summary: "List ledger rows, newest last"
|
|
96169
|
+
},
|
|
96170
|
+
{
|
|
96171
|
+
name: "check",
|
|
96172
|
+
usage: "workit ledger check [--pr <n> | --branch <b>]",
|
|
96173
|
+
summary: "Whether the branch head carries an accepted non-author verdict"
|
|
96174
|
+
},
|
|
96175
|
+
{
|
|
96176
|
+
name: "standing",
|
|
96177
|
+
usage: `workit ledger standing add "<order>" | standing list | standing clear [<id>] [--fanout <name>] [--supersedes <id>] [--session <id> | --as <role>]`,
|
|
96178
|
+
summary: "The lead's standing orders for a fanout's workers"
|
|
96179
|
+
},
|
|
96180
|
+
{
|
|
96181
|
+
name: "add",
|
|
96182
|
+
usage: 'workit ledger add decision|ruling|verdict "<what>" …',
|
|
96183
|
+
summary: "Same as the bare decision, ruling and verdict forms"
|
|
96184
|
+
}
|
|
96185
|
+
],
|
|
96186
|
+
examples: [
|
|
96187
|
+
'workit ledger decision "keep the registry as the help source" --why "one place to update"',
|
|
96188
|
+
'workit ledger verdict verified --how "ran the CLI against a scratch repo" --kind live --as verifier'
|
|
96189
|
+
],
|
|
95480
96190
|
load: () => Promise.resolve().then(() => (init_ledger2(), exports_ledger))
|
|
95481
|
-
},
|
|
96191
|
+
}),
|
|
95482
96192
|
{
|
|
95483
96193
|
name: "test-audit",
|
|
95484
96194
|
group: "delivery",
|
|
95485
|
-
usage: "workit test-audit [paths…] [--diff [base]] [--rule <ids>] [--min-severity <level>] [--fail-on <level>] [--mutate [--test-cmd <cmd {files}>] [--max-mutants <n>] [--budget <s>]
|
|
96195
|
+
usage: "workit test-audit [paths…] [--diff [<base>]] [--rule <ids>] [--min-severity <level>] [--fail-on <level>] [--mutate [--test-cmd <cmd {files}>] [--max-mutants <n>] [--budget <s>] [--timeout <s>]]",
|
|
95486
96196
|
summary: "Flag tautological and low-value tests with a suggested independent oracle; --mutate checks changed lines with diff-scoped mutation",
|
|
95487
96197
|
load: () => Promise.resolve().then(() => (init_test_audit(), exports_test_audit))
|
|
95488
96198
|
},
|
|
95489
|
-
{
|
|
96199
|
+
withSubcommands({
|
|
95490
96200
|
name: "knowledge",
|
|
95491
96201
|
group: "delivery",
|
|
95492
|
-
usage: "workit knowledge lint [--json]",
|
|
95493
96202
|
summary: "Lint agent knowledge files: AGENTS.md byte budget, broken local links, scaffold-only files, duplicated rules (exit 1 on findings)",
|
|
96203
|
+
subcommands: [
|
|
96204
|
+
{
|
|
96205
|
+
name: "lint",
|
|
96206
|
+
usage: "workit knowledge lint",
|
|
96207
|
+
summary: "Lint AGENTS.md and the knowledge files it links"
|
|
96208
|
+
}
|
|
96209
|
+
],
|
|
95494
96210
|
load: () => Promise.resolve().then(() => (init_knowledge2(), exports_knowledge))
|
|
95495
|
-
},
|
|
95496
|
-
{
|
|
96211
|
+
}),
|
|
96212
|
+
withSubcommands({
|
|
95497
96213
|
name: "youtrack",
|
|
95498
96214
|
group: "delivery",
|
|
95499
|
-
usage: "workit youtrack note <ISSUE> (--markdown <t> | --file <p>) [--minutes <n>] | youtrack time|meeting <ISSUE> --minutes <n> [--text <t>] [--date auto|YYYY-MM-DD]",
|
|
95500
96215
|
summary: "Post a YouTrack comment or log work time (host permission, no grant)",
|
|
96216
|
+
subcommands: [
|
|
96217
|
+
{
|
|
96218
|
+
name: "note",
|
|
96219
|
+
usage: "workit youtrack note <ISSUE> (--markdown <t> | --file <p>) [--minutes <n>] [--date auto|YYYY-MM-DD]",
|
|
96220
|
+
summary: "Post a comment, optionally logging time"
|
|
96221
|
+
},
|
|
96222
|
+
{
|
|
96223
|
+
name: "time",
|
|
96224
|
+
usage: "workit youtrack time <ISSUE> --minutes <n> [--text <t>] [--date auto|YYYY-MM-DD]",
|
|
96225
|
+
summary: "Log work time"
|
|
96226
|
+
},
|
|
96227
|
+
{
|
|
96228
|
+
name: "meeting",
|
|
96229
|
+
usage: "workit youtrack meeting <ISSUE> --minutes <n> --text <t> [--date auto|YYYY-MM-DD]",
|
|
96230
|
+
summary: "Log meeting time"
|
|
96231
|
+
}
|
|
96232
|
+
],
|
|
95501
96233
|
load: () => Promise.resolve().then(() => (init_youtrack2(), exports_youtrack))
|
|
95502
|
-
},
|
|
95503
|
-
{
|
|
96234
|
+
}),
|
|
96235
|
+
withSubcommands({
|
|
95504
96236
|
name: "changelog",
|
|
95505
96237
|
group: "delivery",
|
|
95506
|
-
usage: "workit changelog apply (--entries <JSON|@file|-> | --normalize-only) [--path CHANGELOG.md] [--preview]",
|
|
95507
96238
|
summary: "Add entries under the Unreleased section of the changelog",
|
|
96239
|
+
subcommands: [
|
|
96240
|
+
{
|
|
96241
|
+
name: "apply",
|
|
96242
|
+
usage: "workit changelog apply (--entries <JSON|@file|-> | --normalize-only) [--path CHANGELOG.md] [--preview]",
|
|
96243
|
+
summary: "Add entries (or only normalize the file)"
|
|
96244
|
+
}
|
|
96245
|
+
],
|
|
95508
96246
|
load: () => Promise.resolve().then(() => (init_changelog2(), exports_changelog))
|
|
95509
|
-
},
|
|
96247
|
+
}),
|
|
95510
96248
|
{
|
|
95511
96249
|
name: "handoff",
|
|
95512
96250
|
group: "delivery",
|
|
95513
|
-
usage: "workit handoff [--note <t>] [--next <t>] [--record] | workit handoff --task <id>",
|
|
96251
|
+
usage: "workit handoff [--note <t>] [--next <t>] [--record] [--last <n>] | workit handoff --task <id>",
|
|
95514
96252
|
summary: "Print a resume brief (branch, HEAD, dirty state, verdict, rulings, next command); --task exports v1 task state",
|
|
95515
96253
|
load: () => Promise.resolve().then(() => (init_handoff(), exports_handoff))
|
|
95516
96254
|
}
|
|
95517
96255
|
];
|
|
95518
96256
|
var BY_NAME = new Map(VERBS.map((entry) => [entry.name, entry]));
|
|
95519
96257
|
var findVerb = (name) => BY_NAME.get(name);
|
|
96258
|
+
var findSubcommand = (entry, name) => entry.subcommands?.find((sub) => sub.name === name || sub.aliases?.includes(name));
|
|
95520
96259
|
|
|
95521
96260
|
// packages/workit-cli/src/main.ts
|
|
95522
96261
|
var GROUP_TITLES = {
|
|
@@ -95548,20 +96287,17 @@ ${sections.join(`
|
|
|
95548
96287
|
`)}
|
|
95549
96288
|
|
|
95550
96289
|
Global flags:
|
|
95551
|
-
--json
|
|
95552
|
-
--cwd <dir>
|
|
95553
|
-
--version
|
|
95554
|
-
help
|
|
96290
|
+
--json Machine-readable output: {"ok","code","data","error"?,"unblock"?}
|
|
96291
|
+
--cwd <dir> Run as if started in <dir>
|
|
96292
|
+
--version Print the CLI version
|
|
96293
|
+
-h, --help Show usage for the command and subcommand before it (runs nothing)
|
|
96294
|
+
help <cmd> [<sub>] The same, as a command
|
|
95555
96295
|
|
|
95556
96296
|
Exit codes: 0 ok · 1 failed · 2 usage · 3 blocked · 4 busy/pending · 5 unavailable
|
|
95557
96297
|
|
|
95558
96298
|
Run \`npx @brainervirus/workit-cli init\` to configure platforms, YouTrack, VCS and project hygiene.
|
|
95559
96299
|
`;
|
|
95560
96300
|
}
|
|
95561
|
-
var verbHelp = (entry) => `usage: ${entry.usage}
|
|
95562
|
-
|
|
95563
|
-
${entry.summary}${entry.planned ? ` (coming in ${entry.planned})` : ""}
|
|
95564
|
-
`;
|
|
95565
96301
|
function parseGlobals(argv) {
|
|
95566
96302
|
const rest = [];
|
|
95567
96303
|
let json = false;
|
|
@@ -95597,7 +96333,7 @@ var defaultIo = (json) => ({
|
|
|
95597
96333
|
});
|
|
95598
96334
|
async function main(argv, overrides = {}, options = {}) {
|
|
95599
96335
|
const parsed = parseGlobals(argv);
|
|
95600
|
-
const cwd =
|
|
96336
|
+
const cwd = path54.resolve(overrides.cwd ?? process.cwd(), parsed.cwd ?? ".");
|
|
95601
96337
|
const io = { ...defaultIo(parsed.json), ...overrides, json: parsed.json, cwd };
|
|
95602
96338
|
if (parsed.error)
|
|
95603
96339
|
return emit(io, fail("invalid_input", parsed.error));
|
|
@@ -95607,18 +96343,38 @@ async function main(argv, overrides = {}, options = {}) {
|
|
|
95607
96343
|
return emit(io, ok({ version: package_default.version }), (data) => data.version);
|
|
95608
96344
|
}
|
|
95609
96345
|
if (command === undefined || command === "help" || command === "--help" || command === "-h") {
|
|
95610
|
-
const topic = command === "help" ? args
|
|
96346
|
+
const [topic, sub] = command === "help" ? words2(args) : [];
|
|
95611
96347
|
if (topic) {
|
|
95612
96348
|
const entry = findVerb(topic);
|
|
95613
96349
|
if (!entry)
|
|
95614
96350
|
return unknown2(io, topic);
|
|
95615
|
-
|
|
96351
|
+
if (sub === undefined)
|
|
96352
|
+
return help(io, verbHelp(entry));
|
|
96353
|
+
const found = findSubcommand(entry, sub);
|
|
96354
|
+
if (!found)
|
|
96355
|
+
return emit(io, fail("invalid_input", `unknown ${topic} subcommand "${sub}"`, {
|
|
96356
|
+
unblock: `workit help ${topic}`
|
|
96357
|
+
}));
|
|
96358
|
+
return help(io, subcommandHelp(entry, found));
|
|
95616
96359
|
}
|
|
95617
96360
|
return emit(io, ok({ version: package_default.version, verbs: listed().map(describe3) }), () => helpText());
|
|
95618
96361
|
}
|
|
95619
96362
|
const entry = findVerb(command);
|
|
95620
96363
|
if (!entry)
|
|
95621
96364
|
return unknown2(io, command);
|
|
96365
|
+
if (wantsHelp(verbArgs)) {
|
|
96366
|
+
const word = firstWord(verbArgs);
|
|
96367
|
+
const sub = word === undefined ? undefined : findSubcommand(entry, word);
|
|
96368
|
+
const asValue = helpAsValue(verbArgs, sub ? [sub.usage] : usageLines(entry));
|
|
96369
|
+
if (asValue)
|
|
96370
|
+
return emit(io, fail("invalid_input", asValue, {
|
|
96371
|
+
unblock: `workit help ${entry.name}${sub ? ` ${sub.name}` : ""}`
|
|
96372
|
+
}));
|
|
96373
|
+
return help(io, sub ? subcommandHelp(entry, sub) : verbHelp(entry));
|
|
96374
|
+
}
|
|
96375
|
+
const ended = endOfOptions(io, entry, args);
|
|
96376
|
+
if (typeof ended === "number")
|
|
96377
|
+
return ended;
|
|
95622
96378
|
if (parsed.cwd !== null) {
|
|
95623
96379
|
try {
|
|
95624
96380
|
process.chdir(io.cwd);
|
|
@@ -95636,8 +96392,8 @@ async function main(argv, overrides = {}, options = {}) {
|
|
|
95636
96392
|
`);
|
|
95637
96393
|
const verb = await entry.load();
|
|
95638
96394
|
if (!io.json)
|
|
95639
|
-
return verb.run(
|
|
95640
|
-
return runJsonPure(io, command, (pure) => verb.run(
|
|
96395
|
+
return verb.run(ended, io);
|
|
96396
|
+
return runJsonPure(io, command, (pure) => verb.run(ended, pure));
|
|
95641
96397
|
}
|
|
95642
96398
|
var CODE_FOR_EXIT = {
|
|
95643
96399
|
1: "failed",
|
|
@@ -95700,10 +96456,32 @@ var withJsonFlag = (args) => {
|
|
|
95700
96456
|
return end < 0 ? [...args, "--json"] : [...args.slice(0, end), "--json", ...args.slice(end)];
|
|
95701
96457
|
};
|
|
95702
96458
|
var listed = () => VERBS.filter((entry) => !entry.planned);
|
|
96459
|
+
function endOfOptions(io, entry, args) {
|
|
96460
|
+
const end = args.indexOf("--");
|
|
96461
|
+
if (end < 0)
|
|
96462
|
+
return args;
|
|
96463
|
+
const word = firstWord(args);
|
|
96464
|
+
const sub = word === undefined ? undefined : findSubcommand(entry, word);
|
|
96465
|
+
const unblock = `workit help ${entry.name}${sub ? ` ${sub.name}` : ""}`;
|
|
96466
|
+
if (entry.subcommands?.length && !sub) {
|
|
96467
|
+
if (entry.optionalSubcommand || word !== undefined)
|
|
96468
|
+
return args;
|
|
96469
|
+
return emit(io, fail("invalid_input", `missing ${entry.name} subcommand`, { unblock }));
|
|
96470
|
+
}
|
|
96471
|
+
if (takesPositionals(sub ? [sub.usage] : [entry.usage]))
|
|
96472
|
+
return args;
|
|
96473
|
+
const extra = args.slice(end + 1);
|
|
96474
|
+
if (extra.length)
|
|
96475
|
+
return emit(io, fail("invalid_input", `${entry.name}${sub ? ` ${sub.name}` : ""} takes no positional arguments (got: ${extra.join(" ")})`, { unblock }));
|
|
96476
|
+
return args.slice(0, end);
|
|
96477
|
+
}
|
|
96478
|
+
var words2 = (args) => args.filter((arg) => !arg.startsWith("-"));
|
|
96479
|
+
var help = (io, doc) => emit(io, ok(doc), (data) => data.text);
|
|
95703
96480
|
var describe3 = (entry) => ({
|
|
95704
96481
|
name: entry.name,
|
|
95705
96482
|
group: entry.group,
|
|
95706
96483
|
usage: entry.usage,
|
|
96484
|
+
usages: usageLines(entry),
|
|
95707
96485
|
summary: entry.summary,
|
|
95708
96486
|
...entry.planned ? { planned: entry.planned } : {}
|
|
95709
96487
|
});
|