@brainervirus/workit-opencode 8.0.1 → 8.1.1

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.
Files changed (2) hide show
  1. package/dist/plugin.js +239 -202
  2. package/package.json +2 -2
package/dist/plugin.js CHANGED
@@ -4,7 +4,7 @@ function define(plugin) {
4
4
  }
5
5
 
6
6
  // packages/workit-core/src/core.ts
7
- import { spawnSync as spawnSync12 } from "node:child_process";
7
+ import { spawnSync as spawnSync14 } from "node:child_process";
8
8
  import { existsSync as existsSync7, realpathSync as realpathSync5 } from "node:fs";
9
9
  import path19 from "node:path";
10
10
 
@@ -13928,73 +13928,8 @@ var exportDigest = (bundle) => sha256({
13928
13928
  // packages/workit-core/src/core/branch.ts
13929
13929
  import { createHash as createHash10 } from "node:crypto";
13930
13930
 
13931
- // packages/workit-core/src/core/git.ts
13932
- import { execFileSync } from "node:child_process";
13933
- var run = (cwd, args) => {
13934
- try {
13935
- const stdout = execFileSync("git", args, {
13936
- cwd,
13937
- encoding: "utf8",
13938
- stdio: ["pipe", "pipe", "pipe"]
13939
- });
13940
- return { stdout: stdout.trimEnd(), stderr: "", exitCode: 0 };
13941
- } catch (error) {
13942
- const e = error;
13943
- return {
13944
- stdout: (e.stdout ?? "").trimEnd(),
13945
- stderr: (e.stderr ?? "").trimEnd(),
13946
- exitCode: e.status ?? 1
13947
- };
13948
- }
13949
- };
13950
- var gitContext = (workspaceRoot, paths = []) => {
13951
- const cwd = workspaceRoot;
13952
- let failure;
13953
- const runHere = (args) => {
13954
- const result = run(cwd, args);
13955
- if (!failure && result.exitCode !== 0) {
13956
- failure = { stderr: result.stderr, exitCode: result.exitCode };
13957
- }
13958
- return result.stdout;
13959
- };
13960
- const branch = runHere(["rev-parse", "--abbrev-ref", "HEAD"]) || "unknown";
13961
- const status_short = runHere(["status", "--porcelain"]);
13962
- const staged = [];
13963
- const unstaged = [];
13964
- const untracked = [];
13965
- for (const line of status_short.split(`
13966
- `).filter(Boolean)) {
13967
- const code = line.slice(0, 2);
13968
- const file = line.slice(3);
13969
- if (code === "??") {
13970
- untracked.push(file);
13971
- } else {
13972
- if (code[0] !== " " && code[0] !== "?")
13973
- staged.push(file);
13974
- if (code[1] !== " " && code[1] !== "?")
13975
- unstaged.push(file);
13976
- }
13977
- }
13978
- const pathArgs = paths.length ? ["--", ...paths] : [];
13979
- const diff_stat = runHere(["diff", "--stat", ...pathArgs]);
13980
- const cached_stat = runHere(["diff", "--cached", "--stat", ...pathArgs]);
13981
- const stagedSet = new Set(staged);
13982
- const unstagedSet = new Set(unstaged);
13983
- const partial_staged = [...stagedSet].filter((f) => unstagedSet.has(f));
13984
- return {
13985
- workspace_root: cwd,
13986
- branch,
13987
- status_short,
13988
- staged,
13989
- unstaged,
13990
- untracked,
13991
- diff_stat: [diff_stat, cached_stat].filter(Boolean).join(`
13992
- `),
13993
- partial_staged: partial_staged.length > 0,
13994
- partial_staged_files: partial_staged,
13995
- ...failure ? { stderr: failure.stderr, exitCode: failure.exitCode } : {}
13996
- };
13997
- };
13931
+ // packages/workit-core/src/core/branch-policy.ts
13932
+ import { spawnSync as spawnSync7 } from "node:child_process";
13998
13933
 
13999
13934
  // packages/workit-core/src/core/config.ts
14000
13935
  import {
@@ -14120,6 +14055,7 @@ var DEFAULTS = {
14120
14055
  },
14121
14056
  commitPolicy: { preset: "conventional" }
14122
14057
  };
14058
+ var unchosenBranchPolicy = new WeakSet([DEFAULTS]);
14123
14059
  var readSafe = (p) => {
14124
14060
  try {
14125
14061
  return readFileSync3(p, "utf8");
@@ -14144,22 +14080,21 @@ var parseConfigResult = (raw, file) => {
14144
14080
  const locale = LOCALE_RE.test(String(input.locale ?? "")) ? input.locale : DEFAULTS.locale;
14145
14081
  const preset = Object.hasOwn(PRESETS, input.branchPolicy?.preset) ? input.branchPolicy?.preset : "gitflow";
14146
14082
  const commitPreset = COMMIT_PRESETS.includes(String(input.commitPolicy?.preset ?? "")) ? input.commitPolicy?.preset : "conventional";
14147
- return {
14148
- status: "valid",
14149
- path: file,
14150
- config: {
14151
- locale,
14152
- localeOptions: Array.isArray(input.localeOptions) ? input.localeOptions : DEFAULTS.localeOptions,
14153
- branchPolicy: mergePreset(preset, {
14154
- allowed: Array.isArray(input.branchPolicy?.allowed) ? input.branchPolicy.allowed : undefined,
14155
- protectedNames: Array.isArray(input.branchPolicy?.protected) ? input.branchPolicy.protected : undefined
14156
- }, DEFAULTS),
14157
- commitPolicy: {
14158
- preset: commitPreset,
14159
- ...typeof input.commitPolicy?.pattern === "string" ? { pattern: input.commitPolicy.pattern } : {}
14160
- }
14083
+ const config = {
14084
+ locale,
14085
+ localeOptions: Array.isArray(input.localeOptions) ? input.localeOptions : DEFAULTS.localeOptions,
14086
+ branchPolicy: mergePreset(preset, {
14087
+ allowed: Array.isArray(input.branchPolicy?.allowed) ? input.branchPolicy.allowed : undefined,
14088
+ protectedNames: Array.isArray(input.branchPolicy?.protected) ? input.branchPolicy.protected : undefined
14089
+ }, DEFAULTS),
14090
+ commitPolicy: {
14091
+ preset: commitPreset,
14092
+ ...typeof input.commitPolicy?.pattern === "string" ? { pattern: input.commitPolicy.pattern } : {}
14161
14093
  }
14162
14094
  };
14095
+ if (!Object.hasOwn(PRESETS, input.branchPolicy?.preset))
14096
+ unchosenBranchPolicy.add(config);
14097
+ return { status: "valid", path: file, config };
14163
14098
  };
14164
14099
  var readConfigTyped = (dir) => {
14165
14100
  const file = path12.join(dir ?? configDir(), "config.json");
@@ -14185,9 +14120,11 @@ var writeConfig = (config) => {
14185
14120
  };
14186
14121
  var vcsConfigPath = () => process.env.WORKFLOW_VCS_CONFIG ?? path12.join(configDir(), "vcs.json");
14187
14122
  var branchGlobPattern = (glob) => new RegExp(`^${glob.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*")}$`, "i");
14188
- var resolveBranchPolicy = (config, workspace) => {
14123
+ var resolveBranchPolicy = (config, workspace, repoPreset) => {
14189
14124
  const wp = workspace?.branchPolicy ?? {};
14190
- const preset = Object.hasOwn(PRESETS, wp.preset) ? wp.preset : config.branchPolicy?.preset ?? "gitflow";
14125
+ const workspacePreset = Object.hasOwn(PRESETS, wp.preset);
14126
+ const detected = !workspacePreset && unchosenBranchPolicy.has(config) ? repoPreset?.() ?? null : null;
14127
+ const preset = workspacePreset ? wp.preset : detected ?? config.branchPolicy?.preset ?? "gitflow";
14191
14128
  const merged = mergePreset(preset, {
14192
14129
  allowed: wp.allowed,
14193
14130
  protectedNames: wp.protected
@@ -14196,9 +14133,10 @@ var resolveBranchPolicy = (config, workspace) => {
14196
14133
  return {
14197
14134
  preset,
14198
14135
  allowed,
14199
- protected: new Set(merged.protected.map((p) => p.toLowerCase())),
14136
+ protected: new Set([...merged.protected, ...detected ? PRESETS.gitflow.protected : []].map((p) => p.toLowerCase())),
14200
14137
  integration: wp.integration === "merge" ? "merge" : "pr",
14201
- defaultTargetBranch: preset === "github-flow" ? "main" : preset === "trunk-based" ? "master" : "develop"
14138
+ defaultTargetBranch: preset === "github-flow" ? "main" : preset === "trunk-based" ? "master" : "develop",
14139
+ detected: detected !== null
14202
14140
  };
14203
14141
  };
14204
14142
  var COMMIT_PRESETS = [
@@ -14220,7 +14158,140 @@ var resolveCommitPolicy = (config, workspace) => {
14220
14158
  return config.commitPolicy ?? { preset: "conventional" };
14221
14159
  };
14222
14160
 
14161
+ // packages/workit-core/src/core/branch-policy.ts
14162
+ var PREFIXES = {
14163
+ feature: "feature/*",
14164
+ bugfix: "bugfix/*",
14165
+ release: "release/*",
14166
+ hotfix: "hotfix/*"
14167
+ };
14168
+ var branchNames = (workspaceRoot) => {
14169
+ const r = spawnSync7("git", ["for-each-ref", "--format=%(refname)", "refs/heads", "refs/remotes/origin"], { cwd: workspaceRoot, encoding: "utf8" });
14170
+ if (r.status !== 0)
14171
+ return new Set;
14172
+ return new Set((r.stdout ?? "").split(`
14173
+ `).filter(Boolean).map((ref) => ref.startsWith("refs/heads/") ? ref.slice("refs/heads/".length) : ref.slice("refs/remotes/origin/".length)));
14174
+ };
14175
+ var detectBranchPolicy = (workspaceRoot) => {
14176
+ const names = branchNames(workspaceRoot);
14177
+ const develop = names.has("develop");
14178
+ const main = names.has("main");
14179
+ const master = names.has("master");
14180
+ const root = main ? "main" : master ? "master" : null;
14181
+ if (develop) {
14182
+ return {
14183
+ preset: "gitflow",
14184
+ developBranch: "develop",
14185
+ integration: "merge",
14186
+ protected: root ? [root, "develop"] : ["develop"],
14187
+ allowed: [...PRESETS.gitflow.allowed],
14188
+ prefixes: PREFIXES
14189
+ };
14190
+ }
14191
+ if (root === "main") {
14192
+ return {
14193
+ preset: "github-flow",
14194
+ developBranch: null,
14195
+ integration: "pr",
14196
+ protected: [root],
14197
+ allowed: ["*"],
14198
+ prefixes: PREFIXES
14199
+ };
14200
+ }
14201
+ if (root === "master") {
14202
+ return {
14203
+ preset: "trunk-based",
14204
+ developBranch: null,
14205
+ integration: "pr",
14206
+ protected: [root],
14207
+ allowed: ["*"],
14208
+ prefixes: PREFIXES
14209
+ };
14210
+ }
14211
+ return {
14212
+ preset: "gitflow",
14213
+ developBranch: null,
14214
+ integration: "merge",
14215
+ protected: [],
14216
+ allowed: [],
14217
+ prefixes: PREFIXES
14218
+ };
14219
+ };
14220
+ var repoBranchPreset = (workspaceRoot) => {
14221
+ const detected = detectBranchPolicy(workspaceRoot);
14222
+ return detected.developBranch || detected.allowed.length ? detected.preset : null;
14223
+ };
14224
+
14225
+ // packages/workit-core/src/core/git.ts
14226
+ import { execFileSync } from "node:child_process";
14227
+ var run = (cwd, args) => {
14228
+ try {
14229
+ const stdout = execFileSync("git", args, {
14230
+ cwd,
14231
+ encoding: "utf8",
14232
+ stdio: ["pipe", "pipe", "pipe"]
14233
+ });
14234
+ return { stdout: stdout.trimEnd(), stderr: "", exitCode: 0 };
14235
+ } catch (error) {
14236
+ const e = error;
14237
+ return {
14238
+ stdout: (e.stdout ?? "").trimEnd(),
14239
+ stderr: (e.stderr ?? "").trimEnd(),
14240
+ exitCode: e.status ?? 1
14241
+ };
14242
+ }
14243
+ };
14244
+ var gitContext = (workspaceRoot, paths = []) => {
14245
+ const cwd = workspaceRoot;
14246
+ let failure;
14247
+ const runHere = (args) => {
14248
+ const result = run(cwd, args);
14249
+ if (!failure && result.exitCode !== 0) {
14250
+ failure = { stderr: result.stderr, exitCode: result.exitCode };
14251
+ }
14252
+ return result.stdout;
14253
+ };
14254
+ const branch = runHere(["rev-parse", "--abbrev-ref", "HEAD"]) || "unknown";
14255
+ const status_short = runHere(["status", "--porcelain"]);
14256
+ const staged = [];
14257
+ const unstaged = [];
14258
+ const untracked = [];
14259
+ for (const line of status_short.split(`
14260
+ `).filter(Boolean)) {
14261
+ const code = line.slice(0, 2);
14262
+ const file = line.slice(3);
14263
+ if (code === "??") {
14264
+ untracked.push(file);
14265
+ } else {
14266
+ if (code[0] !== " " && code[0] !== "?")
14267
+ staged.push(file);
14268
+ if (code[1] !== " " && code[1] !== "?")
14269
+ unstaged.push(file);
14270
+ }
14271
+ }
14272
+ const pathArgs = paths.length ? ["--", ...paths] : [];
14273
+ const diff_stat = runHere(["diff", "--stat", ...pathArgs]);
14274
+ const cached_stat = runHere(["diff", "--cached", "--stat", ...pathArgs]);
14275
+ const stagedSet = new Set(staged);
14276
+ const unstagedSet = new Set(unstaged);
14277
+ const partial_staged = [...stagedSet].filter((f) => unstagedSet.has(f));
14278
+ return {
14279
+ workspace_root: cwd,
14280
+ branch,
14281
+ status_short,
14282
+ staged,
14283
+ unstaged,
14284
+ untracked,
14285
+ diff_stat: [diff_stat, cached_stat].filter(Boolean).join(`
14286
+ `),
14287
+ partial_staged: partial_staged.length > 0,
14288
+ partial_staged_files: partial_staged,
14289
+ ...failure ? { stderr: failure.stderr, exitCode: failure.exitCode } : {}
14290
+ };
14291
+ };
14292
+
14223
14293
  // packages/workit-core/src/core/workspaces.ts
14294
+ import { spawnSync as spawnSync8 } from "node:child_process";
14224
14295
  import { createHash as createHash8 } from "node:crypto";
14225
14296
  import { readFileSync as readFileSync4, realpathSync as realpathSync3 } from "node:fs";
14226
14297
  import path13 from "node:path";
@@ -14465,6 +14536,53 @@ var validateWorkspaceGlob = (glob) => {
14465
14536
  }
14466
14537
  return { ok: true };
14467
14538
  };
14539
+
14540
+ class WorkspaceConfigError extends Error {
14541
+ name = "WorkspaceConfigError";
14542
+ }
14543
+ var mainCheckouts = new Map;
14544
+ var mainCheckoutOf = (cwd) => {
14545
+ const cached = mainCheckouts.get(cwd);
14546
+ if (cached !== undefined)
14547
+ return cached;
14548
+ const env = { ...process.env };
14549
+ for (const name of ["GIT_DIR", "GIT_WORK_TREE", "GIT_COMMON_DIR", "GIT_INDEX_FILE"])
14550
+ delete env[name];
14551
+ const git = (args) => {
14552
+ const run = spawnSync8("git", args, {
14553
+ cwd,
14554
+ env,
14555
+ encoding: "utf8",
14556
+ timeout: 5000,
14557
+ windowsHide: true
14558
+ });
14559
+ return run.status === 0 ? run.stdout : null;
14560
+ };
14561
+ let main = null;
14562
+ const dirs = git(["rev-parse", "--path-format=absolute", "--git-dir", "--git-common-dir"]);
14563
+ const [gitDir, common] = (dirs ?? "").trim().split(/\r?\n/u);
14564
+ if (gitDir && common && path13.resolve(gitDir) !== path13.resolve(common)) {
14565
+ const listed = /^worktree (.+)$/mu.exec(git(["worktree", "list", "--porcelain"]) ?? "")?.[1];
14566
+ main = listed?.trim() || (path13.basename(common) === ".git" ? path13.dirname(common) : common);
14567
+ }
14568
+ mainCheckouts.set(cwd, main);
14569
+ return main;
14570
+ };
14571
+ var matchingEntries = (cwd, entries) => {
14572
+ const match = (where) => {
14573
+ const targets = [where, realpathOf(where)].map((value) => value.replaceAll("\\", "/"));
14574
+ return entries.filter((entry) => {
14575
+ const glob = entry.glob.replaceAll("\\", "/");
14576
+ const canonical = canonicalGlob(glob);
14577
+ return targets.some((target) => matchWorkspace(glob, target) || canonical !== glob && matchWorkspace(canonical, target));
14578
+ });
14579
+ };
14580
+ const direct = match(cwd);
14581
+ if (direct.length)
14582
+ return direct;
14583
+ const main = mainCheckoutOf(cwd);
14584
+ return main ? match(main) : direct;
14585
+ };
14468
14586
  var realpathOf = (p) => {
14469
14587
  const real = realpathSync3.native ?? realpathSync3;
14470
14588
  try {
@@ -14489,43 +14607,29 @@ var selectWorkspaceMatch = (matches, cwd, workspaceName) => {
14489
14607
  if (named.length === 1)
14490
14608
  return named[0];
14491
14609
  if (named.length > 1)
14492
- throw new Error(`ambiguous workspace ${JSON.stringify(workspaceName)} for ${cwd}`);
14610
+ throw new WorkspaceConfigError(`ambiguous workspace ${JSON.stringify(workspaceName)} for ${cwd}`);
14493
14611
  if (matches.length > 0) {
14494
- throw new Error(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}; matching choices: ${matches.map((entry) => entry.name).join(", ")}`);
14612
+ throw new WorkspaceConfigError(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}; matching choices: ${matches.map((entry) => entry.name).join(", ")}`);
14495
14613
  }
14496
- throw new Error(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}`);
14614
+ throw new WorkspaceConfigError(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}`);
14497
14615
  }
14498
14616
  if (matches.length < 2)
14499
14617
  return matches[0];
14500
14618
  const highestSpecificity = Math.max(...matches.map((entry) => globSpecificity(entry.glob)));
14501
14619
  const mostSpecific = matches.filter((entry) => globSpecificity(entry.glob) === highestSpecificity);
14502
14620
  if (mostSpecific.length > 1) {
14503
- throw new Error(`ambiguous workspace for ${cwd}; choose one of: ${mostSpecific.map((entry) => entry.name).join(", ")}`);
14621
+ throw new WorkspaceConfigError(`ambiguous workspace for ${cwd}; choose one of: ${mostSpecific.map((entry) => entry.name).join(", ")}`);
14504
14622
  }
14505
14623
  return mostSpecific[0];
14506
14624
  };
14507
14625
  var resolveWorkspaceFromEntries = (cwd, entries, workspaceName) => {
14508
- const targets = [cwd, realpathOf(cwd)].map((p) => p.replaceAll("\\", "/"));
14509
- const matches = [];
14510
- for (const ws of entries) {
14511
- const glob = ws.glob.replaceAll("\\", "/");
14512
- const canonical = canonicalGlob(glob);
14513
- let matched = false;
14514
- for (const target of targets) {
14515
- if (matchWorkspace(glob, target) || canonical !== glob && matchWorkspace(canonical, target)) {
14516
- matched = true;
14517
- break;
14518
- }
14519
- }
14520
- if (matched)
14521
- matches.push(ws);
14522
- }
14626
+ const matches = matchingEntries(cwd, entries);
14523
14627
  return selectWorkspaceMatch(matches, cwd, workspaceName) ?? null;
14524
14628
  };
14525
14629
  var resolveWorkspaceFrom = (cwd, dir, workspaceName) => {
14526
14630
  const result = readWorkspacesResult(dir);
14527
14631
  if (result.status === "malformed" || result.status === "invalid")
14528
- throw new Error(result.error);
14632
+ throw new WorkspaceConfigError(result.error);
14529
14633
  return resolveWorkspaceFromEntries(cwd, result.entries, workspaceName);
14530
14634
  };
14531
14635
  var runtimeWorkspacePolicySchema = (kind) => {
@@ -14557,31 +14661,26 @@ var matchRuntimeWorkspace = (cwd) => {
14557
14661
  } catch (error) {
14558
14662
  if (error.code === "ENOENT")
14559
14663
  return null;
14560
- throw new Error(`${file} could not be read: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
14664
+ throw new WorkspaceConfigError(`${file} could not be read: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
14561
14665
  }
14562
14666
  let parsed;
14563
14667
  try {
14564
14668
  parsed = JSON.parse(raw);
14565
14669
  } catch {
14566
- throw new Error(`${file} is not valid JSON`);
14670
+ throw new WorkspaceConfigError(`${file} is not valid JSON`);
14567
14671
  }
14568
14672
  const validated = runtimeWorkspaceIndexSchema.safeParse(parsed);
14569
14673
  if (!validated.success) {
14570
14674
  const detail = validated.error.issues.map((issue) => `${issue.path.map(String).join(".") || "workspaces"}: ${issue.message}`).join("; ");
14571
- throw new Error(`${file} has invalid workspace matching data: ${detail}`);
14675
+ throw new WorkspaceConfigError(`${file} has invalid workspace matching data: ${detail}`);
14572
14676
  }
14573
14677
  const entries = validated.data.workspaces;
14574
14678
  for (const entry of entries ?? []) {
14575
14679
  const glob = validateWorkspaceGlob(entry.glob);
14576
14680
  if (!glob.ok)
14577
- throw new Error(`${file} workspace ${entry.name}: ${glob.error}`);
14681
+ throw new WorkspaceConfigError(`${file} workspace ${entry.name}: ${glob.error}`);
14578
14682
  }
14579
- const targets = [cwd, realpathOf(cwd)].map((value) => value.replaceAll("\\", "/"));
14580
- const matches = (entries ?? []).filter((entry) => {
14581
- const glob = entry.glob.replaceAll("\\", "/");
14582
- const canonical = canonicalGlob(glob);
14583
- return targets.some((target) => matchWorkspace(glob, target) || canonical !== glob && matchWorkspace(canonical, target));
14584
- });
14683
+ const matches = matchingEntries(cwd, entries ?? []);
14585
14684
  const workspaceName = process.env.WORKFLOW_WORKSPACE_NAME?.trim() || undefined;
14586
14685
  const selected = selectWorkspaceMatch(matches, cwd, workspaceName);
14587
14686
  return selected ? { file, selected } : null;
@@ -14598,7 +14697,7 @@ var resolveRuntimeWorkspaceCandidate = (cwd, kind) => {
14598
14697
  const policy = runtimeWorkspacePolicySchema(kind).safeParse(selected);
14599
14698
  if (!policy.success) {
14600
14699
  const detail = policy.error.issues.map((issue) => `${issue.path.map(String).join(".") || "workspace"}: ${issue.message}`).join("; ");
14601
- throw new Error(`${file} has invalid ${kind} policy configuration: ${detail}`);
14700
+ throw new WorkspaceConfigError(`${file} has invalid ${kind} policy configuration: ${detail}`);
14602
14701
  }
14603
14702
  return policy.data;
14604
14703
  };
@@ -14609,10 +14708,10 @@ var resolveRuntimeWorkspacePolicy = (cwd, kind, requestedProfile) => {
14609
14708
  const key = kind === "branch" ? "branchPolicy" : "commitPolicy";
14610
14709
  const profileName = requestedProfile?.trim() || candidate.defaultProfile;
14611
14710
  if (candidate.defaultProfile && !Object.hasOwn(candidate.profiles ?? {}, candidate.defaultProfile))
14612
- throw new Error(`workspace ${JSON.stringify(candidate.name)} has no profile ${JSON.stringify(candidate.defaultProfile)}`);
14711
+ throw new WorkspaceConfigError(`workspace ${JSON.stringify(candidate.name)} has no profile ${JSON.stringify(candidate.defaultProfile)}`);
14613
14712
  const profile = profileName ? candidate.profiles?.[profileName] : undefined;
14614
14713
  if (profileName && !profile)
14615
- throw new Error(`workspace ${JSON.stringify(candidate.name)} has no profile ${JSON.stringify(profileName)}`);
14714
+ throw new WorkspaceConfigError(`workspace ${JSON.stringify(candidate.name)} has no profile ${JSON.stringify(profileName)}`);
14616
14715
  const profilePolicy = profile?.[key];
14617
14716
  const workspacePolicy = candidate[key];
14618
14717
  return {
@@ -14625,18 +14724,18 @@ function workspaceDefaultTarget(cwd, globalDefault) {
14625
14724
  const wp = ws?.branchPolicy ?? {};
14626
14725
  const hasWorkspacePolicy = typeof wp.preset === "string" && Object.hasOwn(PRESETS, wp.preset);
14627
14726
  const selected = resolveRuntimeWorkspacePolicy(cwd, "branch", process.env.WORKFLOW_PROFILE?.trim() || undefined);
14628
- const policyDefault = resolveBranchPolicy(readConfig(), selected.policy ? { branchPolicy: selected.policy } : null).defaultTargetBranch;
14727
+ const policyDefault = resolveBranchPolicy(readConfig(), selected.policy ? { branchPolicy: selected.policy } : null, () => repoBranchPreset(cwd)).defaultTargetBranch;
14629
14728
  return String(ws?.vcs?.defaultTargetBranch ?? (hasWorkspacePolicy ? policyDefault : globalDefault ?? policyDefault) ?? "develop");
14630
14729
  }
14631
14730
 
14632
14731
  // packages/workit-core/src/core/vcs-config.ts
14633
14732
  import fs12 from "node:fs";
14634
14733
  import path14 from "node:path";
14635
- import { spawnSync as spawnSync8 } from "node:child_process";
14734
+ import { spawnSync as spawnSync10 } from "node:child_process";
14636
14735
 
14637
14736
  // packages/workit-core/src/core/release-tracks.ts
14638
14737
  import { createHash as createHash9 } from "node:crypto";
14639
- import { spawnSync as spawnSync7 } from "node:child_process";
14738
+ import { spawnSync as spawnSync9 } from "node:child_process";
14640
14739
  class ReleaseTrackError extends Error {
14641
14740
  }
14642
14741
  var KNOWN_FIELDS = new Set([
@@ -14921,7 +15020,7 @@ function resolveReleaseTrack(input) {
14921
15020
  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 ")}`);
14922
15021
  }
14923
15022
  var git4 = (cwd, args) => {
14924
- const run = spawnSync7("git", args, {
15023
+ const run = spawnSync9("git", args, {
14925
15024
  cwd,
14926
15025
  encoding: "utf8",
14927
15026
  timeout: 20000,
@@ -15036,7 +15135,7 @@ function resolveTrackFor(cwd, options) {
15036
15135
  var workspacesPath = () => path14.join(configDir(), "workspaces.json");
15037
15136
  var vcsCwd = (cwd) => cwd ?? process.env.WORKFLOW_WORKSPACE_ROOT ?? process.cwd();
15038
15137
  var remoteProvider = (cwd) => {
15039
- const r = spawnSync8("git", ["remote", "get-url", "origin"], { cwd, encoding: "utf8" });
15138
+ const r = spawnSync10("git", ["remote", "get-url", "origin"], { cwd, encoding: "utf8" });
15040
15139
  if (r.status !== 0)
15041
15140
  return null;
15042
15141
  const url = (r.stdout ?? "").trim();
@@ -15073,7 +15172,7 @@ var remoteEndpoint = (remote) => {
15073
15172
  var configuredSshEndpoint = (host) => {
15074
15173
  if (host.startsWith("-"))
15075
15174
  return null;
15076
- const resolved = spawnSync8("ssh", ["-G", host], {
15175
+ const resolved = spawnSync10("ssh", ["-G", host], {
15077
15176
  encoding: "utf8",
15078
15177
  timeout: 5000,
15079
15178
  maxBuffer: 1024 * 1024,
@@ -15246,7 +15345,7 @@ function mergedPrStyle(limit = 6, cwd) {
15246
15345
  `).filter((l) => l.startsWith("## ")).map((l) => l.trim()),
15247
15346
  descriptionPreview: desc.slice(0, 600)
15248
15347
  });
15249
- const remoteResult = spawnSync8("git", ["remote", "get-url", "--push", "--all", "origin"], {
15348
+ const remoteResult = spawnSync10("git", ["remote", "get-url", "--push", "--all", "origin"], {
15250
15349
  cwd,
15251
15350
  encoding: "utf8"
15252
15351
  });
@@ -15262,7 +15361,7 @@ function mergedPrStyle(limit = 6, cwd) {
15262
15361
  if (!hostingApiHostMatches(remote, host))
15263
15362
  return { ok: false, error: "PR style target does not match the provider host" };
15264
15363
  if (provider === "gitlab") {
15265
- const run = (args) => spawnSync8("glab", ["api", ...args], {
15364
+ const run = (args) => spawnSync10("glab", ["api", ...args], {
15266
15365
  cwd,
15267
15366
  encoding: "utf8",
15268
15367
  env
@@ -15282,7 +15381,7 @@ function mergedPrStyle(limit = 6, cwd) {
15282
15381
  });
15283
15382
  }
15284
15383
  } else if (provider === "github") {
15285
- const r = spawnSync8("gh", [
15384
+ const r = spawnSync10("gh", [
15286
15385
  "pr",
15287
15386
  "list",
15288
15387
  "--repo",
@@ -15343,7 +15442,7 @@ function effectiveWorkspacePolicy(workspaceRoot, kind, profileName) {
15343
15442
  const selected = resolveRuntimeWorkspacePolicy(workspaceRoot, kind, profileName?.trim() || process.env.WORKFLOW_PROFILE?.trim() || undefined);
15344
15443
  const config = readConfig();
15345
15444
  return kind === "branch" ? {
15346
- branchPolicy: withReleaseTracks(workspaceRoot, resolveBranchPolicy(config, selected.policy ? { branchPolicy: selected.policy } : null)),
15445
+ branchPolicy: withReleaseTracks(workspaceRoot, resolveBranchPolicy(config, selected.policy ? { branchPolicy: selected.policy } : null, () => repoBranchPreset(workspaceRoot))),
15347
15446
  provenance: { branchPolicy: selected.source }
15348
15447
  } : {
15349
15448
  commitPolicy: resolveCommitPolicy(config, selected.policy ? { commitPolicy: selected.policy } : null),
@@ -17353,7 +17452,7 @@ class WorkitCore {
17353
17452
  }
17354
17453
  }
17355
17454
  // packages/workit-core/src/core/repo-context.ts
17356
- import { spawnSync as spawnSync9 } from "node:child_process";
17455
+ import { spawnSync as spawnSync11 } from "node:child_process";
17357
17456
  import { existsSync as existsSync6, readFileSync as readFileSync5, readdirSync as readdirSync4 } from "node:fs";
17358
17457
  import path16 from "node:path";
17359
17458
  var isSafeContextRange = (value) => value.length <= 4096 && (() => {
@@ -17382,7 +17481,7 @@ var invalidRange = (cwd) => ({
17382
17481
  cwd
17383
17482
  });
17384
17483
  var runGit = (cwd, args) => {
17385
- const result = spawnSync9("git", args, { cwd, encoding: "utf8" });
17484
+ const result = spawnSync11("git", args, { cwd, encoding: "utf8" });
17386
17485
  return {
17387
17486
  stdout: (result.stdout ?? "").trimEnd(),
17388
17487
  stderr: (result.stderr ?? "").trimEnd(),
@@ -17823,12 +17922,12 @@ function releaseNotesContext(root, rangeOrTag) {
17823
17922
  }
17824
17923
 
17825
17924
  // packages/workit-core/src/core/tracker-issues.ts
17826
- import { spawnSync as spawnSync11 } from "node:child_process";
17925
+ import { spawnSync as spawnSync13 } from "node:child_process";
17827
17926
 
17828
17927
  // packages/workit-core/src/core/pr-create.ts
17829
17928
  import fs13 from "node:fs";
17830
17929
  import path17 from "node:path";
17831
- import { spawnSync as spawnSync10 } from "node:child_process";
17930
+ import { spawnSync as spawnSync12 } from "node:child_process";
17832
17931
  // packages/workit-core/src/forge/pr-body.ts
17833
17932
  function parseGhIssue(value) {
17834
17933
  const m = /issues\/(\d+)/.exec(value);
@@ -17853,7 +17952,7 @@ function whichOnPath(tool) {
17853
17952
  }
17854
17953
  var hostingCliAvailable = (provider) => whichOnPath(provider === "gitlab" ? "glab" : "gh") !== null;
17855
17954
  var pushRemote = (cwd) => {
17856
- const result = spawnSync10("git", ["remote", "get-url", "--push", "--all", "origin"], {
17955
+ const result = spawnSync12("git", ["remote", "get-url", "--push", "--all", "origin"], {
17857
17956
  cwd,
17858
17957
  encoding: "utf8"
17859
17958
  });
@@ -17884,7 +17983,7 @@ var defaultCli = (bin, available) => {
17884
17983
  if (!available)
17885
17984
  return null;
17886
17985
  return (args, root) => {
17887
- const out = spawnSync11(bin, args, {
17986
+ const out = spawnSync13(bin, args, {
17888
17987
  cwd: root,
17889
17988
  encoding: "utf8",
17890
17989
  env: { ...process.env, PATH: process.env.PATH ?? "" }
@@ -18460,7 +18559,7 @@ function resolveInside(root, candidate) {
18460
18559
  }
18461
18560
  function run2(root, executable, args, env = {}) {
18462
18561
  const cwd = realpathSync5(root);
18463
- const result = spawnSync12(executable, args, {
18562
+ const result = spawnSync14(executable, args, {
18464
18563
  cwd,
18465
18564
  encoding: "utf8",
18466
18565
  env: { ...process.env, ...env }
@@ -18710,11 +18809,11 @@ var segmentsOf = (command) => {
18710
18809
  flushSegment();
18711
18810
  return segments;
18712
18811
  };
18713
- var PREFIXES = new Set(["sudo", "command", "env", "nohup", "time", "exec", "xargs"]);
18812
+ var PREFIXES2 = new Set(["sudo", "command", "env", "nohup", "time", "exec", "xargs"]);
18714
18813
  var operands = (words) => words.filter((item) => !item.startsWith("-"));
18715
18814
  var editsOf = (input) => {
18716
18815
  let words = input;
18717
- while (words.length && (PREFIXES.has(words[0]) || /^\w+=/.test(words[0])))
18816
+ while (words.length && (PREFIXES2.has(words[0]) || /^\w+=/.test(words[0])))
18718
18817
  words = words.slice(1);
18719
18818
  const [verb, ...args] = words;
18720
18819
  const name = (verb?.split(/[\\/]/).at(-1) ?? "").toLowerCase();
@@ -19081,74 +19180,12 @@ var ensureHygieneFiles = (root, opts) => {
19081
19180
  // packages/workit-core/src/core/init.ts
19082
19181
  import fs15 from "node:fs";
19083
19182
  import path25 from "node:path";
19084
- import { spawnSync as spawnSync14 } from "node:child_process";
19183
+ import { spawnSync as spawnSync15 } from "node:child_process";
19085
19184
 
19086
19185
  // packages/workit-core/src/core/workspace-branch-policy.ts
19087
19186
  import { mkdirSync as mkdirSync4, readFileSync as readFileSync8, renameSync as renameSync3, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "node:fs";
19088
19187
  import path24 from "node:path";
19089
19188
  import { isDeepStrictEqual } from "node:util";
19090
-
19091
- // packages/workit-core/src/core/branch-policy.ts
19092
- import { spawnSync as spawnSync13 } from "node:child_process";
19093
- var PREFIXES2 = {
19094
- feature: "feature/*",
19095
- bugfix: "bugfix/*",
19096
- release: "release/*",
19097
- hotfix: "hotfix/*"
19098
- };
19099
- var detectBranchPolicy = (workspaceRoot) => {
19100
- const branchExists = (name) => {
19101
- const r = spawnSync13("git", ["branch", "--list", name], {
19102
- cwd: workspaceRoot,
19103
- encoding: "utf8"
19104
- });
19105
- return r.status === 0 && (r.stdout ?? "").trim() !== "";
19106
- };
19107
- const develop = branchExists("develop");
19108
- const main = branchExists("main");
19109
- const master = branchExists("master");
19110
- const root = main ? "main" : master ? "master" : null;
19111
- if (develop) {
19112
- return {
19113
- preset: "gitflow",
19114
- developBranch: "develop",
19115
- integration: "merge",
19116
- protected: root ? [root, "develop"] : ["develop"],
19117
- allowed: [...PRESETS.gitflow.allowed],
19118
- prefixes: PREFIXES2
19119
- };
19120
- }
19121
- if (root === "main") {
19122
- return {
19123
- preset: "github-flow",
19124
- developBranch: null,
19125
- integration: "pr",
19126
- protected: [root],
19127
- allowed: ["*"],
19128
- prefixes: PREFIXES2
19129
- };
19130
- }
19131
- if (root === "master") {
19132
- return {
19133
- preset: "trunk-based",
19134
- developBranch: null,
19135
- integration: "pr",
19136
- protected: [root],
19137
- allowed: ["*"],
19138
- prefixes: PREFIXES2
19139
- };
19140
- }
19141
- return {
19142
- preset: "gitflow",
19143
- developBranch: null,
19144
- integration: "merge",
19145
- protected: [],
19146
- allowed: [],
19147
- prefixes: PREFIXES2
19148
- };
19149
- };
19150
-
19151
- // packages/workit-core/src/core/workspace-branch-policy.ts
19152
19189
  var readFileSafe = (p) => {
19153
19190
  try {
19154
19191
  return readFileSync8(p, "utf8");
@@ -19266,7 +19303,7 @@ var resolveInitProvider = (cwd) => {
19266
19303
  return env.toLowerCase();
19267
19304
  const root = cwd ?? process.env.WORKFLOW_WORKSPACE_ROOT ?? process.cwd();
19268
19305
  try {
19269
- const out = spawnSync14("git", ["remote", "get-url", "origin"], {
19306
+ const out = spawnSync15("git", ["remote", "get-url", "origin"], {
19270
19307
  cwd: root,
19271
19308
  encoding: "utf8"
19272
19309
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainervirus/workit-opencode",
3
- "version": "8.0.1",
3
+ "version": "8.1.1",
4
4
  "private": false,
5
5
  "description": "Workit OpenCode plugin — native tools, adaptive policy, and sixteen method skills",
6
6
  "keywords": [
@@ -39,7 +39,7 @@
39
39
  "typecheck": "tsc --noEmit"
40
40
  },
41
41
  "dependencies": {
42
- "@brainervirus/workit-core": "^8.0.1"
42
+ "@brainervirus/workit-core": "^8.1.1"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@opencode/plugin": "2.0.18"