@brainervirus/workit-codex 7.0.0 → 7.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/.codex-plugin/plugin.json +1 -1
- package/dist/launch-mcp.js +496 -61
- package/dist/workit-hook.js +207 -27
- package/package.json +3 -3
package/dist/launch-mcp.js
CHANGED
|
@@ -6625,7 +6625,7 @@ import { existsSync as existsSync9, realpathSync as realpathSync7, statSync as s
|
|
|
6625
6625
|
import path21 from "node:path";
|
|
6626
6626
|
|
|
6627
6627
|
// packages/workit-core/src/core.ts
|
|
6628
|
-
import { spawnSync as
|
|
6628
|
+
import { spawnSync as spawnSync12 } from "node:child_process";
|
|
6629
6629
|
import { existsSync as existsSync7, realpathSync as realpathSync5 } from "node:fs";
|
|
6630
6630
|
import path19 from "node:path";
|
|
6631
6631
|
|
|
@@ -18884,6 +18884,11 @@ function worktreeSignal(cwd, options = {}) {
|
|
|
18884
18884
|
}
|
|
18885
18885
|
return `sig:${hash.digest("hex")}`;
|
|
18886
18886
|
}
|
|
18887
|
+
function mergeBase(cwd, a, b) {
|
|
18888
|
+
if (!safeArg(a) || !safeArg(b))
|
|
18889
|
+
return null;
|
|
18890
|
+
return line(git2(cwd, ["merge-base", a, b]));
|
|
18891
|
+
}
|
|
18887
18892
|
function patchId(cwd, base, head) {
|
|
18888
18893
|
if (!safeArg(base) || !safeArg(head))
|
|
18889
18894
|
return null;
|
|
@@ -18907,9 +18912,33 @@ function patchId(cwd, base, head) {
|
|
|
18907
18912
|
const id = git2(cwd, ["patch-id", "--stable"], { input: diff.stdout });
|
|
18908
18913
|
return line(id)?.split(/\s+/u)[0] ?? null;
|
|
18909
18914
|
}
|
|
18915
|
+
function remoteNames(cwd) {
|
|
18916
|
+
return (git2(cwd, ["remote"]).stdout ?? "").split(/\r?\n/u).map((value) => value.trim()).filter(Boolean);
|
|
18917
|
+
}
|
|
18918
|
+
function resolveRef(cwd, ref) {
|
|
18919
|
+
if (!safeArg(ref))
|
|
18920
|
+
return null;
|
|
18921
|
+
return line(git2(cwd, ["rev-parse", "--verify", "-q", `${ref}^{commit}`]));
|
|
18922
|
+
}
|
|
18923
|
+
var config2 = (cwd, key) => line(git2(cwd, ["config", "--get", key]));
|
|
18910
18924
|
function currentBranch(cwd) {
|
|
18911
18925
|
return line(git2(cwd, ["symbolic-ref", "--short", "-q", "HEAD"]));
|
|
18912
18926
|
}
|
|
18927
|
+
function pushRemoteName(cwd, branch) {
|
|
18928
|
+
const name = branch ?? currentBranch(cwd);
|
|
18929
|
+
const remotes = remoteNames(cwd);
|
|
18930
|
+
const candidates = [
|
|
18931
|
+
name ? config2(cwd, `branch.${name}.pushRemote`) : null,
|
|
18932
|
+
config2(cwd, "remote.pushDefault"),
|
|
18933
|
+
name ? config2(cwd, `branch.${name}.remote`) : null
|
|
18934
|
+
];
|
|
18935
|
+
for (const candidate of candidates)
|
|
18936
|
+
if (candidate && candidate !== "." && remotes.includes(candidate))
|
|
18937
|
+
return candidate;
|
|
18938
|
+
if (remotes.includes("origin"))
|
|
18939
|
+
return "origin";
|
|
18940
|
+
return remotes.length === 1 ? remotes[0] : null;
|
|
18941
|
+
}
|
|
18913
18942
|
|
|
18914
18943
|
// packages/workit-core/src/core/policy/derive.ts
|
|
18915
18944
|
import { existsSync as existsSync3 } from "node:fs";
|
|
@@ -20523,6 +20552,8 @@ var readConfig = () => {
|
|
|
20523
20552
|
throw new Error(result.error);
|
|
20524
20553
|
return result.config ?? DEFAULTS;
|
|
20525
20554
|
};
|
|
20555
|
+
var vcsConfigPath = () => process.env.WORKFLOW_VCS_CONFIG ?? path12.join(configDir(), "vcs.json");
|
|
20556
|
+
var branchGlobPattern = (glob) => new RegExp(`^${glob.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*")}$`, "i");
|
|
20526
20557
|
var resolveBranchPolicy = (config, workspace) => {
|
|
20527
20558
|
const wp = workspace?.branchPolicy ?? {};
|
|
20528
20559
|
const preset = Object.hasOwn(PRESETS, wp.preset) ? wp.preset : config.branchPolicy?.preset ?? "gitflow";
|
|
@@ -20530,7 +20561,7 @@ var resolveBranchPolicy = (config, workspace) => {
|
|
|
20530
20561
|
allowed: wp.allowed,
|
|
20531
20562
|
protectedNames: wp.protected
|
|
20532
20563
|
}, config);
|
|
20533
|
-
const allowed = merged.allowed.map(
|
|
20564
|
+
const allowed = merged.allowed.map(branchGlobPattern);
|
|
20534
20565
|
return {
|
|
20535
20566
|
preset,
|
|
20536
20567
|
allowed,
|
|
@@ -20547,16 +20578,6 @@ var COMMIT_PRESETS = [
|
|
|
20547
20578
|
"custom",
|
|
20548
20579
|
"auto"
|
|
20549
20580
|
];
|
|
20550
|
-
var resolveCommitPolicy = (config, workspace) => {
|
|
20551
|
-
const wp = workspace?.commitPolicy ?? {};
|
|
20552
|
-
if (COMMIT_PRESETS.includes(String(wp.preset ?? ""))) {
|
|
20553
|
-
return {
|
|
20554
|
-
preset: wp.preset,
|
|
20555
|
-
...typeof wp.pattern === "string" ? { pattern: wp.pattern } : {}
|
|
20556
|
-
};
|
|
20557
|
-
}
|
|
20558
|
-
return config.commitPolicy ?? { preset: "conventional" };
|
|
20559
|
-
};
|
|
20560
20581
|
|
|
20561
20582
|
// packages/workit-core/src/core/workspaces.ts
|
|
20562
20583
|
import { createHash as createHash8 } from "node:crypto";
|
|
@@ -20595,26 +20616,31 @@ var versionSourceSchema = discriminatedUnion("kind", [
|
|
|
20595
20616
|
object({ kind: literal("manual") }).strict()
|
|
20596
20617
|
]);
|
|
20597
20618
|
var releaseTrackSchema = object({
|
|
20598
|
-
strategy: branchPreset,
|
|
20619
|
+
strategy: branchPreset.optional(),
|
|
20599
20620
|
productionBranch: nonBlank,
|
|
20600
20621
|
integrationBranch: nonBlank,
|
|
20601
|
-
naming: object({
|
|
20602
|
-
|
|
20603
|
-
|
|
20604
|
-
|
|
20605
|
-
|
|
20606
|
-
|
|
20607
|
-
|
|
20608
|
-
|
|
20622
|
+
naming: object({
|
|
20623
|
+
feature: nonBlank.optional(),
|
|
20624
|
+
release: nonBlank.optional(),
|
|
20625
|
+
hotfix: nonBlank.optional()
|
|
20626
|
+
}).passthrough().optional(),
|
|
20627
|
+
baseBranch: nonBlank.optional(),
|
|
20628
|
+
mergeBackBranches: array(nonBlank).optional(),
|
|
20629
|
+
pullRequestTarget: nonBlank.optional(),
|
|
20630
|
+
tagNamespace: string2().optional(),
|
|
20631
|
+
versionSource: versionSourceSchema.optional(),
|
|
20632
|
+
requiredChecks: array(nonBlank).optional(),
|
|
20633
|
+
critical: array(nonBlank).optional()
|
|
20634
|
+
}).passthrough().superRefine((track, context) => {
|
|
20609
20635
|
for (const [field, values] of [
|
|
20610
|
-
["mergeBackBranches", track.mergeBackBranches],
|
|
20611
|
-
["requiredChecks", track.requiredChecks]
|
|
20636
|
+
["mergeBackBranches", track.mergeBackBranches ?? []],
|
|
20637
|
+
["requiredChecks", track.requiredChecks ?? []]
|
|
20612
20638
|
]) {
|
|
20613
20639
|
if (new Set(values).size !== values.length) {
|
|
20614
20640
|
context.addIssue({ code: "custom", path: [field], message: "entries must be unique" });
|
|
20615
20641
|
}
|
|
20616
20642
|
}
|
|
20617
|
-
if (track.versionSource
|
|
20643
|
+
if (track.versionSource?.kind === "package-json" && (path13.posix.isAbsolute(track.versionSource.path.replaceAll("\\", "/")) || /^[A-Za-z]:\//u.test(track.versionSource.path.replaceAll("\\", "/")) || track.versionSource.path.replaceAll("\\", "/").split("/").includes(".."))) {
|
|
20618
20644
|
context.addIssue({
|
|
20619
20645
|
code: "custom",
|
|
20620
20646
|
path: ["versionSource", "path"],
|
|
@@ -20882,7 +20908,7 @@ var resolveRuntimeWorkspaceVcs = (cwd) => resolveRuntimeWorkspaceCandidate(cwd,
|
|
|
20882
20908
|
var runtimeWorkspaceIndexSchema = object({
|
|
20883
20909
|
workspaces: array(object({ name: nonBlank, glob: nonBlank }).passthrough()).optional()
|
|
20884
20910
|
}).passthrough();
|
|
20885
|
-
var
|
|
20911
|
+
var matchRuntimeWorkspace = (cwd) => {
|
|
20886
20912
|
const file = path13.join(configDir(), "workspaces.json");
|
|
20887
20913
|
let raw;
|
|
20888
20914
|
try {
|
|
@@ -20917,8 +20943,17 @@ var resolveRuntimeWorkspaceCandidate = (cwd, kind) => {
|
|
|
20917
20943
|
});
|
|
20918
20944
|
const workspaceName = process.env.WORKFLOW_WORKSPACE_NAME?.trim() || undefined;
|
|
20919
20945
|
const selected = selectWorkspaceMatch(matches, cwd, workspaceName);
|
|
20920
|
-
|
|
20946
|
+
return selected ? { file, selected } : null;
|
|
20947
|
+
};
|
|
20948
|
+
var resolveRuntimeReleaseTracks = (cwd) => {
|
|
20949
|
+
const matched = matchRuntimeWorkspace(cwd);
|
|
20950
|
+
return matched ? { workspace: matched.selected.name, releaseTracks: matched.selected.releaseTracks } : null;
|
|
20951
|
+
};
|
|
20952
|
+
var resolveRuntimeWorkspaceCandidate = (cwd, kind) => {
|
|
20953
|
+
const matched = matchRuntimeWorkspace(cwd);
|
|
20954
|
+
if (!matched)
|
|
20921
20955
|
return null;
|
|
20956
|
+
const { file, selected } = matched;
|
|
20922
20957
|
const policy = runtimeWorkspacePolicySchema(kind).safeParse(selected);
|
|
20923
20958
|
if (!policy.success) {
|
|
20924
20959
|
const detail = policy.error.issues.map((issue) => `${issue.path.map(String).join(".") || "workspace"}: ${issue.message}`).join("; ");
|
|
@@ -20944,15 +20979,410 @@ var resolveRuntimeWorkspacePolicy = (cwd, kind, requestedProfile) => {
|
|
|
20944
20979
|
source: profilePolicy ? `profile:${profileName}` : workspacePolicy ? `workspace:${candidate.name}` : "user-default"
|
|
20945
20980
|
};
|
|
20946
20981
|
};
|
|
20982
|
+
function workspaceDefaultTarget(cwd, globalDefault) {
|
|
20983
|
+
const ws = resolveRuntimeWorkspaceVcs(cwd);
|
|
20984
|
+
const wp = ws?.branchPolicy ?? {};
|
|
20985
|
+
const hasWorkspacePolicy = typeof wp.preset === "string" && Object.hasOwn(PRESETS, wp.preset);
|
|
20986
|
+
const selected = resolveRuntimeWorkspacePolicy(cwd, "branch", process.env.WORKFLOW_PROFILE?.trim() || undefined);
|
|
20987
|
+
const policyDefault = resolveBranchPolicy(readConfig(), selected.policy ? { branchPolicy: selected.policy } : null).defaultTargetBranch;
|
|
20988
|
+
return String(ws?.vcs?.defaultTargetBranch ?? (hasWorkspacePolicy ? policyDefault : globalDefault ?? policyDefault) ?? "develop");
|
|
20989
|
+
}
|
|
20947
20990
|
|
|
20948
20991
|
// packages/workit-core/src/core/vcs-config.ts
|
|
20949
20992
|
import fs12 from "node:fs";
|
|
20950
20993
|
import path14 from "node:path";
|
|
20994
|
+
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
20995
|
+
|
|
20996
|
+
// packages/workit-core/src/core/release-tracks.ts
|
|
20997
|
+
import { createHash as createHash9 } from "node:crypto";
|
|
20951
20998
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
20952
|
-
var
|
|
20999
|
+
var KNOWN_FIELDS = new Set([
|
|
21000
|
+
"strategy",
|
|
21001
|
+
"productionBranch",
|
|
21002
|
+
"integrationBranch",
|
|
21003
|
+
"naming",
|
|
21004
|
+
"baseBranch",
|
|
21005
|
+
"mergeBackBranches",
|
|
21006
|
+
"pullRequestTarget",
|
|
21007
|
+
"tagNamespace",
|
|
21008
|
+
"versionSource",
|
|
21009
|
+
"requiredChecks",
|
|
21010
|
+
"critical"
|
|
21011
|
+
]);
|
|
21012
|
+
var BRANCH_FIELDS = ["productionBranch", "integrationBranch", "baseBranch", "pullRequestTarget"];
|
|
21013
|
+
var PLACEHOLDER = /\{[^}]*\}/gu;
|
|
21014
|
+
var isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
21015
|
+
var branchName = (value) => typeof value === "string" && value.trim() && !value.trim().startsWith("-") ? value.trim() : null;
|
|
21016
|
+
var namedBranches = (entry) => [
|
|
21017
|
+
...BRANCH_FIELDS.map((field) => branchName(entry[field])),
|
|
21018
|
+
...Array.isArray(entry.mergeBackBranches) ? entry.mergeBackBranches.map(branchName) : []
|
|
21019
|
+
].filter((name) => name !== null);
|
|
21020
|
+
var literalOf = (template) => template.replace(PLACEHOLDER, "").replace(/[*/]/gu, "").trim();
|
|
21021
|
+
function readReleaseTracks(raw) {
|
|
21022
|
+
const out = { tracks: [], issues: [], error: null, protectedBranches: [] };
|
|
21023
|
+
if (raw === undefined || raw === null)
|
|
21024
|
+
return out;
|
|
21025
|
+
if (!isRecord3(raw)) {
|
|
21026
|
+
out.issues.push("releaseTracks is not an object; ignored");
|
|
21027
|
+
return out;
|
|
21028
|
+
}
|
|
21029
|
+
const fatal = [];
|
|
21030
|
+
const protectedNames = new Set;
|
|
21031
|
+
for (const [name, entry] of Object.entries(raw).toSorted(([a], [b]) => a < b ? -1 : 1)) {
|
|
21032
|
+
const label = `release track ${JSON.stringify(name)}`;
|
|
21033
|
+
if (!isRecord3(entry)) {
|
|
21034
|
+
out.issues.push(`${label} is not an object; ignored`);
|
|
21035
|
+
continue;
|
|
21036
|
+
}
|
|
21037
|
+
for (const branch of namedBranches(entry))
|
|
21038
|
+
protectedNames.add(branch);
|
|
21039
|
+
if (!name.trim()) {
|
|
21040
|
+
out.issues.push("a release track with a blank name was ignored");
|
|
21041
|
+
continue;
|
|
21042
|
+
}
|
|
21043
|
+
let critical = [];
|
|
21044
|
+
if (Array.isArray(entry.critical))
|
|
21045
|
+
critical = entry.critical.filter((item) => typeof item === "string");
|
|
21046
|
+
else if (entry.critical !== undefined)
|
|
21047
|
+
out.issues.push(`${label} critical: must be a list of field names; ignored`);
|
|
21048
|
+
const isCritical = (field) => critical.some((item) => field === item || field.startsWith(`${item}.`));
|
|
21049
|
+
const problem = (field, message) => {
|
|
21050
|
+
if (isCritical(field))
|
|
21051
|
+
fatal.push(`${label} ${field}: ${message}`);
|
|
21052
|
+
else
|
|
21053
|
+
out.issues.push(`${label} ${field}: ${message}`);
|
|
21054
|
+
};
|
|
21055
|
+
for (const key of Object.keys(entry))
|
|
21056
|
+
if (!KNOWN_FIELDS.has(key))
|
|
21057
|
+
problem(key, "unknown field, ignored");
|
|
21058
|
+
const productionBranch = branchName(entry.productionBranch);
|
|
21059
|
+
const integrationBranch = branchName(entry.integrationBranch);
|
|
21060
|
+
if (!productionBranch)
|
|
21061
|
+
problem("productionBranch", "missing or not a branch name");
|
|
21062
|
+
if (!integrationBranch)
|
|
21063
|
+
problem("integrationBranch", "missing or not a branch name");
|
|
21064
|
+
const optionalBranch = (field) => {
|
|
21065
|
+
if (entry[field] === undefined)
|
|
21066
|
+
return null;
|
|
21067
|
+
const value = branchName(entry[field]);
|
|
21068
|
+
if (!value)
|
|
21069
|
+
problem(field, "not a branch name; using the integration branch");
|
|
21070
|
+
return value;
|
|
21071
|
+
};
|
|
21072
|
+
const baseBranch = optionalBranch("baseBranch");
|
|
21073
|
+
const pullRequestTarget = optionalBranch("pullRequestTarget");
|
|
21074
|
+
let mergeBackBranches = [];
|
|
21075
|
+
if (entry.mergeBackBranches !== undefined) {
|
|
21076
|
+
const list = Array.isArray(entry.mergeBackBranches) ? entry.mergeBackBranches.map(branchName) : [null];
|
|
21077
|
+
if (list.some((item) => item === null))
|
|
21078
|
+
problem("mergeBackBranches", "must be a list of branch names; ignored");
|
|
21079
|
+
else
|
|
21080
|
+
mergeBackBranches = [...new Set(list)];
|
|
21081
|
+
}
|
|
21082
|
+
const naming = {};
|
|
21083
|
+
if (entry.naming !== undefined) {
|
|
21084
|
+
if (!isRecord3(entry.naming))
|
|
21085
|
+
problem("naming", "not an object; ignored");
|
|
21086
|
+
else
|
|
21087
|
+
for (const kind of ["feature", "release", "hotfix"]) {
|
|
21088
|
+
const template = entry.naming[kind];
|
|
21089
|
+
if (template === undefined)
|
|
21090
|
+
continue;
|
|
21091
|
+
if (typeof template !== "string" || !template.trim())
|
|
21092
|
+
problem(`naming.${kind}`, "not a template string; ignored");
|
|
21093
|
+
else if (!literalOf(template))
|
|
21094
|
+
problem(`naming.${kind}`, "needs literal text besides placeholders; ignored");
|
|
21095
|
+
else
|
|
21096
|
+
naming[kind] = template.trim();
|
|
21097
|
+
}
|
|
21098
|
+
}
|
|
21099
|
+
if (!productionBranch || !integrationBranch) {
|
|
21100
|
+
out.issues.push(`${label} was skipped: it needs a productionBranch and integrationBranch`);
|
|
21101
|
+
continue;
|
|
21102
|
+
}
|
|
21103
|
+
out.tracks.push({
|
|
21104
|
+
name,
|
|
21105
|
+
productionBranch,
|
|
21106
|
+
integrationBranch,
|
|
21107
|
+
baseBranch: baseBranch ?? integrationBranch,
|
|
21108
|
+
pullRequestTarget: pullRequestTarget ?? integrationBranch,
|
|
21109
|
+
mergeBackBranches,
|
|
21110
|
+
naming
|
|
21111
|
+
});
|
|
21112
|
+
}
|
|
21113
|
+
out.protectedBranches = [...protectedNames];
|
|
21114
|
+
if (fatal.length)
|
|
21115
|
+
out.error = `workspace releaseTracks cannot be read by this Workit (${fatal.join("; ")}); upgrade Workit or fix the track`;
|
|
21116
|
+
return out;
|
|
21117
|
+
}
|
|
21118
|
+
var IMPLICIT = "";
|
|
21119
|
+
var ownedBy = (tracks, branch) => tracks.filter((track) => [track.integrationBranch, track.productionBranch, track.baseBranch].includes(branch));
|
|
21120
|
+
var shortRef = (ref, remotes) => {
|
|
21121
|
+
const bare = ref.replace(/^refs\/heads\//u, "").replace(/^refs\/remotes\/[^/]+\//u, "");
|
|
21122
|
+
const remote = remotes.find((name) => bare.startsWith(`${name}/`));
|
|
21123
|
+
return remote ? bare.slice(remote.length + 1) : bare;
|
|
21124
|
+
};
|
|
21125
|
+
var MAX_RECORDED_HOPS = 10;
|
|
21126
|
+
function resolveReleaseTrack(input) {
|
|
21127
|
+
const tracks = [...input.tracks];
|
|
21128
|
+
const issues = [...input.issues ?? []];
|
|
21129
|
+
const requested = input.requested?.trim();
|
|
21130
|
+
if (tracks.length === 0) {
|
|
21131
|
+
if (requested)
|
|
21132
|
+
return {
|
|
21133
|
+
status: "invalid",
|
|
21134
|
+
error: `no release tracks configured for this workspace; --track ${requested} cannot apply`,
|
|
21135
|
+
issues
|
|
21136
|
+
};
|
|
21137
|
+
return { status: "none", issues };
|
|
21138
|
+
}
|
|
21139
|
+
const names = tracks.map((track) => track.name).join(", ");
|
|
21140
|
+
let envProblem = null;
|
|
21141
|
+
const done = (track, source, detail, warnings = [], ambiguous = null) => ({
|
|
21142
|
+
status: "resolved",
|
|
21143
|
+
track: track && track.name !== IMPLICIT ? track : null,
|
|
21144
|
+
source,
|
|
21145
|
+
detail,
|
|
21146
|
+
warnings: [...issues, ...envProblem ? [envProblem] : [], ...warnings],
|
|
21147
|
+
tracks,
|
|
21148
|
+
blocking: envProblem ?? ambiguous
|
|
21149
|
+
});
|
|
21150
|
+
if (requested) {
|
|
21151
|
+
const named = tracks.find((track) => track.name === requested);
|
|
21152
|
+
if (!named)
|
|
21153
|
+
return {
|
|
21154
|
+
status: "invalid",
|
|
21155
|
+
error: `no release track ${JSON.stringify(requested)}; configured: ${names}`,
|
|
21156
|
+
issues
|
|
21157
|
+
};
|
|
21158
|
+
return done(named, "flag", `track ${named.name} was requested explicitly`);
|
|
21159
|
+
}
|
|
21160
|
+
const owned = (branch) => branch !== null && tracks.some((track) => [
|
|
21161
|
+
track.integrationBranch,
|
|
21162
|
+
track.productionBranch,
|
|
21163
|
+
track.baseBranch,
|
|
21164
|
+
track.pullRequestTarget
|
|
21165
|
+
].includes(branch));
|
|
21166
|
+
const implicit = input.defaultBranch && !owned(input.defaultBranch) ? {
|
|
21167
|
+
name: IMPLICIT,
|
|
21168
|
+
productionBranch: input.defaultBranch,
|
|
21169
|
+
integrationBranch: input.defaultBranch,
|
|
21170
|
+
baseBranch: input.defaultBranch,
|
|
21171
|
+
pullRequestTarget: input.defaultBranch,
|
|
21172
|
+
mergeBackBranches: [],
|
|
21173
|
+
naming: {}
|
|
21174
|
+
} : null;
|
|
21175
|
+
const candidates = implicit ? [...tracks, implicit] : tracks;
|
|
21176
|
+
const label = (track) => track.name === IMPLICIT ? `the workspace default line (${track.integrationBranch})` : `track ${track.name}`;
|
|
21177
|
+
const fallback = (why) => {
|
|
21178
|
+
const byDefault = input.defaultBranch ? tracks.filter((track) => track.integrationBranch === input.defaultBranch || track.pullRequestTarget === input.defaultBranch) : [];
|
|
21179
|
+
const track = byDefault.length === 1 ? byDefault[0] : null;
|
|
21180
|
+
const target = track ? `track ${track.name}` : `default target ${input.defaultBranch ?? "(none)"}`;
|
|
21181
|
+
const ambiguous = candidates.length >= 2 ? `can't tell which release line ${input.branch ?? "HEAD"} is on (${why}); pass --track <name> (${names}) or --base <branch>` : null;
|
|
21182
|
+
return done(track, "default", `${why}; using the workspace ${target}`, [
|
|
21183
|
+
`release track not determined: ${why}; using the workspace ${target} (pass --track <name> to choose)`
|
|
21184
|
+
], ambiguous);
|
|
21185
|
+
};
|
|
21186
|
+
const branch = input.branch;
|
|
21187
|
+
if (branch) {
|
|
21188
|
+
const owners = ownedBy(candidates, branch);
|
|
21189
|
+
if (owners.length === 1)
|
|
21190
|
+
return done(owners[0], "branch", `${branch} is a branch of ${label(owners[0])}`);
|
|
21191
|
+
if (owners.length > 1)
|
|
21192
|
+
return fallback(`${branch} belongs to more than one track (${owners.map((track) => track.name).join(", ")})`);
|
|
21193
|
+
}
|
|
21194
|
+
const env = input.envRequested?.trim();
|
|
21195
|
+
if (env) {
|
|
21196
|
+
const named = tracks.find((track) => track.name === env);
|
|
21197
|
+
if (named)
|
|
21198
|
+
return done(named, "env", `WORKFLOW_RELEASE_TRACK selects track ${named.name}`);
|
|
21199
|
+
envProblem = `WORKFLOW_RELEASE_TRACK=${env} names no release track of this workspace (${names}); ignored`;
|
|
21200
|
+
}
|
|
21201
|
+
if (!branch)
|
|
21202
|
+
return fallback("HEAD is detached");
|
|
21203
|
+
if (tracks.length === 1 && !implicit)
|
|
21204
|
+
return done(tracks[0], "only-track", `${tracks[0].name} is the only track`);
|
|
21205
|
+
let remotes = null;
|
|
21206
|
+
const short = (ref) => shortRef(ref, remotes ??= input.probe.remotes());
|
|
21207
|
+
const ownerOf = (ref) => {
|
|
21208
|
+
const owner = ownedBy(candidates, short(ref));
|
|
21209
|
+
return owner.length === 1 ? owner[0] : null;
|
|
21210
|
+
};
|
|
21211
|
+
const followRecorded = (start) => {
|
|
21212
|
+
let cursor = start;
|
|
21213
|
+
const seen = new Set([start]);
|
|
21214
|
+
for (let hop = 0;hop < MAX_RECORDED_HOPS; hop += 1) {
|
|
21215
|
+
const recorded = input.probe.recordedBase(cursor);
|
|
21216
|
+
if (!recorded)
|
|
21217
|
+
return null;
|
|
21218
|
+
const base = short(recorded);
|
|
21219
|
+
const owner = ownerOf(base);
|
|
21220
|
+
if (owner)
|
|
21221
|
+
return owner;
|
|
21222
|
+
if (ownedBy(candidates, base).length > 1 || seen.has(base))
|
|
21223
|
+
return null;
|
|
21224
|
+
seen.add(base);
|
|
21225
|
+
cursor = base;
|
|
21226
|
+
}
|
|
21227
|
+
return null;
|
|
21228
|
+
};
|
|
21229
|
+
const recordedOwner = followRecorded(branch);
|
|
21230
|
+
if (recordedOwner)
|
|
21231
|
+
return done(recordedOwner, "recorded-base", `${branch} was created on ${label(recordedOwner)}'s line (recorded base)`);
|
|
21232
|
+
for (const source of ["reflog", "checkout"]) {
|
|
21233
|
+
const ref = source === "reflog" ? input.probe.createdFrom(branch) : input.probe.checkedOutFrom(branch);
|
|
21234
|
+
if (!ref)
|
|
21235
|
+
continue;
|
|
21236
|
+
const owner = ownerOf(ref) ?? followRecorded(short(ref));
|
|
21237
|
+
if (owner)
|
|
21238
|
+
return done(owner, source, `${branch} was created from ${short(ref)} (${source === "reflog" ? "branch reflog" : "HEAD reflog"})`);
|
|
21239
|
+
}
|
|
21240
|
+
const forks = [];
|
|
21241
|
+
for (const track of candidates)
|
|
21242
|
+
for (const ref of new Set([track.integrationBranch, track.baseBranch])) {
|
|
21243
|
+
const sha = input.probe.mergeBase(branch, ref);
|
|
21244
|
+
if (sha)
|
|
21245
|
+
forks.push({ track, ref, sha });
|
|
21246
|
+
}
|
|
21247
|
+
if (forks.length === 0)
|
|
21248
|
+
return fallback(`no track branch could be compared with ${branch} (fetch the track branches)`);
|
|
21249
|
+
const ancestry = new Map;
|
|
21250
|
+
const descends = (older, newer) => {
|
|
21251
|
+
if (older === newer)
|
|
21252
|
+
return false;
|
|
21253
|
+
const key = `${older}>${newer}`;
|
|
21254
|
+
if (!ancestry.has(key))
|
|
21255
|
+
ancestry.set(key, input.probe.isAncestor(older, newer));
|
|
21256
|
+
return ancestry.get(key);
|
|
21257
|
+
};
|
|
21258
|
+
const winners = forks.filter((fork) => forks.every((other) => other.track === fork.track || descends(other.sha, fork.sha)));
|
|
21259
|
+
const winningTracks = [...new Set(winners.map((fork) => fork.track))];
|
|
21260
|
+
if (winningTracks.length === 1 && forks.some((fork) => fork.track !== winningTracks[0])) {
|
|
21261
|
+
const win = winners[0];
|
|
21262
|
+
return done(win.track, "ancestry", `${branch} forked from ${win.ref} at ${win.sha.slice(0, 12)}, after every other line's fork point`);
|
|
21263
|
+
}
|
|
21264
|
+
if (winningTracks.length === 1)
|
|
21265
|
+
return fallback(`only ${label(winningTracks[0])} could be compared with ${branch}`);
|
|
21266
|
+
const newest = forks.filter((fork) => !forks.some((other) => descends(fork.sha, other.sha)));
|
|
21267
|
+
return fallback(`${branch} has the same or unrelated fork points with ${[...new Set(newest.map((fork) => `${fork.ref} (${fork.track.name === IMPLICIT ? "workspace default" : fork.track.name})`))].join(" and ")}`);
|
|
21268
|
+
}
|
|
21269
|
+
var git4 = (cwd, args) => {
|
|
21270
|
+
const run = spawnSync7("git", args, {
|
|
21271
|
+
cwd,
|
|
21272
|
+
encoding: "utf8",
|
|
21273
|
+
timeout: 20000,
|
|
21274
|
+
windowsHide: true,
|
|
21275
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
21276
|
+
});
|
|
21277
|
+
return run.status === 0 ? (run.stdout ?? "").trim() : null;
|
|
21278
|
+
};
|
|
21279
|
+
var recordedBaseKey = (branch) => `branch.${branch}.workitBase`;
|
|
21280
|
+
var escapeRegExp = (text) => text.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
|
|
21281
|
+
var reflog = (cwd, ref) => (git4(cwd, ["log", "-g", "--date=unix", "--format=%H%x09%gd%x09%gs", ref, "--"]) ?? "").split(`
|
|
21282
|
+
`).map((line) => {
|
|
21283
|
+
const [sha = "", selector = "", ...subject] = line.split("\t");
|
|
21284
|
+
return {
|
|
21285
|
+
sha,
|
|
21286
|
+
time: Number(/@\{(\d+)\}$/u.exec(selector)?.[1] ?? Number.NaN),
|
|
21287
|
+
subject: subject.join("\t")
|
|
21288
|
+
};
|
|
21289
|
+
}).filter((entry) => entry.sha && Number.isFinite(entry.time));
|
|
21290
|
+
function gitTrackProbe(cwd) {
|
|
21291
|
+
let remote;
|
|
21292
|
+
let remotes;
|
|
21293
|
+
const tip = (branch) => {
|
|
21294
|
+
remote ??= pushRemoteName(cwd) ?? "origin";
|
|
21295
|
+
return resolveRef(cwd, `refs/remotes/${remote}/${branch}`) ?? resolveRef(cwd, `refs/heads/${branch}`);
|
|
21296
|
+
};
|
|
21297
|
+
return {
|
|
21298
|
+
remotes: () => remotes ??= remoteNames(cwd),
|
|
21299
|
+
recordedBase: (branch) => git4(cwd, ["config", "--get", recordedBaseKey(branch)]) || null,
|
|
21300
|
+
createdFrom: (branch) => {
|
|
21301
|
+
const log = git4(cwd, ["reflog", "show", "--format=%gs", `refs/heads/${branch}`, "--"]);
|
|
21302
|
+
const oldest = log?.split(`
|
|
21303
|
+
`).findLast(Boolean) ?? "";
|
|
21304
|
+
const match = /^branch: Created from (\S+)$/u.exec(oldest);
|
|
21305
|
+
return match && match[1] !== "HEAD" ? match[1] : null;
|
|
21306
|
+
},
|
|
21307
|
+
checkedOutFrom: (branch) => {
|
|
21308
|
+
const own = reflog(cwd, `refs/heads/${branch}`);
|
|
21309
|
+
const created = own.at(-1);
|
|
21310
|
+
if (!created || created.subject !== "branch: Created from HEAD")
|
|
21311
|
+
return null;
|
|
21312
|
+
const pattern = new RegExp(`^checkout: moving from (\\S+) to ${escapeRegExp(branch)}$`, "u");
|
|
21313
|
+
const entry = reflog(cwd, "HEAD").findLast((item) => item.time >= created.time && item.sha === created.sha && pattern.test(item.subject));
|
|
21314
|
+
return entry ? pattern.exec(entry.subject)?.[1] ?? null : null;
|
|
21315
|
+
},
|
|
21316
|
+
mergeBase: (branch, trackBranch) => {
|
|
21317
|
+
const base = tip(trackBranch);
|
|
21318
|
+
return base && resolveRef(cwd, `refs/heads/${branch}`) ? mergeBase(cwd, base, `refs/heads/${branch}`) : null;
|
|
21319
|
+
},
|
|
21320
|
+
isAncestor: (ancestor, descendant) => git4(cwd, ["merge-base", "--is-ancestor", ancestor, descendant]) !== null
|
|
21321
|
+
};
|
|
21322
|
+
}
|
|
21323
|
+
function workspaceReleaseTracks(cwd) {
|
|
21324
|
+
const raw = resolveRuntimeReleaseTracks(cwd);
|
|
21325
|
+
return { workspace: raw?.workspace ?? null, ...readReleaseTracks(raw?.releaseTracks) };
|
|
21326
|
+
}
|
|
21327
|
+
var memo3 = new Map;
|
|
21328
|
+
var MEMO_LIMIT = 64;
|
|
21329
|
+
function resolveTrackFor(cwd, options) {
|
|
21330
|
+
const read = workspaceReleaseTracks(cwd);
|
|
21331
|
+
if (read.error)
|
|
21332
|
+
return { status: "invalid", error: read.error, issues: read.issues };
|
|
21333
|
+
if (read.tracks.length === 0 && !options.track?.trim())
|
|
21334
|
+
return { status: "none", issues: read.issues };
|
|
21335
|
+
const branch = options.branch === undefined ? currentBranch(cwd) : options.branch;
|
|
21336
|
+
const envRequested = process.env.WORKFLOW_RELEASE_TRACK?.trim() || null;
|
|
21337
|
+
const input = {
|
|
21338
|
+
tracks: read.tracks,
|
|
21339
|
+
requested: options.track ?? null,
|
|
21340
|
+
envRequested,
|
|
21341
|
+
branch,
|
|
21342
|
+
defaultBranch: options.defaultBranch,
|
|
21343
|
+
issues: read.issues
|
|
21344
|
+
};
|
|
21345
|
+
let key = null;
|
|
21346
|
+
if (!options.probe) {
|
|
21347
|
+
const refs = git4(cwd, [
|
|
21348
|
+
"for-each-ref",
|
|
21349
|
+
"--format=%(refname) %(objectname)",
|
|
21350
|
+
"refs/heads",
|
|
21351
|
+
"refs/remotes"
|
|
21352
|
+
]) ?? "";
|
|
21353
|
+
const head = git4(cwd, ["reflog", "show", "-n", "1", "--format=%H %gs", "HEAD", "--"]) ?? "";
|
|
21354
|
+
const own = branch ? [
|
|
21355
|
+
git4(cwd, [
|
|
21356
|
+
"log",
|
|
21357
|
+
"-g",
|
|
21358
|
+
"-n",
|
|
21359
|
+
"1",
|
|
21360
|
+
"--date=unix",
|
|
21361
|
+
"--format=%H %gd %gs",
|
|
21362
|
+
`refs/heads/${branch}`,
|
|
21363
|
+
"--"
|
|
21364
|
+
]) ?? "",
|
|
21365
|
+
git4(cwd, ["config", "--get", recordedBaseKey(branch)]) ?? ""
|
|
21366
|
+
] : [];
|
|
21367
|
+
key = createHash9("sha256").update(JSON.stringify({ cwd, input, refs, head, own })).digest("hex");
|
|
21368
|
+
const hit = memo3.get(key);
|
|
21369
|
+
if (hit)
|
|
21370
|
+
return hit;
|
|
21371
|
+
}
|
|
21372
|
+
const resolution = resolveReleaseTrack({ ...input, probe: options.probe ?? gitTrackProbe(cwd) });
|
|
21373
|
+
if (key) {
|
|
21374
|
+
if (memo3.size >= MEMO_LIMIT)
|
|
21375
|
+
memo3.delete(memo3.keys().next().value);
|
|
21376
|
+
memo3.set(key, resolution);
|
|
21377
|
+
}
|
|
21378
|
+
return resolution;
|
|
21379
|
+
}
|
|
21380
|
+
|
|
21381
|
+
// packages/workit-core/src/core/vcs-config.ts
|
|
21382
|
+
var workspacesPath = () => path14.join(configDir(), "workspaces.json");
|
|
20953
21383
|
var vcsCwd = (cwd) => cwd ?? process.env.WORKFLOW_WORKSPACE_ROOT ?? process.cwd();
|
|
20954
21384
|
var remoteProvider = (cwd) => {
|
|
20955
|
-
const r =
|
|
21385
|
+
const r = spawnSync8("git", ["remote", "get-url", "origin"], { cwd, encoding: "utf8" });
|
|
20956
21386
|
if (r.status !== 0)
|
|
20957
21387
|
return null;
|
|
20958
21388
|
const url = (r.stdout ?? "").trim();
|
|
@@ -20989,7 +21419,7 @@ var remoteEndpoint = (remote) => {
|
|
|
20989
21419
|
var configuredSshEndpoint = (host) => {
|
|
20990
21420
|
if (host.startsWith("-"))
|
|
20991
21421
|
return null;
|
|
20992
|
-
const resolved =
|
|
21422
|
+
const resolved = spawnSync8("ssh", ["-G", host], {
|
|
20993
21423
|
encoding: "utf8",
|
|
20994
21424
|
timeout: 5000,
|
|
20995
21425
|
maxBuffer: 1024 * 1024,
|
|
@@ -21054,7 +21484,16 @@ var readVcsConfig = () => {
|
|
|
21054
21484
|
}
|
|
21055
21485
|
return { status: "malformed", path: file, config: {}, error: `${file} is not a JSON object` };
|
|
21056
21486
|
};
|
|
21057
|
-
|
|
21487
|
+
var trackSummary = (resolution) => resolution.status === "resolved" ? {
|
|
21488
|
+
name: resolution.track?.name ?? null,
|
|
21489
|
+
source: resolution.source,
|
|
21490
|
+
detail: resolution.detail,
|
|
21491
|
+
warnings: resolution.warnings,
|
|
21492
|
+
track: resolution.track,
|
|
21493
|
+
tracks: resolution.tracks,
|
|
21494
|
+
blocking: resolution.blocking
|
|
21495
|
+
} : null;
|
|
21496
|
+
function vcsConfig(mode, cwd, options = {}) {
|
|
21058
21497
|
const ws = resolveRuntimeWorkspaceVcs(vcsCwd(cwd));
|
|
21059
21498
|
const wsVcs = ws?.vcs ?? {};
|
|
21060
21499
|
const wsYt = ws?.youtrack ?? {};
|
|
@@ -21064,10 +21503,7 @@ function vcsConfig(mode, cwd) {
|
|
|
21064
21503
|
const determinateRoot = cwd !== undefined || process.env.WORKFLOW_WORKSPACE_ROOT !== undefined;
|
|
21065
21504
|
const rawProvider = wsVcs.provider ?? (determinateRoot ? remoteProvider(root) : null) ?? cfg.provider ?? null;
|
|
21066
21505
|
const provider = rawProvider === null || rawProvider === undefined ? null : String(rawProvider).toLowerCase() || null;
|
|
21067
|
-
const
|
|
21068
|
-
const hasWorkspacePolicy = typeof wp.preset === "string" && Object.hasOwn(PRESETS, wp.preset);
|
|
21069
|
-
const policyDefault = resolveBranchPolicyFor(root).defaultTargetBranch;
|
|
21070
|
-
const defaultTarget = String(wsVcs.defaultTargetBranch ?? (hasWorkspacePolicy ? policyDefault : cfg.defaultTargetBranch ?? policyDefault) ?? "develop");
|
|
21506
|
+
const workspaceDefault = workspaceDefaultTarget(root, cfg.defaultTargetBranch);
|
|
21071
21507
|
const linkIssues = typeof wsYt.link_issues === "boolean" ? wsYt.link_issues : null;
|
|
21072
21508
|
const youtrackBaseUrl = typeof wsYt.baseUrl === "string" ? wsYt.baseUrl : null;
|
|
21073
21509
|
let issuesProvider = null;
|
|
@@ -21079,11 +21515,24 @@ function vcsConfig(mode, cwd) {
|
|
|
21079
21515
|
if (mode === "resolve") {
|
|
21080
21516
|
if (cfgStatus === "malformed")
|
|
21081
21517
|
return { ok: false, error: cfgError, configPath: cfgPath };
|
|
21518
|
+
const trackResolution = resolveTrackFor(root, {
|
|
21519
|
+
track: options.track,
|
|
21520
|
+
...options.branch !== undefined ? { branch: options.branch } : {},
|
|
21521
|
+
defaultBranch: workspaceDefault
|
|
21522
|
+
});
|
|
21523
|
+
if (trackResolution.status === "invalid")
|
|
21524
|
+
return { ok: false, error: trackResolution.error, configPath: workspacesPath() };
|
|
21525
|
+
const releaseTrack = trackSummary(trackResolution);
|
|
21526
|
+
const defaultTarget = releaseTrack?.track?.pullRequestTarget ?? workspaceDefault;
|
|
21527
|
+
const baseBranch = releaseTrack?.track?.baseBranch ?? defaultTarget;
|
|
21082
21528
|
return {
|
|
21083
21529
|
ok: true,
|
|
21084
21530
|
workspace_name: ws?.name ?? null,
|
|
21085
21531
|
provider,
|
|
21086
21532
|
defaultTargetBranch: defaultTarget,
|
|
21533
|
+
workspaceDefaultTargetBranch: workspaceDefault,
|
|
21534
|
+
baseBranch,
|
|
21535
|
+
releaseTrack,
|
|
21087
21536
|
link_issues: linkIssues,
|
|
21088
21537
|
youtrack_base_url: youtrackBaseUrl,
|
|
21089
21538
|
issues_provider: issuesProvider,
|
|
@@ -21107,7 +21556,7 @@ function vcsConfig(mode, cwd) {
|
|
|
21107
21556
|
ok: true,
|
|
21108
21557
|
configPath: path14.resolve(cfgPath),
|
|
21109
21558
|
provider,
|
|
21110
|
-
defaultTargetBranch:
|
|
21559
|
+
defaultTargetBranch: workspaceDefault,
|
|
21111
21560
|
pr: cfg.pr ?? {},
|
|
21112
21561
|
workspace_name: ws?.name ?? null,
|
|
21113
21562
|
link_issues: linkIssues,
|
|
@@ -21143,7 +21592,7 @@ function mergedPrStyle(limit = 6, cwd) {
|
|
|
21143
21592
|
`).filter((l) => l.startsWith("## ")).map((l) => l.trim()),
|
|
21144
21593
|
descriptionPreview: desc.slice(0, 600)
|
|
21145
21594
|
});
|
|
21146
|
-
const remoteResult =
|
|
21595
|
+
const remoteResult = spawnSync8("git", ["remote", "get-url", "--push", "--all", "origin"], {
|
|
21147
21596
|
cwd,
|
|
21148
21597
|
encoding: "utf8"
|
|
21149
21598
|
});
|
|
@@ -21159,7 +21608,7 @@ function mergedPrStyle(limit = 6, cwd) {
|
|
|
21159
21608
|
if (!hostingApiHostMatches(remote, host))
|
|
21160
21609
|
return { ok: false, error: "PR style target does not match the provider host" };
|
|
21161
21610
|
if (provider === "gitlab") {
|
|
21162
|
-
const run = (args) =>
|
|
21611
|
+
const run = (args) => spawnSync8("glab", ["api", ...args], {
|
|
21163
21612
|
cwd,
|
|
21164
21613
|
encoding: "utf8",
|
|
21165
21614
|
env
|
|
@@ -21179,7 +21628,7 @@ function mergedPrStyle(limit = 6, cwd) {
|
|
|
21179
21628
|
});
|
|
21180
21629
|
}
|
|
21181
21630
|
} else if (provider === "github") {
|
|
21182
|
-
const r =
|
|
21631
|
+
const r = spawnSync8("gh", [
|
|
21183
21632
|
"pr",
|
|
21184
21633
|
"list",
|
|
21185
21634
|
"--repo",
|
|
@@ -21210,20 +21659,6 @@ function mergedPrStyle(limit = 6, cwd) {
|
|
|
21210
21659
|
examples
|
|
21211
21660
|
};
|
|
21212
21661
|
}
|
|
21213
|
-
|
|
21214
|
-
// packages/workit-core/src/core/branch.ts
|
|
21215
|
-
function effectiveWorkspacePolicy(workspaceRoot, kind, profileName) {
|
|
21216
|
-
const selected = resolveRuntimeWorkspacePolicy(workspaceRoot, kind, profileName?.trim() || process.env.WORKFLOW_PROFILE?.trim() || undefined);
|
|
21217
|
-
const config = readConfig();
|
|
21218
|
-
return kind === "branch" ? {
|
|
21219
|
-
branchPolicy: resolveBranchPolicy(config, selected.policy ? { branchPolicy: selected.policy } : null),
|
|
21220
|
-
provenance: { branchPolicy: selected.source }
|
|
21221
|
-
} : {
|
|
21222
|
-
commitPolicy: resolveCommitPolicy(config, selected.policy ? { commitPolicy: selected.policy } : null),
|
|
21223
|
-
provenance: { commitPolicy: selected.source }
|
|
21224
|
-
};
|
|
21225
|
-
}
|
|
21226
|
-
var resolveBranchPolicyFor = (workspaceRoot, profileName) => effectiveWorkspacePolicy(workspaceRoot, "branch", profileName).branchPolicy;
|
|
21227
21662
|
// packages/workit-core/src/core/task-engine.ts
|
|
21228
21663
|
import { realpathSync as realpathSync4 } from "node:fs";
|
|
21229
21664
|
|
|
@@ -23077,7 +23512,7 @@ class WorkitCore {
|
|
|
23077
23512
|
}
|
|
23078
23513
|
}
|
|
23079
23514
|
// packages/workit-core/src/core/repo-context.ts
|
|
23080
|
-
import { spawnSync as
|
|
23515
|
+
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
23081
23516
|
import { existsSync as existsSync6, readFileSync as readFileSync5, readdirSync as readdirSync4 } from "node:fs";
|
|
23082
23517
|
import path16 from "node:path";
|
|
23083
23518
|
var isSafeContextRange = (value) => value.length <= 4096 && (() => {
|
|
@@ -23106,7 +23541,7 @@ var invalidRange = (cwd) => ({
|
|
|
23106
23541
|
cwd
|
|
23107
23542
|
});
|
|
23108
23543
|
var runGit = (cwd, args) => {
|
|
23109
|
-
const result =
|
|
23544
|
+
const result = spawnSync9("git", args, { cwd, encoding: "utf8" });
|
|
23110
23545
|
return {
|
|
23111
23546
|
stdout: (result.stdout ?? "").trimEnd(),
|
|
23112
23547
|
stderr: (result.stderr ?? "").trimEnd(),
|
|
@@ -23547,12 +23982,12 @@ function releaseNotesContext(root, rangeOrTag) {
|
|
|
23547
23982
|
}
|
|
23548
23983
|
|
|
23549
23984
|
// packages/workit-core/src/core/tracker-issues.ts
|
|
23550
|
-
import { spawnSync as
|
|
23985
|
+
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
23551
23986
|
|
|
23552
23987
|
// packages/workit-core/src/core/pr-create.ts
|
|
23553
23988
|
import fs13 from "node:fs";
|
|
23554
23989
|
import path17 from "node:path";
|
|
23555
|
-
import { spawnSync as
|
|
23990
|
+
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
23556
23991
|
// packages/workit-core/src/forge/pr-body.ts
|
|
23557
23992
|
function parseGhIssue(value) {
|
|
23558
23993
|
const m = /issues\/(\d+)/.exec(value);
|
|
@@ -23577,7 +24012,7 @@ function whichOnPath(tool) {
|
|
|
23577
24012
|
}
|
|
23578
24013
|
var hostingCliAvailable = (provider) => whichOnPath(provider === "gitlab" ? "glab" : "gh") !== null;
|
|
23579
24014
|
var pushRemote = (cwd) => {
|
|
23580
|
-
const result =
|
|
24015
|
+
const result = spawnSync10("git", ["remote", "get-url", "--push", "--all", "origin"], {
|
|
23581
24016
|
cwd,
|
|
23582
24017
|
encoding: "utf8"
|
|
23583
24018
|
});
|
|
@@ -23608,7 +24043,7 @@ var defaultCli = (bin, available) => {
|
|
|
23608
24043
|
if (!available)
|
|
23609
24044
|
return null;
|
|
23610
24045
|
return (args, root) => {
|
|
23611
|
-
const out =
|
|
24046
|
+
const out = spawnSync11(bin, args, {
|
|
23612
24047
|
cwd: root,
|
|
23613
24048
|
encoding: "utf8",
|
|
23614
24049
|
env: { ...process.env, PATH: process.env.PATH ?? "" }
|
|
@@ -24126,7 +24561,7 @@ function resolveInside(root, candidate) {
|
|
|
24126
24561
|
}
|
|
24127
24562
|
function run2(root, executable, args, env = {}) {
|
|
24128
24563
|
const cwd = realpathSync5(root);
|
|
24129
|
-
const result =
|
|
24564
|
+
const result = spawnSync12(executable, args, {
|
|
24130
24565
|
cwd,
|
|
24131
24566
|
encoding: "utf8",
|
|
24132
24567
|
env: { ...process.env, ...env }
|
|
@@ -26572,8 +27007,8 @@ var SENSITIVE_WORDS = new Set([
|
|
|
26572
27007
|
"query"
|
|
26573
27008
|
]);
|
|
26574
27009
|
var STACK_WORDS = new Set(["stack", "stacktrace", "trace"]);
|
|
26575
|
-
var
|
|
26576
|
-
var homePattern = new RegExp(`${
|
|
27010
|
+
var escapeRegExp2 = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
27011
|
+
var homePattern = new RegExp(`${escapeRegExp2(os4.homedir())}(?=[/\\\\]|$)|\\$HOME(?=[/\\\\]|$)`, "g");
|
|
26577
27012
|
var applyPatterns = (value) => {
|
|
26578
27013
|
let out = value;
|
|
26579
27014
|
out = out.replace(SECRET_VALUE, REDACTED);
|
package/dist/workit-hook.js
CHANGED
|
@@ -13872,6 +13872,7 @@ var readConfig = () => {
|
|
|
13872
13872
|
throw new Error(result.error);
|
|
13873
13873
|
return result.config ?? DEFAULTS;
|
|
13874
13874
|
};
|
|
13875
|
+
var branchGlobPattern = (glob) => new RegExp(`^${glob.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*")}$`, "i");
|
|
13875
13876
|
var resolveBranchPolicy = (config, workspace) => {
|
|
13876
13877
|
const wp = workspace?.branchPolicy ?? {};
|
|
13877
13878
|
const preset = Object.hasOwn(PRESETS, wp.preset) ? wp.preset : config.branchPolicy?.preset ?? "gitflow";
|
|
@@ -13879,7 +13880,7 @@ var resolveBranchPolicy = (config, workspace) => {
|
|
|
13879
13880
|
allowed: wp.allowed,
|
|
13880
13881
|
protectedNames: wp.protected
|
|
13881
13882
|
}, config);
|
|
13882
|
-
const allowed = merged.allowed.map(
|
|
13883
|
+
const allowed = merged.allowed.map(branchGlobPattern);
|
|
13883
13884
|
return {
|
|
13884
13885
|
preset,
|
|
13885
13886
|
allowed,
|
|
@@ -13944,26 +13945,31 @@ var versionSourceSchema = discriminatedUnion("kind", [
|
|
|
13944
13945
|
object({ kind: literal("manual") }).strict()
|
|
13945
13946
|
]);
|
|
13946
13947
|
var releaseTrackSchema = object({
|
|
13947
|
-
strategy: branchPreset,
|
|
13948
|
+
strategy: branchPreset.optional(),
|
|
13948
13949
|
productionBranch: nonBlank,
|
|
13949
13950
|
integrationBranch: nonBlank,
|
|
13950
|
-
naming: object({
|
|
13951
|
-
|
|
13952
|
-
|
|
13953
|
-
|
|
13954
|
-
|
|
13955
|
-
|
|
13956
|
-
|
|
13957
|
-
|
|
13951
|
+
naming: object({
|
|
13952
|
+
feature: nonBlank.optional(),
|
|
13953
|
+
release: nonBlank.optional(),
|
|
13954
|
+
hotfix: nonBlank.optional()
|
|
13955
|
+
}).passthrough().optional(),
|
|
13956
|
+
baseBranch: nonBlank.optional(),
|
|
13957
|
+
mergeBackBranches: array(nonBlank).optional(),
|
|
13958
|
+
pullRequestTarget: nonBlank.optional(),
|
|
13959
|
+
tagNamespace: string2().optional(),
|
|
13960
|
+
versionSource: versionSourceSchema.optional(),
|
|
13961
|
+
requiredChecks: array(nonBlank).optional(),
|
|
13962
|
+
critical: array(nonBlank).optional()
|
|
13963
|
+
}).passthrough().superRefine((track, context) => {
|
|
13958
13964
|
for (const [field, values] of [
|
|
13959
|
-
["mergeBackBranches", track.mergeBackBranches],
|
|
13960
|
-
["requiredChecks", track.requiredChecks]
|
|
13965
|
+
["mergeBackBranches", track.mergeBackBranches ?? []],
|
|
13966
|
+
["requiredChecks", track.requiredChecks ?? []]
|
|
13961
13967
|
]) {
|
|
13962
13968
|
if (new Set(values).size !== values.length) {
|
|
13963
13969
|
context.addIssue({ code: "custom", path: [field], message: "entries must be unique" });
|
|
13964
13970
|
}
|
|
13965
13971
|
}
|
|
13966
|
-
if (track.versionSource
|
|
13972
|
+
if (track.versionSource?.kind === "package-json" && (path13.posix.isAbsolute(track.versionSource.path.replaceAll("\\", "/")) || /^[A-Za-z]:\//u.test(track.versionSource.path.replaceAll("\\", "/")) || track.versionSource.path.replaceAll("\\", "/").split("/").includes(".."))) {
|
|
13967
13973
|
context.addIssue({
|
|
13968
13974
|
code: "custom",
|
|
13969
13975
|
path: ["versionSource", "path"],
|
|
@@ -14230,7 +14236,7 @@ var runtimeWorkspacePolicySchema = (kind) => {
|
|
|
14230
14236
|
var runtimeWorkspaceIndexSchema = object({
|
|
14231
14237
|
workspaces: array(object({ name: nonBlank, glob: nonBlank }).passthrough()).optional()
|
|
14232
14238
|
}).passthrough();
|
|
14233
|
-
var
|
|
14239
|
+
var matchRuntimeWorkspace = (cwd) => {
|
|
14234
14240
|
const file = path13.join(configDir(), "workspaces.json");
|
|
14235
14241
|
let raw;
|
|
14236
14242
|
try {
|
|
@@ -14265,8 +14271,17 @@ var resolveRuntimeWorkspaceCandidate = (cwd, kind) => {
|
|
|
14265
14271
|
});
|
|
14266
14272
|
const workspaceName = process.env.WORKFLOW_WORKSPACE_NAME?.trim() || undefined;
|
|
14267
14273
|
const selected = selectWorkspaceMatch(matches, cwd, workspaceName);
|
|
14268
|
-
|
|
14274
|
+
return selected ? { file, selected } : null;
|
|
14275
|
+
};
|
|
14276
|
+
var resolveRuntimeReleaseTracks = (cwd) => {
|
|
14277
|
+
const matched = matchRuntimeWorkspace(cwd);
|
|
14278
|
+
return matched ? { workspace: matched.selected.name, releaseTracks: matched.selected.releaseTracks } : null;
|
|
14279
|
+
};
|
|
14280
|
+
var resolveRuntimeWorkspaceCandidate = (cwd, kind) => {
|
|
14281
|
+
const matched = matchRuntimeWorkspace(cwd);
|
|
14282
|
+
if (!matched)
|
|
14269
14283
|
return null;
|
|
14284
|
+
const { file, selected } = matched;
|
|
14270
14285
|
const policy = runtimeWorkspacePolicySchema(kind).safeParse(selected);
|
|
14271
14286
|
if (!policy.success) {
|
|
14272
14287
|
const detail = policy.error.issues.map((issue) => `${issue.path.map(String).join(".") || "workspace"}: ${issue.message}`).join("; ");
|
|
@@ -16230,11 +16245,176 @@ var turnContextText = (input, descriptor) => {
|
|
|
16230
16245
|
};
|
|
16231
16246
|
// packages/workit-core/src/core/branch.ts
|
|
16232
16247
|
import { createHash as createHash9 } from "node:crypto";
|
|
16248
|
+
|
|
16249
|
+
// packages/workit-core/src/core/release-tracks.ts
|
|
16250
|
+
class ReleaseTrackError extends Error {
|
|
16251
|
+
}
|
|
16252
|
+
var KNOWN_FIELDS = new Set([
|
|
16253
|
+
"strategy",
|
|
16254
|
+
"productionBranch",
|
|
16255
|
+
"integrationBranch",
|
|
16256
|
+
"naming",
|
|
16257
|
+
"baseBranch",
|
|
16258
|
+
"mergeBackBranches",
|
|
16259
|
+
"pullRequestTarget",
|
|
16260
|
+
"tagNamespace",
|
|
16261
|
+
"versionSource",
|
|
16262
|
+
"requiredChecks",
|
|
16263
|
+
"critical"
|
|
16264
|
+
]);
|
|
16265
|
+
var BRANCH_FIELDS = ["productionBranch", "integrationBranch", "baseBranch", "pullRequestTarget"];
|
|
16266
|
+
var PLACEHOLDER = /\{[^}]*\}/gu;
|
|
16267
|
+
var HAS_PLACEHOLDER = /\{[^}]*\}/u;
|
|
16268
|
+
var isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16269
|
+
var branchName = (value) => typeof value === "string" && value.trim() && !value.trim().startsWith("-") ? value.trim() : null;
|
|
16270
|
+
var namedBranches = (entry) => [
|
|
16271
|
+
...BRANCH_FIELDS.map((field) => branchName(entry[field])),
|
|
16272
|
+
...Array.isArray(entry.mergeBackBranches) ? entry.mergeBackBranches.map(branchName) : []
|
|
16273
|
+
].filter((name) => name !== null);
|
|
16274
|
+
var literalOf = (template) => template.replace(PLACEHOLDER, "").replace(/[*/]/gu, "").trim();
|
|
16275
|
+
function readReleaseTracks(raw) {
|
|
16276
|
+
const out = { tracks: [], issues: [], error: null, protectedBranches: [] };
|
|
16277
|
+
if (raw === undefined || raw === null)
|
|
16278
|
+
return out;
|
|
16279
|
+
if (!isRecord3(raw)) {
|
|
16280
|
+
out.issues.push("releaseTracks is not an object; ignored");
|
|
16281
|
+
return out;
|
|
16282
|
+
}
|
|
16283
|
+
const fatal = [];
|
|
16284
|
+
const protectedNames = new Set;
|
|
16285
|
+
for (const [name, entry] of Object.entries(raw).toSorted(([a], [b]) => a < b ? -1 : 1)) {
|
|
16286
|
+
const label = `release track ${JSON.stringify(name)}`;
|
|
16287
|
+
if (!isRecord3(entry)) {
|
|
16288
|
+
out.issues.push(`${label} is not an object; ignored`);
|
|
16289
|
+
continue;
|
|
16290
|
+
}
|
|
16291
|
+
for (const branch of namedBranches(entry))
|
|
16292
|
+
protectedNames.add(branch);
|
|
16293
|
+
if (!name.trim()) {
|
|
16294
|
+
out.issues.push("a release track with a blank name was ignored");
|
|
16295
|
+
continue;
|
|
16296
|
+
}
|
|
16297
|
+
let critical = [];
|
|
16298
|
+
if (Array.isArray(entry.critical))
|
|
16299
|
+
critical = entry.critical.filter((item) => typeof item === "string");
|
|
16300
|
+
else if (entry.critical !== undefined)
|
|
16301
|
+
out.issues.push(`${label} critical: must be a list of field names; ignored`);
|
|
16302
|
+
const isCritical = (field) => critical.some((item) => field === item || field.startsWith(`${item}.`));
|
|
16303
|
+
const problem = (field, message) => {
|
|
16304
|
+
if (isCritical(field))
|
|
16305
|
+
fatal.push(`${label} ${field}: ${message}`);
|
|
16306
|
+
else
|
|
16307
|
+
out.issues.push(`${label} ${field}: ${message}`);
|
|
16308
|
+
};
|
|
16309
|
+
for (const key of Object.keys(entry))
|
|
16310
|
+
if (!KNOWN_FIELDS.has(key))
|
|
16311
|
+
problem(key, "unknown field, ignored");
|
|
16312
|
+
const productionBranch = branchName(entry.productionBranch);
|
|
16313
|
+
const integrationBranch = branchName(entry.integrationBranch);
|
|
16314
|
+
if (!productionBranch)
|
|
16315
|
+
problem("productionBranch", "missing or not a branch name");
|
|
16316
|
+
if (!integrationBranch)
|
|
16317
|
+
problem("integrationBranch", "missing or not a branch name");
|
|
16318
|
+
const optionalBranch = (field) => {
|
|
16319
|
+
if (entry[field] === undefined)
|
|
16320
|
+
return null;
|
|
16321
|
+
const value = branchName(entry[field]);
|
|
16322
|
+
if (!value)
|
|
16323
|
+
problem(field, "not a branch name; using the integration branch");
|
|
16324
|
+
return value;
|
|
16325
|
+
};
|
|
16326
|
+
const baseBranch = optionalBranch("baseBranch");
|
|
16327
|
+
const pullRequestTarget = optionalBranch("pullRequestTarget");
|
|
16328
|
+
let mergeBackBranches = [];
|
|
16329
|
+
if (entry.mergeBackBranches !== undefined) {
|
|
16330
|
+
const list = Array.isArray(entry.mergeBackBranches) ? entry.mergeBackBranches.map(branchName) : [null];
|
|
16331
|
+
if (list.some((item) => item === null))
|
|
16332
|
+
problem("mergeBackBranches", "must be a list of branch names; ignored");
|
|
16333
|
+
else
|
|
16334
|
+
mergeBackBranches = [...new Set(list)];
|
|
16335
|
+
}
|
|
16336
|
+
const naming = {};
|
|
16337
|
+
if (entry.naming !== undefined) {
|
|
16338
|
+
if (!isRecord3(entry.naming))
|
|
16339
|
+
problem("naming", "not an object; ignored");
|
|
16340
|
+
else
|
|
16341
|
+
for (const kind of ["feature", "release", "hotfix"]) {
|
|
16342
|
+
const template = entry.naming[kind];
|
|
16343
|
+
if (template === undefined)
|
|
16344
|
+
continue;
|
|
16345
|
+
if (typeof template !== "string" || !template.trim())
|
|
16346
|
+
problem(`naming.${kind}`, "not a template string; ignored");
|
|
16347
|
+
else if (!literalOf(template))
|
|
16348
|
+
problem(`naming.${kind}`, "needs literal text besides placeholders; ignored");
|
|
16349
|
+
else
|
|
16350
|
+
naming[kind] = template.trim();
|
|
16351
|
+
}
|
|
16352
|
+
}
|
|
16353
|
+
if (!productionBranch || !integrationBranch) {
|
|
16354
|
+
out.issues.push(`${label} was skipped: it needs a productionBranch and integrationBranch`);
|
|
16355
|
+
continue;
|
|
16356
|
+
}
|
|
16357
|
+
out.tracks.push({
|
|
16358
|
+
name,
|
|
16359
|
+
productionBranch,
|
|
16360
|
+
integrationBranch,
|
|
16361
|
+
baseBranch: baseBranch ?? integrationBranch,
|
|
16362
|
+
pullRequestTarget: pullRequestTarget ?? integrationBranch,
|
|
16363
|
+
mergeBackBranches,
|
|
16364
|
+
naming
|
|
16365
|
+
});
|
|
16366
|
+
}
|
|
16367
|
+
out.protectedBranches = [...protectedNames];
|
|
16368
|
+
if (fatal.length)
|
|
16369
|
+
out.error = `workspace releaseTracks cannot be read by this Workit (${fatal.join("; ")}); upgrade Workit or fix the track`;
|
|
16370
|
+
return out;
|
|
16371
|
+
}
|
|
16372
|
+
var trackBranches = (tracks) => [
|
|
16373
|
+
...new Set(tracks.flatMap((track) => [
|
|
16374
|
+
track.productionBranch,
|
|
16375
|
+
track.integrationBranch,
|
|
16376
|
+
track.baseBranch,
|
|
16377
|
+
track.pullRequestTarget,
|
|
16378
|
+
...track.mergeBackBranches
|
|
16379
|
+
]))
|
|
16380
|
+
];
|
|
16381
|
+
var namingGlob = (template) => HAS_PLACEHOLDER.test(template) ? template.replace(PLACEHOLDER, "*") : `${template.replace(/\/?\*?$/u, "")}/*`;
|
|
16382
|
+
function workspaceReleaseTracks(cwd) {
|
|
16383
|
+
const raw = resolveRuntimeReleaseTracks(cwd);
|
|
16384
|
+
return { workspace: raw?.workspace ?? null, ...readReleaseTracks(raw?.releaseTracks) };
|
|
16385
|
+
}
|
|
16386
|
+
var memo3 = new Map;
|
|
16387
|
+
|
|
16388
|
+
// packages/workit-core/src/core/branch.ts
|
|
16389
|
+
var withReleaseTracks = (workspaceRoot, policy) => {
|
|
16390
|
+
const read = workspaceReleaseTracks(workspaceRoot);
|
|
16391
|
+
if (read.error)
|
|
16392
|
+
throw new ReleaseTrackError(read.error);
|
|
16393
|
+
if (read.tracks.length === 0 && read.protectedBranches.length === 0)
|
|
16394
|
+
return policy;
|
|
16395
|
+
const known = new Set(policy.allowed.map((pattern) => pattern.source));
|
|
16396
|
+
const allowed = [...policy.allowed];
|
|
16397
|
+
for (const glob of read.tracks.flatMap((track) => Object.values(track.naming).map(namingGlob))) {
|
|
16398
|
+
const pattern = branchGlobPattern(glob);
|
|
16399
|
+
if (!known.has(pattern.source)) {
|
|
16400
|
+
known.add(pattern.source);
|
|
16401
|
+
allowed.push(pattern);
|
|
16402
|
+
}
|
|
16403
|
+
}
|
|
16404
|
+
return {
|
|
16405
|
+
...policy,
|
|
16406
|
+
allowed,
|
|
16407
|
+
protected: new Set([
|
|
16408
|
+
...policy.protected,
|
|
16409
|
+
...[...trackBranches(read.tracks), ...read.protectedBranches].map((name) => name.toLowerCase())
|
|
16410
|
+
])
|
|
16411
|
+
};
|
|
16412
|
+
};
|
|
16233
16413
|
function effectiveWorkspacePolicy(workspaceRoot, kind, profileName) {
|
|
16234
16414
|
const selected = resolveRuntimeWorkspacePolicy(workspaceRoot, kind, profileName?.trim() || process.env.WORKFLOW_PROFILE?.trim() || undefined);
|
|
16235
16415
|
const config = readConfig();
|
|
16236
16416
|
return kind === "branch" ? {
|
|
16237
|
-
branchPolicy: resolveBranchPolicy(config, selected.policy ? { branchPolicy: selected.policy } : null),
|
|
16417
|
+
branchPolicy: withReleaseTracks(workspaceRoot, resolveBranchPolicy(config, selected.policy ? { branchPolicy: selected.policy } : null)),
|
|
16238
16418
|
provenance: { branchPolicy: selected.source }
|
|
16239
16419
|
} : {
|
|
16240
16420
|
commitPolicy: resolveCommitPolicy(config, selected.policy ? { commitPolicy: selected.policy } : null),
|
|
@@ -16583,7 +16763,7 @@ function writeGate(cwd, paths) {
|
|
|
16583
16763
|
// packages/workit-core/src/hooks/hosts/fields.ts
|
|
16584
16764
|
import { existsSync as existsSync6, realpathSync as realpathSync6, statSync as statSync2 } from "node:fs";
|
|
16585
16765
|
import path17 from "node:path";
|
|
16586
|
-
var
|
|
16766
|
+
var isRecord4 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
16587
16767
|
var nonEmpty2 = (value) => typeof value === "string" && value.trim() !== "";
|
|
16588
16768
|
var optionalText = (value) => typeof value === "string" ? value : null;
|
|
16589
16769
|
var existingDirectory = (value) => {
|
|
@@ -16639,7 +16819,7 @@ var WRITE_TOOLS = new Set([
|
|
|
16639
16819
|
var isWriteTool = (name) => typeof name === "string" && WRITE_TOOLS.has(name.toLowerCase().replace(/[_-]/g, ""));
|
|
16640
16820
|
var PATH_KEYS = ["file_path", "filePath", "notebook_path", "path", "target_file", "file"];
|
|
16641
16821
|
var writePaths = (input) => {
|
|
16642
|
-
if (!
|
|
16822
|
+
if (!isRecord4(input))
|
|
16643
16823
|
return [];
|
|
16644
16824
|
const paths = PATH_KEYS.map((key) => input[key]).filter(nonEmpty2);
|
|
16645
16825
|
for (const value of Object.values(input))
|
|
@@ -16843,7 +17023,7 @@ var EVENTS = {
|
|
|
16843
17023
|
};
|
|
16844
17024
|
var SOURCES = new Set(["startup", "resume", "clear", "compact", "fork"]);
|
|
16845
17025
|
var SHELL_TOOLS = new Set(["Bash", "PowerShell"]);
|
|
16846
|
-
var toolCommand = (value) =>
|
|
17026
|
+
var toolCommand = (value) => isRecord4(value.tool_input) ? commandText(value.tool_input.command) : null;
|
|
16847
17027
|
var eventOf = (name, value) => {
|
|
16848
17028
|
const toolUseId = optionalText(value.tool_use_id);
|
|
16849
17029
|
switch (name) {
|
|
@@ -16873,7 +17053,7 @@ var eventOf = (name, value) => {
|
|
|
16873
17053
|
const command = toolCommand(value);
|
|
16874
17054
|
if (!SHELL_TOOLS.has(String(value.tool_name)) || !command)
|
|
16875
17055
|
return { ok: false, error: "only shell PostToolUse is mapped" };
|
|
16876
|
-
const response =
|
|
17056
|
+
const response = isRecord4(value.tool_response) ? value.tool_response : {};
|
|
16877
17057
|
return {
|
|
16878
17058
|
ok: true,
|
|
16879
17059
|
event: {
|
|
@@ -16949,14 +17129,14 @@ var render = (decision, native) => {
|
|
|
16949
17129
|
var claudeCodeAdapter = {
|
|
16950
17130
|
descriptor: CLAUDE_CODE_DESCRIPTOR,
|
|
16951
17131
|
parse(raw) {
|
|
16952
|
-
const native =
|
|
17132
|
+
const native = isRecord4(raw) && Object.hasOwn(EVENTS, String(raw.hook_event_name)) ? raw.hook_event_name : null;
|
|
16953
17133
|
const fail = (error) => ({
|
|
16954
17134
|
ok: false,
|
|
16955
17135
|
error,
|
|
16956
17136
|
native,
|
|
16957
17137
|
event: native ? EVENTS[native] : null
|
|
16958
17138
|
});
|
|
16959
|
-
if (!
|
|
17139
|
+
if (!isRecord4(raw) || !native)
|
|
16960
17140
|
return fail("hook_event_name is required");
|
|
16961
17141
|
if (!nonEmpty2(raw.session_id))
|
|
16962
17142
|
return fail("session_id is required");
|
|
@@ -17099,7 +17279,7 @@ var SHELL_TOOLS2 = new Set(["bash", "unified-exec"]);
|
|
|
17099
17279
|
var isShellTool = (name) => SHELL_TOOLS2.has(String(name).toLowerCase());
|
|
17100
17280
|
var SOURCES2 = new Set(["startup", "resume", "clear", "compact"]);
|
|
17101
17281
|
var parseCodexHookInput = (value) => {
|
|
17102
|
-
if (!
|
|
17282
|
+
if (!isRecord4(value) || !Object.hasOwn(EVENTS2, String(value.hook_event_name)))
|
|
17103
17283
|
return { ok: false, error: "hook_event_name is required" };
|
|
17104
17284
|
const event = value.hook_event_name;
|
|
17105
17285
|
const cwd = existingDirectory(value.cwd);
|
|
@@ -17107,7 +17287,7 @@ var parseCodexHookInput = (value) => {
|
|
|
17107
17287
|
return { ok: false, error: "cwd must be an existing absolute directory" };
|
|
17108
17288
|
if (event === "PreToolUse" && !nonEmpty2(value.tool_name))
|
|
17109
17289
|
return { ok: false, error: "tool_name is required" };
|
|
17110
|
-
const command =
|
|
17290
|
+
const command = isRecord4(value.tool_input) ? commandText(value.tool_input.command) : null;
|
|
17111
17291
|
if (event === "PreToolUse" && isShellTool(value.tool_name) && !command)
|
|
17112
17292
|
return { ok: false, error: "tool_input.command is required for shell tools" };
|
|
17113
17293
|
if (event === "SubagentStart" && !nonEmpty2(value.agent_id))
|
|
@@ -17190,7 +17370,7 @@ var codexAdapter = {
|
|
|
17190
17370
|
const host = detectCodexSurface(env);
|
|
17191
17371
|
const parsed = parseCodexHookInput(raw);
|
|
17192
17372
|
if (!parsed.ok) {
|
|
17193
|
-
const native =
|
|
17373
|
+
const native = isRecord4(raw) && Object.hasOwn(EVENTS2, String(raw.hook_event_name)) ? raw.hook_event_name : null;
|
|
17194
17374
|
return { ok: false, error: parsed.error, native, event: native ? EVENTS2[native] : null };
|
|
17195
17375
|
}
|
|
17196
17376
|
const input = parsed.data;
|
|
@@ -17329,7 +17509,7 @@ var EVENTS3 = {
|
|
|
17329
17509
|
preCompact: "compact.pre"
|
|
17330
17510
|
};
|
|
17331
17511
|
var parseCursorHookInput = (value) => {
|
|
17332
|
-
if (!
|
|
17512
|
+
if (!isRecord4(value) || !Object.hasOwn(EVENTS3, String(value.hook_event_name)))
|
|
17333
17513
|
return { ok: false, error: "hook_event_name is required" };
|
|
17334
17514
|
const roots = value.workspace_roots;
|
|
17335
17515
|
if (!Array.isArray(roots) || roots.length === 0 || !roots.every(nonEmpty2))
|
|
@@ -17435,7 +17615,7 @@ var cursorAdapter = {
|
|
|
17435
17615
|
parse(raw) {
|
|
17436
17616
|
const parsed = parseCursorHookInput(raw);
|
|
17437
17617
|
if (!parsed.ok) {
|
|
17438
|
-
const native =
|
|
17618
|
+
const native = isRecord4(raw) && Object.hasOwn(EVENTS3, String(raw.hook_event_name)) ? raw.hook_event_name : null;
|
|
17439
17619
|
return { ok: false, error: parsed.error, native, event: native ? EVENTS3[native] : null };
|
|
17440
17620
|
}
|
|
17441
17621
|
const input = parsed.data;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainervirus/workit-codex",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.1.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Workit Codex CLI/desktop plugin — shared MCP transport, hooks, and sixteen method skills",
|
|
6
6
|
"keywords": [
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"build": "bun scripts/build.ts"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@brainervirus/workit-core": "^7.
|
|
42
|
-
"@brainervirus/workit-mcp": "^7.
|
|
41
|
+
"@brainervirus/workit-core": "^7.1.0",
|
|
42
|
+
"@brainervirus/workit-mcp": "^7.1.0"
|
|
43
43
|
},
|
|
44
44
|
"engines": {
|
|
45
45
|
"node": ">=24"
|