@brainervirus/workit-cursor 8.18.0 → 8.19.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.
@@ -2,7 +2,7 @@
2
2
  "name": "workit",
3
3
  "displayName": "Workit",
4
4
  "description": "Adaptive Workit workflow with shared MCP tools and native Cursor hooks",
5
- "version": "8.18.0",
5
+ "version": "8.19.0",
6
6
  "author": {
7
7
  "name": "Cristhofer Pincetti"
8
8
  },
@@ -10331,6 +10331,221 @@ var init_vcs_config = __esm(() => {
10331
10331
  TRACKERS = new Set(["github", "gitlab", "youtrack"]);
10332
10332
  });
10333
10333
 
10334
+ // packages/workit-core/src/core/commit-flavors.ts
10335
+ var init_commit_flavors = () => {};
10336
+
10337
+ // packages/workit-core/src/core/git.ts
10338
+ var init_git = () => {};
10339
+
10340
+ // packages/workit-core/src/core/branch.ts
10341
+ import { createHash as createHash6 } from "node:crypto";
10342
+ function effectiveWorkspacePolicy(workspaceRoot, kind, profileName) {
10343
+ const selected = resolveRuntimeWorkspacePolicy(workspaceRoot, kind, profileName?.trim() || process.env.WORKFLOW_PROFILE?.trim() || undefined);
10344
+ const config = readConfig();
10345
+ return kind === "branch" ? {
10346
+ branchPolicy: withReleaseTracks(workspaceRoot, resolveBranchPolicy(config, selected.policy ? { branchPolicy: selected.policy } : null, () => repoBranchPreset(workspaceRoot))),
10347
+ provenance: { branchPolicy: selected.source }
10348
+ } : {
10349
+ commitPolicy: resolveCommitPolicy(config, selected.policy ? { commitPolicy: selected.policy } : null),
10350
+ provenance: { commitPolicy: selected.source }
10351
+ };
10352
+ }
10353
+ var withReleaseTracks = (workspaceRoot, policy) => {
10354
+ const read = workspaceReleaseTracks(workspaceRoot);
10355
+ if (read.error)
10356
+ throw new ReleaseTrackError(read.error);
10357
+ if (read.tracks.length === 0 && read.protectedBranches.length === 0)
10358
+ return policy;
10359
+ const known = new Set(policy.allowed.map((pattern) => pattern.source));
10360
+ const allowed = [...policy.allowed];
10361
+ for (const glob of read.tracks.flatMap((track) => Object.values(track.naming).map(namingGlob))) {
10362
+ const pattern = branchGlobPattern(glob);
10363
+ if (!known.has(pattern.source)) {
10364
+ known.add(pattern.source);
10365
+ allowed.push(pattern);
10366
+ }
10367
+ }
10368
+ return {
10369
+ ...policy,
10370
+ allowed,
10371
+ protected: new Set([
10372
+ ...policy.protected,
10373
+ ...[...trackBranches(read.tracks), ...read.protectedBranches].map((name) => name.toLowerCase())
10374
+ ])
10375
+ };
10376
+ }, KIND_SYNONYMS, allowedKinds = (allowed) => [
10377
+ ...new Set(allowed.map((pattern) => /^\^([\w.-]+)\\?\/\.\*\$$/u.exec(pattern.source)?.[1]?.toLowerCase()).filter((kind) => Boolean(kind)))
10378
+ ], editDistance = (a, b) => {
10379
+ const row = Array.from({ length: b.length + 1 }, (_, index) => index);
10380
+ for (let i = 1;i <= a.length; i++) {
10381
+ let previous = row[0];
10382
+ row[0] = i;
10383
+ for (let j = 1;j <= b.length; j++) {
10384
+ const saved = row[j];
10385
+ row[j] = Math.min(row[j] + 1, row[j - 1] + 1, previous + (a[i - 1] === b[j - 1] ? 0 : 1));
10386
+ previous = saved;
10387
+ }
10388
+ }
10389
+ return row[b.length];
10390
+ }, suggestBranchName = (name, kinds) => {
10391
+ if (!kinds.length)
10392
+ return null;
10393
+ const slash = name.indexOf("/");
10394
+ const prefix = slash > 0 ? name.slice(0, slash).toLowerCase() : "";
10395
+ const rest = (slash > 0 ? name.slice(slash + 1) : name) || "name";
10396
+ const synonym = KIND_SYNONYMS[prefix];
10397
+ const near = kinds.map((kind) => ({ kind, distance: editDistance(prefix, kind) })).filter((entry) => prefix && entry.distance <= 2).toSorted((a, b) => a.distance - b.distance)[0]?.kind;
10398
+ const kind = (synonym && kinds.includes(synonym) ? synonym : null) ?? near ?? (kinds.includes("feature") ? "feature" : kinds[0]);
10399
+ return `${kind}/${rest}`;
10400
+ }, kindList = (kinds) => kinds.map((kind) => `${kind}/`).join(", "), aliasNote = (kinds) => {
10401
+ const notes = [
10402
+ ["fix", "bugfix"],
10403
+ ["chore", "feature"]
10404
+ ].filter(([, kind]) => kinds.includes(kind)).map(([alias, kind]) => `${alias}/ is ${kind}/`);
10405
+ return notes.length ? ` (${notes.join(", ")})` : "";
10406
+ }, validateBranchNamePolicy = (name, policy, source) => {
10407
+ const allowed = policy.allowed.map((pattern) => `/${pattern.source}/${pattern.flags}`);
10408
+ const kinds = allowedKinds(policy.allowed);
10409
+ if (policy.protected.has(name.toLowerCase())) {
10410
+ const correction = kinds.length ? `choose a non-protected branch of an allowed kind (${kindList(kinds)}), e.g. ${kinds[0]}/<slug>: workit git branch --kind ${kinds[0]} --slug <slug>` : `choose a non-protected branch matching one of: ${allowed.join(", ")}`;
10411
+ return {
10412
+ ok: false,
10413
+ rule: "protected_ref",
10414
+ source,
10415
+ attempted: name,
10416
+ correction,
10417
+ error: `protected_ref: branch ${JSON.stringify(name)} is protected by ${source}; ${correction}`
10418
+ };
10419
+ }
10420
+ if (!policy.allowed.some((pattern) => pattern.test(name))) {
10421
+ const suggestion = suggestBranchName(name, kinds);
10422
+ const correction = suggestion && policy.allowed.some((pattern) => pattern.test(suggestion)) ? `use ${JSON.stringify(suggestion)}; the allowed kinds are ${kindList(kinds)} (workit git branch ${suggestion})` : `choose a branch matching one of: ${allowed.join(", ")}`;
10423
+ return {
10424
+ ok: false,
10425
+ rule: "allowed_pattern",
10426
+ source,
10427
+ attempted: name,
10428
+ correction,
10429
+ error: `allowed_pattern: branch ${JSON.stringify(name)} violates ${source} policy; ${correction}`
10430
+ };
10431
+ }
10432
+ return { ok: true };
10433
+ }, branchPolicySnapshotFor = (workspaceRoot) => {
10434
+ const resolved = effectiveWorkspacePolicy(workspaceRoot, "branch");
10435
+ const branchPolicy = resolved.branchPolicy;
10436
+ const source = resolved.provenance.branchPolicy;
10437
+ const allowed = branchPolicy.allowed.map((pattern) => `${pattern.source}/${pattern.flags}`).toSorted();
10438
+ const protectedRefs = [...branchPolicy.protected].map((name) => name.toLowerCase()).toSorted();
10439
+ const fingerprint = createHash6("sha256").update(JSON.stringify({ allowed, protectedRefs, source })).digest("hex");
10440
+ return {
10441
+ branchPolicy,
10442
+ namePolicy: { allowed: branchPolicy.allowed, protected: branchPolicy.protected },
10443
+ source,
10444
+ fingerprint
10445
+ };
10446
+ }, validateBranchNameFor = (workspaceRoot, name) => {
10447
+ try {
10448
+ const resolved = branchPolicySnapshotFor(workspaceRoot);
10449
+ return validateBranchNamePolicy(name, resolved.namePolicy, resolved.source);
10450
+ } catch (error) {
10451
+ const correction = "repair or select a valid workspace policy before creating a branch";
10452
+ return {
10453
+ ok: false,
10454
+ rule: "policy_unavailable",
10455
+ source: "workspaces.json",
10456
+ attempted: name,
10457
+ correction,
10458
+ error: `policy_unavailable: cannot validate branch ${JSON.stringify(name)} because ${error instanceof Error ? error.message : String(error)}; ${correction}`
10459
+ };
10460
+ }
10461
+ }, resolveBranchPolicyFor = (workspaceRoot, profileName) => effectiveWorkspacePolicy(workspaceRoot, "branch", profileName).branchPolicy, gitFlowOf = (root, integration) => {
10462
+ try {
10463
+ if (resolveBranchPolicyFor(root).preset !== "gitflow")
10464
+ return null;
10465
+ const selected = resolveRuntimeWorkspacePolicy(root, "branch", process.env.WORKFLOW_PROFILE?.trim() || undefined).policy;
10466
+ const names = branchNames(root);
10467
+ const production = productionBranchOf(names);
10468
+ const develop = selected?.developBranch?.trim() || (integration && integration.toLowerCase() !== production ? integration : "develop");
10469
+ return { develop, production, developExists: names.has(develop) };
10470
+ } catch {
10471
+ return null;
10472
+ }
10473
+ }, releaseBranchesOf = (cwd) => {
10474
+ try {
10475
+ const resolved = resolveBranchPolicyFor(cwd);
10476
+ const flow = resolved.preset === "gitflow" ? gitFlowOf(cwd) : null;
10477
+ return {
10478
+ preset: resolved.preset,
10479
+ branches: flow ? [flow.production, flow.develop] : [],
10480
+ production: flow ? flow.production : resolved.defaultTargetBranch
10481
+ };
10482
+ } catch {
10483
+ return { preset: "unknown", branches: [], production: null };
10484
+ }
10485
+ }, releaseBranch = (cwd, branch) => releaseBranchesOf(cwd).branches.some((name) => name.toLowerCase() === branch.toLowerCase()), branchGuidance = (cwd) => {
10486
+ try {
10487
+ const patterns = branchPolicySnapshotFor(cwd).namePolicy.allowed;
10488
+ const kinds = allowedKinds(patterns);
10489
+ const kindShaped = new Set(kinds.map((kind) => branchGlobPattern(`${kind}/*`).source));
10490
+ const anyName = patterns.some((pattern) => pattern.source === "^.*$");
10491
+ const others = patterns.filter((pattern) => !kindShaped.has(pattern.source)).map((pattern) => globOf(pattern));
10492
+ const allowed = anyName ? "Any non-protected branch name is allowed here." : `${kinds.length ? `Allowed branch kinds here: ${kindList(kinds)}${aliasNote(kinds)}` : "Allowed branch names here:"}${others.length ? `${kinds.length ? "; also" : ""} names matching ${others.join(", ")}` : ""}; anything else is denied.`;
10493
+ const resolved = vcsConfig("resolve", cwd);
10494
+ const integration = resolved.ok === false ? null : String(resolved.defaultTargetBranch ?? "") || null;
10495
+ const flow = resolved.releaseTrack?.track ? null : gitFlowOf(cwd, integration);
10496
+ if (flow?.developExists)
10497
+ return `${allowed} git-flow: feature/, bugfix/ and release/ start from origin/${flow.develop}, hotfix/ from origin/${flow.production}; feature/ and bugfix/ land on ${flow.develop}, release/ and hotfix/ on ${flow.production}.`;
10498
+ const names = branchNames(cwd);
10499
+ const configured = String(resolved.baseBranch ?? integration ?? "") || null;
10500
+ const trunk = productionBranchOf(names);
10501
+ const base = configured && names.has(configured) ? `Branch from origin/${configured}.` : names.has(trunk) ? `Branch from origin/${trunk}${configured ? ` (the default target ${configured} does not exist here)` : ""}.` : "No base branch exists here yet; pass the base explicitly.";
10502
+ return `${allowed} ${base}`;
10503
+ } catch {
10504
+ return null;
10505
+ }
10506
+ }, globOf = (pattern) => pattern.source.replace(/^\^|\$$/gu, "").replaceAll(".*", "*").replace(/\\(.)/gu, "$1"), policy = (root) => resolveBranchPolicyFor(root), isProtected = (root, name) => policy(root).protected.has(name.toLowerCase()), isProtectedTarget = (root, name) => {
10507
+ try {
10508
+ return isProtected(root, name);
10509
+ } catch {
10510
+ return true;
10511
+ }
10512
+ };
10513
+ var init_branch = __esm(() => {
10514
+ init_branch_policy();
10515
+ init_commit_flavors();
10516
+ init_git();
10517
+ init_config();
10518
+ init_workspaces();
10519
+ init_vcs_config();
10520
+ init_release_tracks();
10521
+ KIND_SYNONYMS = {
10522
+ fix: "bugfix",
10523
+ fixes: "bugfix",
10524
+ bug: "bugfix",
10525
+ bugs: "bugfix",
10526
+ bugfixes: "bugfix",
10527
+ feat: "feature",
10528
+ features: "feature",
10529
+ chore: "feature",
10530
+ docs: "feature",
10531
+ doc: "feature",
10532
+ refactor: "feature",
10533
+ test: "feature",
10534
+ tests: "feature",
10535
+ ci: "feature",
10536
+ build: "feature",
10537
+ perf: "feature",
10538
+ style: "feature",
10539
+ deps: "feature",
10540
+ task: "feature",
10541
+ enhancement: "feature",
10542
+ hot: "hotfix",
10543
+ hotfixes: "hotfix",
10544
+ releases: "release",
10545
+ rel: "release"
10546
+ };
10547
+ });
10548
+
10334
10549
  // packages/workit-core/src/core/logger.ts
10335
10550
  import os3 from "node:os";
10336
10551
  import path6 from "node:path";
@@ -10392,7 +10607,7 @@ var init_logger = __esm(() => {
10392
10607
  });
10393
10608
 
10394
10609
  // packages/workit-core/src/host-session.ts
10395
- import { createHash as createHash6, randomBytes, timingSafeEqual } from "node:crypto";
10610
+ import { createHash as createHash7, randomBytes, timingSafeEqual } from "node:crypto";
10396
10611
  import fs5 from "node:fs";
10397
10612
  import path7 from "node:path";
10398
10613
  function hostSessionFromEnv(env) {
@@ -10467,6 +10682,21 @@ function recordIssuedSession(cwd, lead, issued) {
10467
10682
  return null;
10468
10683
  }
10469
10684
  }
10685
+ function judgeBranch(cwd) {
10686
+ const branch = currentBranch(cwd);
10687
+ return branch && !isProtectedTarget(cwd, branch) ? branch : null;
10688
+ }
10689
+ function verdictCommand(options) {
10690
+ const kind = options.judge === "verifier" ? "<live|unit>" : options.judge === "reviewer" ? "review" : "<live|unit|review>";
10691
+ return [
10692
+ "workit ledger verdict <verified|failed|blocked>",
10693
+ `--kind ${kind}`,
10694
+ `--branch ${options.branch ?? "<branch>"}`,
10695
+ options.session ? `--session ${options.session}` : null,
10696
+ options.token ? `--token=${options.token}` : null,
10697
+ '--how "<what you ran and saw>"'
10698
+ ].filter(Boolean).join(" ");
10699
+ }
10470
10700
  function pruneIssued(dir, own, tokens) {
10471
10701
  try {
10472
10702
  const entries = fs5.readdirSync(dir);
@@ -10488,7 +10718,7 @@ function issuedBinding(cwd, claimed) {
10488
10718
  return null;
10489
10719
  return leadBound ? "token" : "legacy";
10490
10720
  }
10491
- var HOST_SESSION_VARS, family = (host) => host?.replace(/_(?:cli|desktop)$/, "") ?? null, ISSUED_PER_LEAD = 64, ISSUED_SESSIONS_MARKER = "workit-issued-sessions/3", hash = (value) => createHash6("sha256").update(value).digest("hex").slice(0, 32), userIssuedRoot = () => path7.join(resolveStateDir(), "issued"), userTokenRoot = () => path7.join(resolveStateDir(), "issued-tokens"), safeList = (dir) => {
10721
+ var HOST_SESSION_VARS, family = (host) => host?.replace(/_(?:cli|desktop)$/, "") ?? null, ISSUED_PER_LEAD = 64, ISSUED_SESSIONS_MARKER = "workit-issued-sessions/3", hash = (value) => createHash7("sha256").update(value).digest("hex").slice(0, 32), userIssuedRoot = () => path7.join(resolveStateDir(), "issued"), userTokenRoot = () => path7.join(resolveStateDir(), "issued-tokens"), safeList = (dir) => {
10492
10722
  try {
10493
10723
  return fs5.readdirSync(dir);
10494
10724
  } catch {
@@ -10498,7 +10728,7 @@ var HOST_SESSION_VARS, family = (host) => host?.replace(/_(?:cli|desktop)$/, "")
10498
10728
  try {
10499
10729
  fs5.rmdirSync(dir);
10500
10730
  } catch {}
10501
- }, tokenHash = (token) => createHash6("sha256").update(token).digest("hex"), issuedRecord = (cwd, claimed) => {
10731
+ }, tokenHash = (token) => createHash7("sha256").update(token).digest("hex"), issuedRecord = (cwd, claimed) => {
10502
10732
  const cut = claimed.lastIndexOf(":");
10503
10733
  if (cut <= 0)
10504
10734
  return null;
@@ -10521,7 +10751,9 @@ var HOST_SESSION_VARS, family = (host) => host?.replace(/_(?:cli|desktop)$/, "")
10521
10751
  }
10522
10752
  }, OWN_CHILD_SHELL;
10523
10753
  var init_host_session = __esm(() => {
10754
+ init_branch();
10524
10755
  init_logger();
10756
+ init_rev();
10525
10757
  init_paths();
10526
10758
  HOST_SESSION_VARS = [
10527
10759
  ["OPENCODE_SESSION_ID", () => "opencode"],
@@ -10537,7 +10769,7 @@ var init_host_session = __esm(() => {
10537
10769
 
10538
10770
  // packages/workit-core/src/ledger.ts
10539
10771
  import { spawnSync as spawnSync8 } from "node:child_process";
10540
- import { createHash as createHash7, randomBytes as randomBytes2 } from "node:crypto";
10772
+ import { createHash as createHash8, randomBytes as randomBytes2 } from "node:crypto";
10541
10773
  import fs6 from "node:fs";
10542
10774
  import path8 from "node:path";
10543
10775
  function resolveCommit(cwd, ref) {
@@ -10593,7 +10825,7 @@ function diffHash(cwd, base, head) {
10593
10825
  ], GIT_TIMEOUTS.worktree);
10594
10826
  if (!diff.ok || !diff.stdout)
10595
10827
  return null;
10596
- const hash = createHash7("sha256");
10828
+ const hash = createHash8("sha256");
10597
10829
  for (const line of diff.stdout.split(`
10598
10830
  `)) {
10599
10831
  if (line.startsWith("index "))
@@ -11196,7 +11428,7 @@ var LEDGER_VERSION = 1, MAX_LINE_BYTES = 4096, PASSING, FAILING, STRONG_RESULTS,
11196
11428
  } catch {}
11197
11429
  }
11198
11430
  return null;
11199
- }, ledgerLock, sha2562 = (text) => createHash7("sha256").update(text).digest("hex"), chainHash = (prevHash, body) => sha2562(`${prevHash ?? ""}
11431
+ }, ledgerLock, sha2562 = (text) => createHash8("sha256").update(text).digest("hex"), chainHash = (prevHash, body) => sha2562(`${prevHash ?? ""}
11200
11432
  ${body}`), TAIL_BYTES, lastLine = (fd, size) => {
11201
11433
  for (let span = Math.min(size, TAIL_BYTES);span > 0; span = Math.min(size, span * 2)) {
11202
11434
  const buffer = Buffer.alloc(span);
@@ -13162,7 +13394,7 @@ var isPlainObject2 = (value) => typeof value === "object" && value !== null && !
13162
13394
  });
13163
13395
 
13164
13396
  // packages/workit-core/src/store/reduce.ts
13165
- import { createHash as createHash8 } from "node:crypto";
13397
+ import { createHash as createHash9 } from "node:crypto";
13166
13398
  function reduce(state, event, blobs) {
13167
13399
  const data = event.data;
13168
13400
  const known = KNOWN_TYPES.has(event.type);
@@ -13229,7 +13461,7 @@ function eventType(before, after) {
13229
13461
  return "task.noted";
13230
13462
  return "task.updated";
13231
13463
  }
13232
- var OPENING_TYPES, KNOWN_TYPES, isObject5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), isKey = (value) => isObject5(value) && typeof value.key === "string" && (value.kind === "branch" || value.kind === "detached" || value.kind === "dir") && (value.branch === null || typeof value.branch === "string"), BLOB_REF = "$blob", blobRef = (value) => isObject5(value) && Object.keys(value).length === 1 && typeof value[BLOB_REF] === "string" && /^[0-9a-f]{64}$/.test(value[BLOB_REF]) ? value[BLOB_REF] : null, blobDigest = (value) => createHash8("sha256").update(JSON.stringify(value)).digest("hex"), toBlob = (value, blobs) => {
13464
+ var OPENING_TYPES, KNOWN_TYPES, isObject5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), isKey = (value) => isObject5(value) && typeof value.key === "string" && (value.kind === "branch" || value.kind === "detached" || value.kind === "dir") && (value.branch === null || typeof value.branch === "string"), BLOB_REF = "$blob", blobRef = (value) => isObject5(value) && Object.keys(value).length === 1 && typeof value[BLOB_REF] === "string" && /^[0-9a-f]{64}$/.test(value[BLOB_REF]) ? value[BLOB_REF] : null, blobDigest = (value) => createHash9("sha256").update(JSON.stringify(value)).digest("hex"), toBlob = (value, blobs) => {
13233
13465
  if (!isObject5(value))
13234
13466
  return value;
13235
13467
  const digest = blobDigest(value);
@@ -13300,7 +13532,7 @@ var init_notes = __esm(() => {
13300
13532
  });
13301
13533
 
13302
13534
  // packages/workit-core/src/core/task-store.ts
13303
- import { createHash as createHash9, randomUUID as randomUUID3 } from "node:crypto";
13535
+ import { createHash as createHash10, randomUUID as randomUUID3 } from "node:crypto";
13304
13536
  import * as fs11 from "node:fs";
13305
13537
  import path15 from "node:path";
13306
13538
 
@@ -14264,7 +14496,7 @@ class TaskStore {
14264
14496
  return bound.ok ? success(null, null, bound.data[0] ?? null) : bound;
14265
14497
  }
14266
14498
  withKeyLock(key, operation) {
14267
- const digest = createHash9("sha256").update(key).digest("hex").slice(0, 32);
14499
+ const digest = createHash10("sha256").update(key).digest("hex").slice(0, 32);
14268
14500
  return this.withLock(path15.join(this.paths().dir, "keys", `${digest}.lock`), operation);
14269
14501
  }
14270
14502
  bindLocked(taskId, key, timestamp) {
@@ -15252,7 +15484,7 @@ var init_check_config = __esm(() => {
15252
15484
  });
15253
15485
 
15254
15486
  // packages/workit-core/src/core/task-evaluation.ts
15255
- import { createHash as createHash10 } from "node:crypto";
15487
+ import { createHash as createHash11 } from "node:crypto";
15256
15488
  import * as fs13 from "node:fs";
15257
15489
  import { spawnSync as spawnSync10 } from "node:child_process";
15258
15490
  import path17 from "node:path";
@@ -15706,7 +15938,7 @@ function boundTaskSummary(summary) {
15706
15938
  brief.truncated = JSON.stringify(brief).includes("…") || progress.blockers.length > BRIEF_BLOCKERS || unmet.length > BRIEF_OPEN;
15707
15939
  return brief;
15708
15940
  }
15709
- var digestBytes = (value) => createHash10("sha256").update(value).digest("hex"), inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path17.sep}`), relative = (root, candidate) => path17.relative(root, candidate).split(path17.sep).join("/") || ".", canonicalPath = (value) => {
15941
+ var digestBytes = (value) => createHash11("sha256").update(value).digest("hex"), inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path17.sep}`), relative = (root, candidate) => path17.relative(root, candidate).split(path17.sep).join("/") || ".", canonicalPath = (value) => {
15710
15942
  if (typeof value !== "string" || !value)
15711
15943
  return null;
15712
15944
  if (value.includes("\\") || value.split("/").includes(".."))
@@ -17872,7 +18104,7 @@ var support = (descriptor, axis) => {
17872
18104
  });
17873
18105
 
17874
18106
  // packages/workit-core/src/hooks/context.ts
17875
- import { createHash as createHash11 } from "node:crypto";
18107
+ import { createHash as createHash12 } from "node:crypto";
17876
18108
  import fs14 from "node:fs";
17877
18109
  import path18 from "node:path";
17878
18110
  function sessionCompactContext(store, session, context, selection = "session-bound") {
@@ -18007,7 +18239,7 @@ ${options.addendum}` : ""}
18007
18239
  } catch {
18008
18240
  return null;
18009
18241
  }
18010
- }, TURN_TTL_MS, digestOf = (text) => createHash11("sha256").update(text).digest("hex"), turnMarker = (input) => {
18242
+ }, TURN_TTL_MS, digestOf = (text) => createHash12("sha256").update(text).digest("hex"), turnMarker = (input) => {
18011
18243
  if (!input.session.id)
18012
18244
  return null;
18013
18245
  try {
@@ -18081,215 +18313,6 @@ var init_context = __esm(() => {
18081
18313
  TURN_TTL_MS = 7 * 24 * 60 * 60 * 1000;
18082
18314
  });
18083
18315
 
18084
- // packages/workit-core/src/core/commit-flavors.ts
18085
- var init_commit_flavors = () => {};
18086
-
18087
- // packages/workit-core/src/core/git.ts
18088
- var init_git = () => {};
18089
-
18090
- // packages/workit-core/src/core/branch.ts
18091
- import { createHash as createHash12 } from "node:crypto";
18092
- function effectiveWorkspacePolicy(workspaceRoot, kind, profileName) {
18093
- const selected = resolveRuntimeWorkspacePolicy(workspaceRoot, kind, profileName?.trim() || process.env.WORKFLOW_PROFILE?.trim() || undefined);
18094
- const config = readConfig();
18095
- return kind === "branch" ? {
18096
- branchPolicy: withReleaseTracks(workspaceRoot, resolveBranchPolicy(config, selected.policy ? { branchPolicy: selected.policy } : null, () => repoBranchPreset(workspaceRoot))),
18097
- provenance: { branchPolicy: selected.source }
18098
- } : {
18099
- commitPolicy: resolveCommitPolicy(config, selected.policy ? { commitPolicy: selected.policy } : null),
18100
- provenance: { commitPolicy: selected.source }
18101
- };
18102
- }
18103
- var withReleaseTracks = (workspaceRoot, policy) => {
18104
- const read = workspaceReleaseTracks(workspaceRoot);
18105
- if (read.error)
18106
- throw new ReleaseTrackError(read.error);
18107
- if (read.tracks.length === 0 && read.protectedBranches.length === 0)
18108
- return policy;
18109
- const known = new Set(policy.allowed.map((pattern) => pattern.source));
18110
- const allowed = [...policy.allowed];
18111
- for (const glob of read.tracks.flatMap((track) => Object.values(track.naming).map(namingGlob))) {
18112
- const pattern = branchGlobPattern(glob);
18113
- if (!known.has(pattern.source)) {
18114
- known.add(pattern.source);
18115
- allowed.push(pattern);
18116
- }
18117
- }
18118
- return {
18119
- ...policy,
18120
- allowed,
18121
- protected: new Set([
18122
- ...policy.protected,
18123
- ...[...trackBranches(read.tracks), ...read.protectedBranches].map((name) => name.toLowerCase())
18124
- ])
18125
- };
18126
- }, KIND_SYNONYMS, allowedKinds = (allowed) => [
18127
- ...new Set(allowed.map((pattern) => /^\^([\w.-]+)\\?\/\.\*\$$/u.exec(pattern.source)?.[1]?.toLowerCase()).filter((kind) => Boolean(kind)))
18128
- ], editDistance = (a, b) => {
18129
- const row = Array.from({ length: b.length + 1 }, (_, index) => index);
18130
- for (let i = 1;i <= a.length; i++) {
18131
- let previous = row[0];
18132
- row[0] = i;
18133
- for (let j = 1;j <= b.length; j++) {
18134
- const saved = row[j];
18135
- row[j] = Math.min(row[j] + 1, row[j - 1] + 1, previous + (a[i - 1] === b[j - 1] ? 0 : 1));
18136
- previous = saved;
18137
- }
18138
- }
18139
- return row[b.length];
18140
- }, suggestBranchName = (name, kinds) => {
18141
- if (!kinds.length)
18142
- return null;
18143
- const slash = name.indexOf("/");
18144
- const prefix = slash > 0 ? name.slice(0, slash).toLowerCase() : "";
18145
- const rest = (slash > 0 ? name.slice(slash + 1) : name) || "name";
18146
- const synonym = KIND_SYNONYMS[prefix];
18147
- const near = kinds.map((kind) => ({ kind, distance: editDistance(prefix, kind) })).filter((entry) => prefix && entry.distance <= 2).toSorted((a, b) => a.distance - b.distance)[0]?.kind;
18148
- const kind = (synonym && kinds.includes(synonym) ? synonym : null) ?? near ?? (kinds.includes("feature") ? "feature" : kinds[0]);
18149
- return `${kind}/${rest}`;
18150
- }, kindList = (kinds) => kinds.map((kind) => `${kind}/`).join(", "), aliasNote = (kinds) => {
18151
- const notes = [
18152
- ["fix", "bugfix"],
18153
- ["chore", "feature"]
18154
- ].filter(([, kind]) => kinds.includes(kind)).map(([alias, kind]) => `${alias}/ is ${kind}/`);
18155
- return notes.length ? ` (${notes.join(", ")})` : "";
18156
- }, validateBranchNamePolicy = (name, policy, source) => {
18157
- const allowed = policy.allowed.map((pattern) => `/${pattern.source}/${pattern.flags}`);
18158
- const kinds = allowedKinds(policy.allowed);
18159
- if (policy.protected.has(name.toLowerCase())) {
18160
- const correction = kinds.length ? `choose a non-protected branch of an allowed kind (${kindList(kinds)}), e.g. ${kinds[0]}/<slug>: workit git branch --kind ${kinds[0]} --slug <slug>` : `choose a non-protected branch matching one of: ${allowed.join(", ")}`;
18161
- return {
18162
- ok: false,
18163
- rule: "protected_ref",
18164
- source,
18165
- attempted: name,
18166
- correction,
18167
- error: `protected_ref: branch ${JSON.stringify(name)} is protected by ${source}; ${correction}`
18168
- };
18169
- }
18170
- if (!policy.allowed.some((pattern) => pattern.test(name))) {
18171
- const suggestion = suggestBranchName(name, kinds);
18172
- const correction = suggestion && policy.allowed.some((pattern) => pattern.test(suggestion)) ? `use ${JSON.stringify(suggestion)}; the allowed kinds are ${kindList(kinds)} (workit git branch ${suggestion})` : `choose a branch matching one of: ${allowed.join(", ")}`;
18173
- return {
18174
- ok: false,
18175
- rule: "allowed_pattern",
18176
- source,
18177
- attempted: name,
18178
- correction,
18179
- error: `allowed_pattern: branch ${JSON.stringify(name)} violates ${source} policy; ${correction}`
18180
- };
18181
- }
18182
- return { ok: true };
18183
- }, branchPolicySnapshotFor = (workspaceRoot) => {
18184
- const resolved = effectiveWorkspacePolicy(workspaceRoot, "branch");
18185
- const branchPolicy = resolved.branchPolicy;
18186
- const source = resolved.provenance.branchPolicy;
18187
- const allowed = branchPolicy.allowed.map((pattern) => `${pattern.source}/${pattern.flags}`).toSorted();
18188
- const protectedRefs = [...branchPolicy.protected].map((name) => name.toLowerCase()).toSorted();
18189
- const fingerprint = createHash12("sha256").update(JSON.stringify({ allowed, protectedRefs, source })).digest("hex");
18190
- return {
18191
- branchPolicy,
18192
- namePolicy: { allowed: branchPolicy.allowed, protected: branchPolicy.protected },
18193
- source,
18194
- fingerprint
18195
- };
18196
- }, validateBranchNameFor = (workspaceRoot, name) => {
18197
- try {
18198
- const resolved = branchPolicySnapshotFor(workspaceRoot);
18199
- return validateBranchNamePolicy(name, resolved.namePolicy, resolved.source);
18200
- } catch (error) {
18201
- const correction = "repair or select a valid workspace policy before creating a branch";
18202
- return {
18203
- ok: false,
18204
- rule: "policy_unavailable",
18205
- source: "workspaces.json",
18206
- attempted: name,
18207
- correction,
18208
- error: `policy_unavailable: cannot validate branch ${JSON.stringify(name)} because ${error instanceof Error ? error.message : String(error)}; ${correction}`
18209
- };
18210
- }
18211
- }, resolveBranchPolicyFor = (workspaceRoot, profileName) => effectiveWorkspacePolicy(workspaceRoot, "branch", profileName).branchPolicy, gitFlowOf = (root, integration) => {
18212
- try {
18213
- if (resolveBranchPolicyFor(root).preset !== "gitflow")
18214
- return null;
18215
- const selected = resolveRuntimeWorkspacePolicy(root, "branch", process.env.WORKFLOW_PROFILE?.trim() || undefined).policy;
18216
- const names = branchNames(root);
18217
- const production = productionBranchOf(names);
18218
- const develop = selected?.developBranch?.trim() || (integration && integration.toLowerCase() !== production ? integration : "develop");
18219
- return { develop, production, developExists: names.has(develop) };
18220
- } catch {
18221
- return null;
18222
- }
18223
- }, releaseBranchesOf = (cwd) => {
18224
- try {
18225
- const resolved = resolveBranchPolicyFor(cwd);
18226
- const flow = resolved.preset === "gitflow" ? gitFlowOf(cwd) : null;
18227
- return {
18228
- preset: resolved.preset,
18229
- branches: flow ? [flow.production, flow.develop] : [],
18230
- production: flow ? flow.production : resolved.defaultTargetBranch
18231
- };
18232
- } catch {
18233
- return { preset: "unknown", branches: [], production: null };
18234
- }
18235
- }, releaseBranch = (cwd, branch) => releaseBranchesOf(cwd).branches.some((name) => name.toLowerCase() === branch.toLowerCase()), branchGuidance = (cwd) => {
18236
- try {
18237
- const patterns = branchPolicySnapshotFor(cwd).namePolicy.allowed;
18238
- const kinds = allowedKinds(patterns);
18239
- const kindShaped = new Set(kinds.map((kind) => branchGlobPattern(`${kind}/*`).source));
18240
- const anyName = patterns.some((pattern) => pattern.source === "^.*$");
18241
- const others = patterns.filter((pattern) => !kindShaped.has(pattern.source)).map((pattern) => globOf(pattern));
18242
- const allowed = anyName ? "Any non-protected branch name is allowed here." : `${kinds.length ? `Allowed branch kinds here: ${kindList(kinds)}${aliasNote(kinds)}` : "Allowed branch names here:"}${others.length ? `${kinds.length ? "; also" : ""} names matching ${others.join(", ")}` : ""}; anything else is denied.`;
18243
- const resolved = vcsConfig("resolve", cwd);
18244
- const integration = resolved.ok === false ? null : String(resolved.defaultTargetBranch ?? "") || null;
18245
- const flow = resolved.releaseTrack?.track ? null : gitFlowOf(cwd, integration);
18246
- if (flow?.developExists)
18247
- return `${allowed} git-flow: feature/, bugfix/ and release/ start from origin/${flow.develop}, hotfix/ from origin/${flow.production}; feature/ and bugfix/ land on ${flow.develop}, release/ and hotfix/ on ${flow.production}.`;
18248
- const names = branchNames(cwd);
18249
- const configured = String(resolved.baseBranch ?? integration ?? "") || null;
18250
- const trunk = productionBranchOf(names);
18251
- const base = configured && names.has(configured) ? `Branch from origin/${configured}.` : names.has(trunk) ? `Branch from origin/${trunk}${configured ? ` (the default target ${configured} does not exist here)` : ""}.` : "No base branch exists here yet; pass the base explicitly.";
18252
- return `${allowed} ${base}`;
18253
- } catch {
18254
- return null;
18255
- }
18256
- }, globOf = (pattern) => pattern.source.replace(/^\^|\$$/gu, "").replaceAll(".*", "*").replace(/\\(.)/gu, "$1");
18257
- var init_branch = __esm(() => {
18258
- init_branch_policy();
18259
- init_commit_flavors();
18260
- init_git();
18261
- init_config();
18262
- init_workspaces();
18263
- init_vcs_config();
18264
- init_release_tracks();
18265
- KIND_SYNONYMS = {
18266
- fix: "bugfix",
18267
- fixes: "bugfix",
18268
- bug: "bugfix",
18269
- bugs: "bugfix",
18270
- bugfixes: "bugfix",
18271
- feat: "feature",
18272
- features: "feature",
18273
- chore: "feature",
18274
- docs: "feature",
18275
- doc: "feature",
18276
- refactor: "feature",
18277
- test: "feature",
18278
- tests: "feature",
18279
- ci: "feature",
18280
- build: "feature",
18281
- perf: "feature",
18282
- style: "feature",
18283
- deps: "feature",
18284
- task: "feature",
18285
- enhancement: "feature",
18286
- hot: "hotfix",
18287
- hotfixes: "hotfix",
18288
- releases: "release",
18289
- rel: "release"
18290
- };
18291
- });
18292
-
18293
18316
  // packages/workit-core/src/hooks/session-marker.ts
18294
18317
  import { createHash as createHash13 } from "node:crypto";
18295
18318
  import fs15 from "node:fs";
@@ -22232,9 +22255,14 @@ ${subagentStartText({ ...input, cwd: "" }, descriptor, event)}`;
22232
22255
  if (role !== "judge" || !event.agentId)
22233
22256
  return readOnly;
22234
22257
  const own = subagentSession(session, event.agentId);
22235
- const token = session ? recordIssuedSession(input.cwd || process.cwd(), session, own) : null;
22236
- const flags = token ? `--session ${own} --token ${token}` : `--session ${own}`;
22237
- return `${readOnly} Its own Workit session is ${own}: record verdicts with \`workit ledger verdict <result> ${flags} ...\` so the ledger tells it apart from the author.${token ? " The token is this subagent's alone: never write it into a report, a file or a commit. --token needs a workit CLI at least as new as this plugin; if the CLI answers that --token is an unknown option, update the workit CLI (workit upgrade --cli) and record again." : ""}`;
22258
+ const cwd = input.cwd || process.cwd();
22259
+ const token = session ? recordIssuedSession(cwd, session, own) : null;
22260
+ if (session && !token)
22261
+ return `${readOnly} ${own} was already issued to an earlier subagent, so no token is handed out again and a verdict under it would be refused (unbound_session). Record no verdict as ${own}: spawn a fresh verifier or reviewer, which gets its own session and token.`;
22262
+ const judge = event.agentType.endsWith("reviewer") ? "reviewer" : "verifier";
22263
+ const line = verdictCommand({ branch: judgeBranch(cwd), judge, session: own, token });
22264
+ const pick = judge === "verifier" ? ", --kind live when you drove the real surface" : "";
22265
+ return `${readOnly} Its own Workit session is ${own}, so the ledger tells its verdicts apart from the author's. Record the verdict with exactly this command (pick the result${pick}, name the candidate branch if it differs, say what you ran): \`${line}\`.${token ? " The token is this subagent's alone: never write it into a report, a file or a commit. --token needs a workit CLI at least as new as this plugin; if the CLI answers that --token is an unknown option, update the workit CLI (workit upgrade --cli) and record again." : ""}`;
22238
22266
  }, failureDecision = (descriptor, event, error) => {
22239
22267
  if (event === "shell.pre" || event === "tool.pre" || event === "write.pre")
22240
22268
  return descriptor.shellPolicy.failClosed ? { kind: "deny", reason: error, unblock: null } : NONE5;