@brainervirus/workit-claude-code 8.0.0 → 8.1.0

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