@brainervirus/workit-cursor 0.9.0 → 0.10.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.
@@ -20376,7 +20376,7 @@ var init_config = __esm(() => {
20376
20376
  "trunk-based": { allowed: ["*"], protected: ["main"] },
20377
20377
  custom: { allowed: [], protected: [] }
20378
20378
  };
20379
- LOCALE_RE = /^[a-z]{2,3}(-[A-Z]{2})?$/;
20379
+ LOCALE_RE = /^[a-z]{2,3}(-(?:[A-Z]{2}|[0-9]{3}))?$/;
20380
20380
  DEFAULTS = {
20381
20381
  locale: "en",
20382
20382
  localeOptions: ["en", "es-CL", "es-MX", "es-AR", "pt-BR"],
@@ -20630,15 +20630,28 @@ var run = (cwd, args) => {
20630
20630
  var init_git = () => {};
20631
20631
 
20632
20632
  // packages/workit-core/src/core/branch.ts
20633
- import { readFileSync as readFileSync3, mkdirSync as mkdirSync3, writeFileSync as writeFileSync2 } from "node:fs";
20633
+ import {
20634
+ copyFileSync as copyFileSync2,
20635
+ cpSync as cpSync2,
20636
+ existsSync as existsSync2,
20637
+ mkdirSync as mkdirSync3,
20638
+ readFileSync as readFileSync3,
20639
+ readdirSync as readdirSync3,
20640
+ renameSync,
20641
+ rmSync,
20642
+ statSync,
20643
+ writeFileSync as writeFileSync2
20644
+ } from "node:fs";
20634
20645
  import { execFileSync as execFileSync2 } from "node:child_process";
20646
+ import { createHash } from "node:crypto";
20647
+ import { tmpdir } from "node:os";
20635
20648
  import path4 from "node:path";
20636
20649
  var resolveBranchPolicyFor = (workspaceRoot) => resolveBranchPolicy(readConfig(), resolveWorkspace(workspaceRoot)), policy = (root) => resolveBranchPolicyFor(root), allowedBranch = (root, name) => policy(root).allowed.some((r) => r.test(name)), isProtected = (root, name) => policy(root).protected.has(name.toLowerCase()), baseBranch = (cwd) => {
20637
20650
  const resolved = vcsConfig("resolve", cwd);
20638
20651
  if (resolved.ok === false)
20639
20652
  return { error: String(resolved.error) };
20640
20653
  return { base: String(resolved.defaultTargetBranch ?? "develop") };
20641
- }, DECLARE_RE, USE_CURRENT_RE, readSafe2 = (p) => {
20654
+ }, DECLARE_RE, USE_CURRENT_RE, toPosix = (p) => p.split(path4.sep).join("/"), readSafe2 = (p) => {
20642
20655
  try {
20643
20656
  return readFileSync3(p, "utf8");
20644
20657
  } catch {
@@ -20767,10 +20780,7 @@ var resolveBranchPolicyFor = (workspaceRoot) => resolveBranchPolicy(readConfig()
20767
20780
  };
20768
20781
  }
20769
20782
  return { error: `cannot resolve docs branch from HEAD ${JSON.stringify(current)}` };
20770
- }, ensureBaseBranch = (cwd, base) => {
20771
- const git = gitContext(cwd);
20772
- if (!git.branch || git.branch === "unknown")
20773
- return { ok: false, error: "not in a git repository" };
20783
+ }, originBaseReady = (cwd, base) => {
20774
20784
  const run2 = (args) => execFileSync2("git", args, { cwd, encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] });
20775
20785
  try {
20776
20786
  try {
@@ -20778,20 +20788,27 @@ var resolveBranchPolicyFor = (workspaceRoot) => resolveBranchPolicy(readConfig()
20778
20788
  } catch {
20779
20789
  run2(["fetch", "origin", "--prune"]);
20780
20790
  }
20781
- let hasOriginBase = true;
20782
20791
  try {
20783
20792
  execFileSync2("git", ["show-ref", "--verify", "--quiet", `refs/remotes/origin/${base}`], {
20784
20793
  cwd,
20785
20794
  stdio: "pipe"
20786
20795
  });
20787
20796
  } catch {
20788
- hasOriginBase = false;
20789
- }
20790
- if (!hasOriginBase)
20791
20797
  return {
20792
20798
  ok: false,
20793
20799
  error: `origin/${base} missing — push ${base} before creating feature/* or bugfix/* branches`
20794
20800
  };
20801
+ }
20802
+ return { ok: true };
20803
+ } catch (error2) {
20804
+ return {
20805
+ ok: false,
20806
+ error: error2 instanceof Error ? error2.message : "ensure-base-branch failed"
20807
+ };
20808
+ }
20809
+ }, fastForwardBase = (cwd, base) => {
20810
+ const run2 = (args) => execFileSync2("git", args, { cwd, encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] });
20811
+ try {
20795
20812
  let hasLocalBase = true;
20796
20813
  try {
20797
20814
  execFileSync2("git", ["show-ref", "--verify", "--quiet", `refs/heads/${base}`], {
@@ -20816,12 +20833,91 @@ var resolveBranchPolicyFor = (workspaceRoot) => resolveBranchPolicy(readConfig()
20816
20833
  error: error2 instanceof Error ? error2.message : "ensure-base-branch failed"
20817
20834
  };
20818
20835
  }
20836
+ }, ensureBaseBranch = (cwd, base) => {
20837
+ const git = gitContext(cwd);
20838
+ if (!git.branch || git.branch === "unknown")
20839
+ return { ok: false, error: "not in a git repository" };
20840
+ const ready = originBaseReady(cwd, base);
20841
+ if (!ready.ok)
20842
+ return ready;
20843
+ return fastForwardBase(cwd, base);
20844
+ }, purgeStaleFlowGuardRoots = (now) => {
20845
+ const cutoff = now - 24 * 3600000;
20846
+ let entries;
20847
+ try {
20848
+ entries = readdirSync3(tmpdir());
20849
+ } catch {
20850
+ return;
20851
+ }
20852
+ for (const entry of entries) {
20853
+ if (!entry.startsWith("workit-flow-guard-"))
20854
+ continue;
20855
+ try {
20856
+ if (statSync(path4.join(tmpdir(), entry)).mtimeMs < cutoff)
20857
+ rmSync(path4.join(tmpdir(), entry), { recursive: true, force: true });
20858
+ } catch {}
20859
+ }
20860
+ }, snapshotFlowState = (cwd) => {
20861
+ purgeStaleFlowGuardRoots(Date.now());
20862
+ const root = path4.join(tmpdir(), `workit-flow-guard-${createHash("sha256").update(path4.resolve(cwd)).digest("hex").slice(0, 16)}.${process.pid}.${process.hrtime.bigint()}`);
20863
+ mkdirSync3(root, { recursive: true });
20864
+ const docsDir = path4.join(path4.resolve(cwd), "docs");
20865
+ let slugs = [];
20866
+ try {
20867
+ slugs = readdirSync3(docsDir);
20868
+ } catch {
20869
+ return root;
20870
+ }
20871
+ for (const slug of slugs) {
20872
+ for (const rel of [["sdd", "flow.json"], ["spec.md"], ["plan.md"]]) {
20873
+ const src = path4.join(docsDir, slug, ...rel);
20874
+ try {
20875
+ if (!statSync(src).isFile())
20876
+ continue;
20877
+ } catch {
20878
+ continue;
20879
+ }
20880
+ const dest = path4.join(root, "docs", slug, ...rel);
20881
+ mkdirSync3(path4.dirname(dest), { recursive: true });
20882
+ cpSync2(src, dest);
20883
+ }
20884
+ }
20885
+ return root;
20886
+ }, restoreFlowSnapshot = (snapDir, cwd) => {
20887
+ const walk = (dir, rel) => readdirSync3(dir, { withFileTypes: true }).flatMap((entry) => entry.isDirectory() ? walk(path4.join(dir, entry.name), path4.join(rel, entry.name)) : [path4.join(rel, entry.name)]);
20888
+ const restored = [];
20889
+ try {
20890
+ const workspace = path4.resolve(cwd);
20891
+ for (const rel of walk(snapDir, "")) {
20892
+ const dest = path4.join(workspace, rel);
20893
+ if (existsSync2(dest))
20894
+ continue;
20895
+ mkdirSync3(path4.dirname(dest), { recursive: true });
20896
+ const tmpDest = `${dest}.tmp-${process.pid}`;
20897
+ try {
20898
+ copyFileSync2(path4.join(snapDir, rel), tmpDest);
20899
+ renameSync(tmpDest, dest);
20900
+ } catch (error2) {
20901
+ rmSync(tmpDest, { force: true });
20902
+ throw error2;
20903
+ }
20904
+ restored.push(toPosix(rel));
20905
+ }
20906
+ rmSync(snapDir, { recursive: true, force: true });
20907
+ return { restored };
20908
+ } catch (error2) {
20909
+ return {
20910
+ restored,
20911
+ warning: `flow state snapshot restore failed: ${error2 instanceof Error ? error2.message : String(error2)}`
20912
+ };
20913
+ }
20819
20914
  }, branchSetup = ({
20820
20915
  action,
20821
20916
  sdd_dir,
20822
20917
  target_branch,
20823
20918
  stash,
20824
- workspace_root
20919
+ workspace_root,
20920
+ log
20825
20921
  }) => {
20826
20922
  const cwd = path4.resolve(workspace_root);
20827
20923
  const exec = (args) => execFileSync2("git", args, { cwd, encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] });
@@ -20840,20 +20936,74 @@ var resolveBranchPolicyFor = (workspaceRoot) => resolveBranchPolicy(readConfig()
20840
20936
  };
20841
20937
  const writeManifest = (data) => writeFileSync2(manifestPath, JSON.stringify(data, null, 2) + `
20842
20938
  `, "utf8");
20939
+ let snapDir = null;
20940
+ const journal = (message) => log?.(`flow-guard: ${message}`);
20941
+ const snapshotRelPaths = () => {
20942
+ const dir = snapDir;
20943
+ if (!dir)
20944
+ return [];
20945
+ try {
20946
+ const walk = (from, rel) => readdirSync3(from, { withFileTypes: true }).flatMap((entry) => entry.isDirectory() ? walk(path4.join(from, entry.name), path4.join(rel, entry.name)) : [path4.join(rel, entry.name)]);
20947
+ return walk(dir, "").map(toPosix);
20948
+ } catch {
20949
+ return [];
20950
+ }
20951
+ };
20952
+ const journalSnapshot = () => {
20953
+ const dir = snapDir;
20954
+ if (!dir || !log)
20955
+ return;
20956
+ const rels = snapshotRelPaths();
20957
+ journal(`snapshot: ${rels.length} file(s)`);
20958
+ for (const rel of rels) {
20959
+ let shortHash = "";
20960
+ try {
20961
+ shortHash = createHash("sha256").update(readFileSync3(path4.join(dir, rel))).digest("hex").slice(0, 8);
20962
+ } catch {}
20963
+ journal(`snapshot: ${rel} sha=${shortHash}`);
20964
+ }
20965
+ };
20966
+ const journalPresence = (phase) => {
20967
+ for (const rel of snapshotRelPaths()) {
20968
+ journal(`${phase}: ${rel} ${existsSync2(path4.join(cwd, rel)) ? "present" : "MISSING"}`);
20969
+ }
20970
+ };
20971
+ const restoreWithWarning = (dir) => {
20972
+ if (!dir)
20973
+ return { restored: [], warnings: [] };
20974
+ const total = log ? snapshotRelPaths().length : 0;
20975
+ const { restored, warning } = restoreFlowSnapshot(dir, cwd);
20976
+ if (log)
20977
+ journal(`restore: restored=${restored.length} skipped=${total - restored.length}${warning ? ` warning: ${warning}` : ""}`);
20978
+ else if (warning)
20979
+ journal(`restore warning: ${warning}`);
20980
+ return { restored, warnings: warning ? [warning] : [] };
20981
+ };
20843
20982
  if (action === "reapply_stash") {
20844
- const manifest2 = readManifest();
20845
- const ref = manifest2.stash_ref;
20983
+ const manifest = readManifest();
20984
+ const ref = manifest.stash_ref;
20846
20985
  if (!ref)
20847
20986
  return { error: "no stash_ref in manifest" };
20987
+ snapDir = snapshotFlowState(cwd);
20988
+ journalSnapshot();
20989
+ journal(`pre-pop: ${String(ref)}`);
20848
20990
  try {
20849
20991
  exec(["stash", "pop", String(ref)]);
20850
20992
  } catch (error2) {
20851
- return { error: error2 instanceof Error ? error2.message : "stash pop failed" };
20993
+ journal("pop: failed");
20994
+ const {
20995
+ warnings: [warning]
20996
+ } = restoreWithWarning(snapDir);
20997
+ return {
20998
+ error: `${error2 instanceof Error ? error2.message : "stash pop failed"}${warning ? `; ${warning}` : ""}`
20999
+ };
20852
21000
  }
20853
- delete manifest2.stash_ref;
20854
- delete manifest2.stash_created_at;
20855
- writeManifest(manifest2);
20856
- return { action: "reapply_stash", ok: true };
21001
+ journal("pop: ok");
21002
+ delete manifest.stash_ref;
21003
+ delete manifest.stash_created_at;
21004
+ writeManifest(manifest);
21005
+ const { warnings: warnings2 } = restoreWithWarning(snapDir);
21006
+ return { action: "reapply_stash", ok: true, ...warnings2.length > 0 ? { warnings: warnings2 } : {} };
20857
21007
  }
20858
21008
  const target = target_branch ?? "";
20859
21009
  if (!target)
@@ -20862,61 +21012,141 @@ var resolveBranchPolicyFor = (workspaceRoot) => resolveBranchPolicy(readConfig()
20862
21012
  return { error: `protected branch ${target}` };
20863
21013
  if (!allowedBranch(cwd, target))
20864
21014
  return { error: `target branch ${target} is not allowed by the branch policy` };
21015
+ let base;
21016
+ let targetExists = true;
21017
+ try {
21018
+ exec(["rev-parse", "--verify", "--quiet", `refs/heads/${target}`]);
21019
+ } catch {
21020
+ targetExists = false;
21021
+ }
21022
+ if (!targetExists) {
21023
+ const baseResolved = baseBranch(cwd);
21024
+ if ("error" in baseResolved)
21025
+ return { error: baseResolved.error };
21026
+ base = baseResolved.base;
21027
+ }
21028
+ journal(`entry: current=${current} target=${target} base=${base ?? "-"}`);
20865
21029
  let stash_ref;
21030
+ const failAfterStash = (message) => {
21031
+ let suffix = "";
21032
+ if (stash_ref) {
21033
+ journal(`pre-pop: ${stash_ref}`);
21034
+ try {
21035
+ exec(["stash", "pop", stash_ref]);
21036
+ stash_ref = undefined;
21037
+ journal("pop: ok");
21038
+ } catch {
21039
+ journal("pop: failed");
21040
+ suffix = " (changes preserved in stash)";
21041
+ }
21042
+ }
21043
+ const {
21044
+ warnings: [warning]
21045
+ } = restoreWithWarning(snapDir);
21046
+ return { error: `${message}${suffix}${warning ? `; ${warning}` : ""}` };
21047
+ };
20866
21048
  if (current !== target) {
20867
21049
  const dirty = Boolean(gitContext(cwd).status_short.trim());
21050
+ if (dirty && stash !== "yes") {
21051
+ return {
21052
+ error: "dirty working tree — ask with native question, then call workit_branch_setup with stash=yes"
21053
+ };
21054
+ }
21055
+ let validatedBase;
21056
+ if (!targetExists && base !== undefined) {
21057
+ const ready = originBaseReady(cwd, base);
21058
+ if (!ready.ok)
21059
+ return { error: ready.error ?? "ensure-base-branch failed" };
21060
+ validatedBase = base;
21061
+ }
20868
21062
  if (dirty) {
20869
- if (stash !== "yes") {
20870
- return {
20871
- error: "dirty working tree — ask with native question, then call workit_branch_setup with stash=yes"
20872
- };
20873
- }
20874
21063
  try {
21064
+ snapDir = snapshotFlowState(cwd);
21065
+ journalSnapshot();
20875
21066
  exec(["stash", "push", "-u", "-m", `workit: pre-checkout ${target}`, "--", ":!docs/*/sdd"]);
20876
21067
  } catch (error2) {
20877
21068
  return { error: error2 instanceof Error ? error2.message : "stash push failed" };
20878
21069
  }
20879
21070
  stash_ref = "stash@{0}";
21071
+ journal(`stash push: ${stash_ref}`);
20880
21072
  }
20881
21073
  try {
20882
21074
  exec(["checkout", target]);
21075
+ journalPresence("post-checkout");
20883
21076
  } catch (error2) {
20884
21077
  const message = error2 instanceof Error ? error2.message : "checkout failed";
20885
21078
  if (/worktree/i.test(message)) {
20886
- return {
20887
- error: `branch ${target} is locked by an existing git worktree — remove it first (we do not use worktrees)`
20888
- };
21079
+ return failAfterStash(`branch ${target} is locked by an existing git worktree — remove it first (we do not use worktrees)`);
20889
21080
  }
20890
21081
  try {
20891
- const baseResolved = baseBranch(cwd);
20892
- if ("error" in baseResolved)
20893
- return { error: baseResolved.error };
20894
- const baseResult = ensureBaseBranch(cwd, baseResolved.base);
21082
+ let effectiveBase = base;
21083
+ if (effectiveBase === undefined) {
21084
+ const lateResolved = baseBranch(cwd);
21085
+ if ("error" in lateResolved)
21086
+ return failAfterStash(lateResolved.error);
21087
+ effectiveBase = lateResolved.base;
21088
+ }
21089
+ const baseResult = validatedBase !== undefined ? fastForwardBase(cwd, effectiveBase) : ensureBaseBranch(cwd, effectiveBase);
20895
21090
  if (!baseResult.ok)
20896
- return { error: baseResult.error };
21091
+ return failAfterStash(baseResult.error ?? "ensure-base-branch failed");
20897
21092
  exec(["checkout", "-b", target]);
21093
+ journalPresence("post-create");
20898
21094
  } catch (createError) {
20899
- return {
20900
- error: createError instanceof Error ? createError.message : "branch create failed"
20901
- };
21095
+ return failAfterStash(createError instanceof Error ? createError.message : "branch create failed");
20902
21096
  }
20903
21097
  }
20904
21098
  }
20905
- const manifest = readManifest();
20906
- manifest.branch = target;
20907
- manifest.previous_branch = current;
20908
- if (stash_ref) {
20909
- manifest.stash_ref = stash_ref;
20910
- manifest.stash_created_at = new Date().toISOString();
21099
+ try {
21100
+ const manifest = readManifest();
21101
+ manifest.branch = target;
21102
+ manifest.previous_branch = current;
21103
+ if (stash_ref) {
21104
+ manifest.stash_ref = stash_ref;
21105
+ manifest.stash_created_at = new Date().toISOString();
21106
+ }
21107
+ writeManifest(manifest);
21108
+ } catch (error2) {
21109
+ const result = failAfterStash(error2 instanceof Error ? `manifest update failed: ${error2.message}` : "manifest update failed");
21110
+ if (stash_ref === undefined && gitContext(cwd).branch !== current) {
21111
+ try {
21112
+ exec(["checkout", current]);
21113
+ } catch {}
21114
+ }
21115
+ return result;
21116
+ }
21117
+ const { restored: restoredRels, warnings } = restoreWithWarning(snapDir);
21118
+ if (stash_ref && snapDir && warnings.length === 0) {
21119
+ const covered = new Set(restoredRels.map(toPosix));
21120
+ try {
21121
+ const stashed = exec([
21122
+ "stash",
21123
+ "show",
21124
+ "--include-untracked",
21125
+ "--name-only",
21126
+ String(stash_ref)
21127
+ ]).split(`
21128
+ `).map((line) => toPosix(line.trim())).filter(Boolean);
21129
+ if (stashed.length > 0 && stashed.every((p) => covered.has(p))) {
21130
+ exec(["stash", "drop", String(stash_ref)]);
21131
+ stash_ref = undefined;
21132
+ journal("dropped redundant stash (fully covered by snapshot restore)");
21133
+ const manifest = readManifest();
21134
+ delete manifest.stash_ref;
21135
+ delete manifest.stash_created_at;
21136
+ writeManifest(manifest);
21137
+ } else {
21138
+ journal(`kept stash ref ${stash_ref} (not fully covered by actual restores)`);
21139
+ }
21140
+ } catch {}
20911
21141
  }
20912
- writeManifest(manifest);
20913
21142
  return {
20914
21143
  action: "setup",
20915
21144
  ok: true,
20916
21145
  branch: target,
20917
21146
  previous_branch: current,
20918
21147
  stash_ref: stash_ref ?? null,
20919
- manifest: manifestPath
21148
+ manifest: manifestPath,
21149
+ ...warnings.length > 0 ? { warnings } : {}
20920
21150
  };
20921
21151
  };
20922
21152
  var init_branch = __esm(() => {
@@ -21232,7 +21462,7 @@ var init_vcs_config = __esm(() => {
21232
21462
 
21233
21463
  // packages/workit-core/src/core/repo-context.ts
21234
21464
  import { spawnSync as spawnSync2 } from "node:child_process";
21235
- import { existsSync as existsSync2, readFileSync as readFileSync4, readdirSync as readdirSync3 } from "node:fs";
21465
+ import { existsSync as existsSync3, readFileSync as readFileSync4, readdirSync as readdirSync4 } from "node:fs";
21236
21466
  import path6 from "node:path";
21237
21467
  function resolvePrBranchContext(cwd) {
21238
21468
  const branch = currentBranch(cwd);
@@ -21350,7 +21580,7 @@ ${status.stderr}` : "");
21350
21580
  stdout += `
21351
21581
  `;
21352
21582
  stdout += printSection("Recent Validation Signals");
21353
- if (existsSync2(path6.join(cwd, "package.json"))) {
21583
+ if (existsSync3(path6.join(cwd, "package.json"))) {
21354
21584
  stdout += `package.json detected. Common scripts:
21355
21585
  `;
21356
21586
  const found = packageScripts(cwd, ["lint", "format:check", "test", "build"]);
@@ -21359,7 +21589,7 @@ ${status.stderr}` : "");
21359
21589
  `) + `
21360
21590
  `;
21361
21591
  }
21362
- if (existsSync2(path6.join(cwd, "Cargo.toml")) || existsSync2(path6.join(cwd, "src-tauri/Cargo.toml"))) {
21592
+ if (existsSync3(path6.join(cwd, "Cargo.toml")) || existsSync3(path6.join(cwd, "src-tauri/Cargo.toml"))) {
21363
21593
  stdout += `Rust project detected.
21364
21594
  `;
21365
21595
  }
@@ -21400,7 +21630,7 @@ function changelogContext(root, range) {
21400
21630
  `;
21401
21631
  stdout += printSection("Existing CHANGELOG.md");
21402
21632
  const changelogPath = path6.join(cwd, "CHANGELOG.md");
21403
- if (existsSync2(changelogPath)) {
21633
+ if (existsSync3(changelogPath)) {
21404
21634
  stdout += readTrimmed(changelogPath, 260) + `
21405
21635
  `;
21406
21636
  } else {
@@ -21438,7 +21668,7 @@ function docsRefreshContext(root, range) {
21438
21668
  `;
21439
21669
  stdout += printSection("README Preview");
21440
21670
  const readme = path6.join(cwd, "README.md");
21441
- if (existsSync2(readme)) {
21671
+ if (existsSync3(readme)) {
21442
21672
  stdout += readTrimmed(readme, 220) + `
21443
21673
  `;
21444
21674
  } else {
@@ -21447,7 +21677,7 @@ function docsRefreshContext(root, range) {
21447
21677
  }
21448
21678
  stdout += printSection("Package Scripts");
21449
21679
  const pkgPath = path6.join(cwd, "package.json");
21450
- if (existsSync2(pkgPath)) {
21680
+ if (existsSync3(pkgPath)) {
21451
21681
  try {
21452
21682
  const pkg = JSON.parse(readFileSync4(pkgPath, "utf8"));
21453
21683
  stdout += JSON.stringify({ name: pkg.name, version: pkg.version, scripts: pkg.scripts }, null, 2) + `
@@ -21494,7 +21724,7 @@ function releaseNotesContext(root, rangeOrTag) {
21494
21724
  `;
21495
21725
  stdout += printSection("Existing Release Files");
21496
21726
  for (const rel of ["CHANGELOG.md", "RELEASE_NOTES.md", ".github/releases.md"]) {
21497
- if (existsSync2(path6.join(cwd, rel)))
21727
+ if (existsSync3(path6.join(cwd, rel)))
21498
21728
  stdout += rel + `
21499
21729
  `;
21500
21730
  }
@@ -21531,7 +21761,7 @@ var runGit = (cwd, args) => {
21531
21761
 
21532
21762
  `, probeCaseInsensitive = (dir, wanted) => {
21533
21763
  try {
21534
- for (const entry of readdirSync3(dir)) {
21764
+ for (const entry of readdirSync4(dir)) {
21535
21765
  if (entry.toLowerCase() === wanted.toLowerCase())
21536
21766
  return entry;
21537
21767
  }
@@ -21577,7 +21807,7 @@ var runGit = (cwd, args) => {
21577
21807
  return runGit(cwd, ["diff", "--stat", "--"]).stdout;
21578
21808
  }, packageScripts = (cwd, keys) => {
21579
21809
  const pkgPath = path6.join(cwd, "package.json");
21580
- if (!existsSync2(pkgPath))
21810
+ if (!existsSync3(pkgPath))
21581
21811
  return [];
21582
21812
  try {
21583
21813
  const pkg = JSON.parse(readFileSync4(pkgPath, "utf8"));
@@ -21593,7 +21823,7 @@ var runGit = (cwd, args) => {
21593
21823
  return;
21594
21824
  let entries;
21595
21825
  try {
21596
- entries = readdirSync3(dir, { withFileTypes: true });
21826
+ entries = readdirSync4(dir, { withFileTypes: true });
21597
21827
  } catch {
21598
21828
  return;
21599
21829
  }
@@ -21610,7 +21840,7 @@ var runGit = (cwd, args) => {
21610
21840
  walk(cwd, 1);
21611
21841
  return matches.sort().slice(0, 200);
21612
21842
  }, readTrimmed = (file, maxLines) => {
21613
- if (!existsSync2(file))
21843
+ if (!existsSync3(file))
21614
21844
  return "";
21615
21845
  const lines = readFileSync4(file, "utf8").split(`
21616
21846
  `);
@@ -21629,7 +21859,7 @@ var init_repo_context = __esm(() => {
21629
21859
 
21630
21860
  // packages/workit-core/src/core/verify-project.ts
21631
21861
  import { spawnSync as spawnSync3 } from "node:child_process";
21632
- import { existsSync as existsSync3, readFileSync as readFileSync5, statSync } from "node:fs";
21862
+ import { existsSync as existsSync4, readFileSync as readFileSync5, statSync as statSync2 } from "node:fs";
21633
21863
  import path7 from "node:path";
21634
21864
  function runVerifyProject(root, dryRun = false) {
21635
21865
  const cwd = repoRoot(root);
@@ -21688,7 +21918,7 @@ root: ${cwd}
21688
21918
  lines.push(`dry_run: ${String(dryRun)}
21689
21919
  `);
21690
21920
  const pkgPath = path7.join(cwd, "package.json");
21691
- if (existsSync3(pkgPath)) {
21921
+ if (existsSync4(pkgPath)) {
21692
21922
  const runner = packageRunner(cwd);
21693
21923
  for (const script of ["lint", "format:check", "test", "build"]) {
21694
21924
  if (hasScript(cwd, script)) {
@@ -21703,7 +21933,7 @@ root: ${cwd}
21703
21933
  } else {
21704
21934
  skipCheck("javascript", "package.json not found");
21705
21935
  }
21706
- const cargoManifest = existsSync3(path7.join(cwd, "Cargo.toml")) ? "Cargo.toml" : existsSync3(path7.join(cwd, "src-tauri/Cargo.toml")) ? "src-tauri/Cargo.toml" : "";
21936
+ const cargoManifest = existsSync4(path7.join(cwd, "Cargo.toml")) ? "Cargo.toml" : existsSync4(path7.join(cwd, "src-tauri/Cargo.toml")) ? "src-tauri/Cargo.toml" : "";
21707
21937
  if (cargoManifest) {
21708
21938
  runCheck("cargo fmt", "cargo", ["fmt", "--manifest-path", cargoManifest, "--", "--check"]);
21709
21939
  runCheck("cargo clippy", "cargo", [
@@ -21719,7 +21949,7 @@ root: ${cwd}
21719
21949
  } else {
21720
21950
  skipCheck("rust", "Cargo.toml not found");
21721
21951
  }
21722
- if (existsSync3(path7.join(cwd, "pyproject.toml")) || existsSync3(path7.join(cwd, "pytest.ini")) || existsSync3(path7.join(cwd, "tests"))) {
21952
+ if (existsSync4(path7.join(cwd, "pyproject.toml")) || existsSync4(path7.join(cwd, "pytest.ini")) || existsSync4(path7.join(cwd, "tests"))) {
21723
21953
  if (commandOnPath("pytest"))
21724
21954
  runCheck("pytest", "pytest", []);
21725
21955
  else
@@ -21741,7 +21971,7 @@ root: ${cwd}
21741
21971
  lines.push(`status: skipped (dry run)
21742
21972
  `);
21743
21973
  skipped += 1;
21744
- } else if (existsSync3(changelogPath)) {
21974
+ } else if (existsSync4(changelogPath)) {
21745
21975
  if (/## \[Unreleased\]/i.test(readFileSync5(changelogPath, "utf8"))) {
21746
21976
  lines.push(`status: pass
21747
21977
  `);
@@ -21783,9 +22013,9 @@ var commandOnPath = (name) => {
21783
22013
  for (const candidateName of names) {
21784
22014
  const candidate = path7.join(dir, candidateName);
21785
22015
  try {
21786
- statSync(candidate);
22016
+ statSync2(candidate);
21787
22017
  if (process.platform !== "win32") {
21788
- const mode = statSync(candidate).mode & 73;
22018
+ const mode = statSync2(candidate).mode & 73;
21789
22019
  if (mode === 0)
21790
22020
  continue;
21791
22021
  }
@@ -21796,7 +22026,7 @@ var commandOnPath = (name) => {
21796
22026
  return false;
21797
22027
  }, hasScript = (cwd, name) => {
21798
22028
  const pkgPath = path7.join(cwd, "package.json");
21799
- if (!existsSync3(pkgPath))
22029
+ if (!existsSync4(pkgPath))
21800
22030
  return false;
21801
22031
  try {
21802
22032
  const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
@@ -21805,10 +22035,10 @@ var commandOnPath = (name) => {
21805
22035
  return false;
21806
22036
  }
21807
22037
  }, packageRunner = (cwd) => {
21808
- if (existsSync3(path7.join(cwd, "pnpm-lock.yaml")))
22038
+ if (existsSync4(path7.join(cwd, "pnpm-lock.yaml")))
21809
22039
  return "pnpm";
21810
22040
  const pkgPath = path7.join(cwd, "package.json");
21811
- if (existsSync3(pkgPath)) {
22041
+ if (existsSync4(pkgPath)) {
21812
22042
  try {
21813
22043
  const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
21814
22044
  if (typeof pkg.packageManager === "string" && pkg.packageManager.startsWith("pnpm")) {
@@ -21816,7 +22046,7 @@ var commandOnPath = (name) => {
21816
22046
  }
21817
22047
  } catch {}
21818
22048
  }
21819
- if (existsSync3(path7.join(cwd, "yarn.lock")))
22049
+ if (existsSync4(path7.join(cwd, "yarn.lock")))
21820
22050
  return "yarn";
21821
22051
  return "npm";
21822
22052
  };
@@ -21836,21 +22066,21 @@ var init_support_matrix = __esm(() => {
21836
22066
  });
21837
22067
 
21838
22068
  // packages/workit-core/src/core/package-root.ts
21839
- import { existsSync as existsSync4 } from "node:fs";
22069
+ import { existsSync as existsSync5 } from "node:fs";
21840
22070
  import path8 from "node:path";
21841
22071
  import { fileURLToPath } from "node:url";
21842
22072
  var packageRoot = () => {
21843
22073
  let dir = path8.dirname(fileURLToPath(import.meta.url));
21844
22074
  while (true) {
21845
22075
  const parent = path8.dirname(dir);
21846
- if (existsSync4(path8.join(dir, "package.json")) || parent === dir)
22076
+ if (existsSync5(path8.join(dir, "package.json")) || parent === dir)
21847
22077
  return dir;
21848
22078
  dir = parent;
21849
22079
  }
21850
22080
  }, assetRoot = () => {
21851
22081
  const root = packageRoot();
21852
22082
  const assets = path8.join(root, "assets");
21853
- return existsSync4(assets) ? assets : root;
22083
+ return existsSync5(assets) ? assets : root;
21854
22084
  };
21855
22085
  var init_package_root = () => {};
21856
22086
 
@@ -21883,9 +22113,9 @@ var named = (s, name) => s === name || s.startsWith(`${name}@`), CURSOR_RUNTIME_
21883
22113
  var init_registration = () => {};
21884
22114
 
21885
22115
  // packages/workit-core/src/core/skill-manifests.ts
21886
- import { existsSync as existsSync5, readFileSync as readFileSync6, readdirSync as readdirSync4, statSync as statSync2 } from "node:fs";
22116
+ import { existsSync as existsSync6, readFileSync as readFileSync6, readdirSync as readdirSync5, statSync as statSync3 } from "node:fs";
21887
22117
  import path9 from "node:path";
21888
- var CANONICAL_SKILLS, skillManifestNames = (root) => existsSync5(root) ? readdirSync4(root).filter((name) => existsSync5(path9.join(root, name, "SKILL.md"))).sort() : [], validateSkillManifests = (root, expected, label) => {
22118
+ var CANONICAL_SKILLS, skillManifestNames = (root) => existsSync6(root) ? readdirSync5(root).filter((name) => existsSync6(path9.join(root, name, "SKILL.md"))).sort() : [], validateSkillManifests = (root, expected, label) => {
21889
22119
  const actual = skillManifestNames(root);
21890
22120
  const missing = expected.filter((name) => !actual.includes(name));
21891
22121
  const extra = actual.filter((name) => !expected.includes(name));
@@ -21901,11 +22131,11 @@ var CANONICAL_SKILLS, skillManifestNames = (root) => existsSync5(root) ? readdir
21901
22131
  const pending = [vendor];
21902
22132
  while (pending.length > 0) {
21903
22133
  const dir = pending.pop();
21904
- for (const entry of readdirSync4(dir, { withFileTypes: true })) {
22134
+ for (const entry of readdirSync5(dir, { withFileTypes: true })) {
21905
22135
  const file = path9.join(dir, entry.name);
21906
22136
  if (entry.isDirectory())
21907
22137
  pending.push(file);
21908
- else if ((statSync2(file).mode & 73) !== 0 || readFileSync6(file).subarray(0, 2).toString("latin1") === "#!") {
22138
+ else if ((statSync3(file).mode & 73) !== 0 || readFileSync6(file).subarray(0, 2).toString("latin1") === "#!") {
21909
22139
  return `Cursor vendor contains active file: ${file}`;
21910
22140
  }
21911
22141
  }
@@ -21950,13 +22180,13 @@ var init_skill_manifests = __esm(() => {
21950
22180
 
21951
22181
  // packages/workit-core/src/core/doctor.ts
21952
22182
  import { spawnSync as spawnSync4 } from "node:child_process";
21953
- import { existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync7, statSync as statSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "node:fs";
22183
+ import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync7, statSync as statSync4, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "node:fs";
21954
22184
  import os3 from "node:os";
21955
22185
  import path10 from "node:path";
21956
22186
  var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
21957
22187
  let dir = path10.resolve(cwd);
21958
22188
  while (true) {
21959
- if (existsSync6(path10.join(dir, "packages", "workit-core", "package.json")))
22189
+ if (existsSync7(path10.join(dir, "packages", "workit-core", "package.json")))
21960
22190
  return dir;
21961
22191
  const parent = path10.dirname(dir);
21962
22192
  if (parent === dir)
@@ -22010,7 +22240,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
22010
22240
  for (const candidateName of names) {
22011
22241
  const candidate = path10.join(dir, candidateName);
22012
22242
  try {
22013
- const st = statSync3(candidate);
22243
+ const st = statSync4(candidate);
22014
22244
  if (process.platform !== "win32" && (st.mode & 73) === 0)
22015
22245
  continue;
22016
22246
  return true;
@@ -22034,14 +22264,14 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
22034
22264
  }
22035
22265
  return true;
22036
22266
  }, resolveBun = (env) => {
22037
- if (env.BUN && existsSync6(env.BUN))
22267
+ if (env.BUN && existsSync7(env.BUN))
22038
22268
  return env.BUN;
22039
22269
  for (const candidate of [
22040
22270
  path10.join(os3.homedir(), ".bun/bin/bun"),
22041
22271
  "/usr/local/bin/bun",
22042
22272
  "/usr/bin/bun"
22043
22273
  ]) {
22044
- if (existsSync6(candidate))
22274
+ if (existsSync7(candidate))
22045
22275
  return candidate;
22046
22276
  }
22047
22277
  return commandOnPath2("bun", env) ? "bun" : null;
@@ -22155,7 +22385,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
22155
22385
  }
22156
22386
  }, hostsFor = (host) => host === "cli" ? ["opencode", "cursor", "cli"] : [host], checkAssets = (res) => {
22157
22387
  const dev = res.dev;
22158
- const missing = dev ? hostsFor(res.host).flatMap((h) => assetPathsFor(h, dev).filter((p) => !existsSync6(p)).map((p) => `${h}: ${p}`)) : [];
22388
+ const missing = dev ? hostsFor(res.host).flatMap((h) => assetPathsFor(h, dev).filter((p) => !existsSync7(p)).map((p) => `${h}: ${p}`)) : [];
22159
22389
  if (res.host === "cursor" || res.host === "cli") {
22160
22390
  const cursorError = validateCursorSkills(res.cursorPluginDir);
22161
22391
  if (cursorError)
@@ -22196,7 +22426,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
22196
22426
  }
22197
22427
  }, validNodeEntry = (entry, runtime, env) => {
22198
22428
  try {
22199
- const stat = statSync3(entry);
22429
+ const stat = statSync4(entry);
22200
22430
  if (!stat.isFile() || stat.size === 0 || !readFileSync7(entry, "utf8").startsWith(`#!/usr/bin/env node
22201
22431
  `)) {
22202
22432
  return false;
@@ -22206,7 +22436,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
22206
22436
  return false;
22207
22437
  }
22208
22438
  }, registeredCursorLauncher = (res) => {
22209
- if (!existsSync6(res.cursorMcp))
22439
+ if (!existsSync7(res.cursorMcp))
22210
22440
  return "invalid";
22211
22441
  const config2 = readJson(res.cursorMcp);
22212
22442
  if (!config2)
@@ -22235,7 +22465,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
22235
22465
  };
22236
22466
  }, canonicalCursorHook, registeredCursorHook = (res) => {
22237
22467
  const hooksFile = path10.join(res.cursorPluginDir, "hooks", "hooks-cursor.json");
22238
- if (!existsSync6(hooksFile))
22468
+ if (!existsSync7(hooksFile))
22239
22469
  return "invalid";
22240
22470
  const config2 = readJson(hooksFile);
22241
22471
  if (!config2)
@@ -22278,7 +22508,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
22278
22508
  }
22279
22509
  }
22280
22510
  if (dev) {
22281
- missing.push(...hosts.filter((h) => h !== "cursor").flatMap((h) => launcherSlotsFor(h, dev).filter((slot) => !slot.some((p) => existsSync6(p))).map((slot) => `${h}: ${slot.join(" or ")}`)));
22511
+ missing.push(...hosts.filter((h) => h !== "cursor").flatMap((h) => launcherSlotsFor(h, dev).filter((slot) => !slot.some((p) => existsSync7(p))).map((slot) => `${h}: ${slot.join(" or ")}`)));
22282
22512
  }
22283
22513
  if (missing.length > 0) {
22284
22514
  return {
@@ -22330,7 +22560,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
22330
22560
  return "stale";
22331
22561
  if (entry.startsWith("file:")) {
22332
22562
  const target = entry.replace(/^file:\/\//, "").replace(/^file:/, "");
22333
- return existsSync6(target) ? "ok" : "missing-file";
22563
+ return existsSync7(target) ? "ok" : "missing-file";
22334
22564
  }
22335
22565
  return "ok";
22336
22566
  }, checkStalePin = (res) => {
@@ -22341,7 +22571,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
22341
22571
  detail: "opencode pin not inspected on the cursor host"
22342
22572
  };
22343
22573
  }
22344
- if (!existsSync6(res.opencodeConfig)) {
22574
+ if (!existsSync7(res.opencodeConfig)) {
22345
22575
  return {
22346
22576
  id: "stale_pin",
22347
22577
  status: "pass",
@@ -22378,7 +22608,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
22378
22608
  return { id: "stale_pin", status: "pass", detail: "opencode pin resolves" };
22379
22609
  }, pluginMcpSelectors = (res) => {
22380
22610
  const p = path10.join(res.cursorPluginDir, "mcp.json");
22381
- if (!existsSync6(p))
22611
+ if (!existsSync7(p))
22382
22612
  return null;
22383
22613
  const cfg = readJson(p);
22384
22614
  const server = cfg?.mcpServers?.workit;
@@ -22488,13 +22718,13 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
22488
22718
  const problems = [];
22489
22719
  const opencodeHost = res.host !== "cursor";
22490
22720
  const cursorHost = res.host !== "opencode";
22491
- if (opencodeHost && existsSync6(res.opencodeConfig)) {
22721
+ if (opencodeHost && existsSync7(res.opencodeConfig)) {
22492
22722
  const cfg = readJson(res.opencodeConfig);
22493
22723
  const entries = pluginEntries(cfg);
22494
22724
  if (entries.length > 1)
22495
22725
  problems.push(`opencode registers ${entries.length} workit plugin entries`);
22496
22726
  }
22497
- if (cursorHost && existsSync6(res.cursorSettings)) {
22727
+ if (cursorHost && existsSync7(res.cursorSettings)) {
22498
22728
  const settings = readJson(res.cursorSettings);
22499
22729
  const enabled = settings?.enabled_plugins;
22500
22730
  if (enabled && typeof enabled === "object") {
@@ -22509,7 +22739,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
22509
22739
  if (dirs.length > 1)
22510
22740
  problems.push(`cursor plugin_dirs has ${dirs.length} workit entries`);
22511
22741
  }
22512
- if (cursorHost && existsSync6(res.cursorMcp)) {
22742
+ if (cursorHost && existsSync7(res.cursorMcp)) {
22513
22743
  const mcp = readJson(res.cursorMcp);
22514
22744
  const servers = mcp?.mcpServers ?? {};
22515
22745
  if (servers && typeof servers === "object") {
@@ -22535,16 +22765,16 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
22535
22765
  const files = [];
22536
22766
  for (const name of ["config.json", "youtrack.json", "vcs.json", "workspaces.json"]) {
22537
22767
  const p = path10.join(res.configDir, name);
22538
- if (existsSync6(p))
22768
+ if (existsSync7(p))
22539
22769
  files.push(p);
22540
22770
  }
22541
22771
  const opencodeHost = res.host !== "cursor";
22542
22772
  const cursorHost = res.host !== "opencode";
22543
- if (opencodeHost && existsSync6(res.opencodeConfig))
22773
+ if (opencodeHost && existsSync7(res.opencodeConfig))
22544
22774
  files.push(res.opencodeConfig);
22545
- if (cursorHost && existsSync6(res.cursorSettings))
22775
+ if (cursorHost && existsSync7(res.cursorSettings))
22546
22776
  files.push(res.cursorSettings);
22547
- if (cursorHost && existsSync6(res.cursorMcp))
22777
+ if (cursorHost && existsSync7(res.cursorMcp))
22548
22778
  files.push(res.cursorMcp);
22549
22779
  const bad = files.filter((p) => !parsesAsConfigObject(p));
22550
22780
  if (bad.length === 0)
@@ -22561,7 +22791,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
22561
22791
  };
22562
22792
  }, checkWorkspaceMismatch = (res) => {
22563
22793
  const file = path10.join(res.configDir, "workspaces.json");
22564
- if (!existsSync6(file))
22794
+ if (!existsSync7(file))
22565
22795
  return {
22566
22796
  id: "workspace_mismatch",
22567
22797
  status: "pass",
@@ -22599,7 +22829,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
22599
22829
  const youtrackJson = readJson(path10.join(res.configDir, "youtrack.json"));
22600
22830
  if (youtrackJson) {
22601
22831
  tokenPaths.push(typeof youtrackJson.tokenFile === "string" ? youtrackJson.tokenFile : path10.join(res.configDir, "youtrack.token"));
22602
- } else if (existsSync6(path10.join(res.configDir, "youtrack.token"))) {
22832
+ } else if (existsSync7(path10.join(res.configDir, "youtrack.token"))) {
22603
22833
  tokenPaths.push(path10.join(res.configDir, "youtrack.token"));
22604
22834
  }
22605
22835
  const vcsJson = readJson(path10.join(res.configDir, "vcs.json"));
@@ -22608,7 +22838,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
22608
22838
  if (provider && typeof provider === "object") {
22609
22839
  const tf = provider.tokenFile;
22610
22840
  tokenPaths.push(typeof tf === "string" ? tf : path10.join(res.configDir, `${key}.token`));
22611
- } else if (!vcsJson && existsSync6(path10.join(res.configDir, `${key}.token`))) {
22841
+ } else if (!vcsJson && existsSync7(path10.join(res.configDir, `${key}.token`))) {
22612
22842
  tokenPaths.push(path10.join(res.configDir, `${key}.token`));
22613
22843
  }
22614
22844
  }
@@ -22622,12 +22852,12 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
22622
22852
  const problems = [];
22623
22853
  for (const raw of tokenPaths) {
22624
22854
  const p = path10.isAbsolute(raw) ? raw : path10.resolve(res.configDir, raw);
22625
- if (!existsSync6(p)) {
22855
+ if (!existsSync7(p)) {
22626
22856
  problems.push(`${p} is missing`);
22627
22857
  continue;
22628
22858
  }
22629
22859
  if (process.platform !== "win32") {
22630
- const mode = statSync3(p).mode & 511;
22860
+ const mode = statSync4(p).mode & 511;
22631
22861
  if (mode !== 384)
22632
22862
  problems.push(`${p} must be mode 0600 (found ${mode.toString(8)})`);
22633
22863
  }
@@ -23318,10 +23548,10 @@ var init_changelog = __esm(() => {
23318
23548
  });
23319
23549
 
23320
23550
  // packages/workit-core/src/core/hygiene.ts
23321
- import { existsSync as existsSync7, readFileSync as readFileSync8, writeFileSync as writeFileSync4 } from "node:fs";
23551
+ import { existsSync as existsSync8, readFileSync as readFileSync8, writeFileSync as writeFileSync4 } from "node:fs";
23322
23552
  import path13 from "node:path";
23323
23553
  var repoRoot3, templatesDir = () => path13.join(repoRoot3, "templates", "hygiene"), packageJson = (root) => {
23324
- if (!existsSync7(path13.join(root, "package.json")))
23554
+ if (!existsSync8(path13.join(root, "package.json")))
23325
23555
  return null;
23326
23556
  try {
23327
23557
  return JSON.parse(readFileSync8(path13.join(root, "package.json"), "utf8"));
@@ -23329,7 +23559,7 @@ var repoRoot3, templatesDir = () => path13.join(repoRoot3, "templates", "hygiene
23329
23559
  return null;
23330
23560
  }
23331
23561
  }, isOpenSource = (root) => {
23332
- if (existsSync7(path13.join(root, "LICENSE")))
23562
+ if (existsSync8(path13.join(root, "LICENSE")))
23333
23563
  return true;
23334
23564
  const pkg = packageJson(root);
23335
23565
  if (pkg && !pkg.private)
@@ -23360,10 +23590,10 @@ var repoRoot3, templatesDir = () => path13.join(repoRoot3, "templates", "hygiene
23360
23590
  "CONTRIBUTING.md"
23361
23591
  ]) {
23362
23592
  if (file === "LICENSE" || file === "CONTRIBUTING.md") {
23363
- state[file] = openSource ? existsSync7(path13.join(root, file)) ? "ok" : "missing" : "skip";
23593
+ state[file] = openSource ? existsSync8(path13.join(root, file)) ? "ok" : "missing" : "skip";
23364
23594
  continue;
23365
23595
  }
23366
- if (!existsSync7(path13.join(root, file))) {
23596
+ if (!existsSync8(path13.join(root, file))) {
23367
23597
  state[file] = "missing";
23368
23598
  continue;
23369
23599
  }
@@ -23382,10 +23612,10 @@ var repoRoot3, templatesDir = () => path13.join(repoRoot3, "templates", "hygiene
23382
23612
  files.push("LICENSE", "CONTRIBUTING.md");
23383
23613
  const planned = [];
23384
23614
  for (const file of files) {
23385
- if (existsSync7(path13.join(root, file)))
23615
+ if (existsSync8(path13.join(root, file)))
23386
23616
  continue;
23387
23617
  const tpl = path13.join(templatesDir(), file);
23388
- if (!existsSync7(tpl))
23618
+ if (!existsSync8(tpl))
23389
23619
  continue;
23390
23620
  const content = readFileSync8(tpl, "utf8").replace(/<PROJECT>/g, path13.basename(root)).replace(/<YEAR>/g, String(new Date().getFullYear())).replace(/<HOLDER>\s*/g, licenseHolder(root));
23391
23621
  planned.push({ path: path13.join(root, file), content });
@@ -23408,12 +23638,12 @@ var init_hygiene = __esm(() => {
23408
23638
  });
23409
23639
 
23410
23640
  // packages/workit-core/src/core/docs-layout.ts
23411
- import { existsSync as existsSync8, lstatSync, mkdirSync as mkdirSync5, realpathSync as realpathSync2, statSync as statSync4 } from "node:fs";
23641
+ import { existsSync as existsSync9, lstatSync, mkdirSync as mkdirSync5, realpathSync as realpathSync2, statSync as statSync5 } from "node:fs";
23412
23642
  import path14 from "node:path";
23413
23643
  var SLUG_RE, LEGACY_SLUG = "superpowers", posix = (p) => p.split(path14.sep).join("/"), canonicalize = (base, candidate) => {
23414
23644
  const abs = path14.resolve(base, candidate);
23415
23645
  let ancestor = abs;
23416
- while (!existsSync8(ancestor))
23646
+ while (!existsSync9(ancestor))
23417
23647
  ancestor = path14.dirname(ancestor);
23418
23648
  let real;
23419
23649
  try {
@@ -23442,8 +23672,8 @@ var SLUG_RE, LEGACY_SLUG = "superpowers", posix = (p) => p.split(path14.sep).joi
23442
23672
  sdd: path14.join(dir, "sdd")
23443
23673
  };
23444
23674
  }, probeLegacyDocs = (workspace) => ({
23445
- legacy_sdd: existsSync8(path14.join(workspace, ".superpowers", "sdd")),
23446
- superpowers_dir: existsSync8(path14.join(workspace, "docs", LEGACY_SLUG))
23675
+ legacy_sdd: existsSync9(path14.join(workspace, ".superpowers", "sdd")),
23676
+ superpowers_dir: existsSync9(path14.join(workspace, "docs", LEGACY_SLUG))
23447
23677
  }), resolveCanonicalLayout = (input) => {
23448
23678
  const { workspace_root, slug, spec_path, plan_path } = input;
23449
23679
  if (!workspace_root)
@@ -23536,11 +23766,11 @@ var SLUG_RE, LEGACY_SLUG = "superpowers", posix = (p) => p.split(path14.sep).joi
23536
23766
  const { layout } = resolved;
23537
23767
  const created = [];
23538
23768
  const ensure = (dir) => {
23539
- if (!existsSync8(dir)) {
23769
+ if (!existsSync9(dir)) {
23540
23770
  mkdirSync5(dir, { recursive: true });
23541
23771
  const rel = posix(path14.relative(layout.workspace, dir));
23542
23772
  created.push(rel || ".");
23543
- } else if (!statSync4(dir).isDirectory()) {
23773
+ } else if (!statSync5(dir).isDirectory()) {
23544
23774
  throw new Error(`path exists but is not a directory: ${posix(path14.relative(layout.workspace, dir))}`);
23545
23775
  }
23546
23776
  };
@@ -23587,7 +23817,7 @@ var init_docs_layout = __esm(() => {
23587
23817
  });
23588
23818
 
23589
23819
  // packages/workit-core/src/core/docs-validate.ts
23590
- import { existsSync as existsSync9, readFileSync as readFileSync9 } from "node:fs";
23820
+ import { existsSync as existsSync10, readFileSync as readFileSync9 } from "node:fs";
23591
23821
  import { execFileSync as execFileSync3 } from "node:child_process";
23592
23822
  import path15 from "node:path";
23593
23823
  var BRANCH_RE, SPEC_LINK_RE, TASK_RE, err = (code, message, path16) => {
@@ -23840,7 +24070,7 @@ var BRANCH_RE, SPEC_LINK_RE, TASK_RE, err = (code, message, path16) => {
23840
24070
  return findings;
23841
24071
  }, sddIgnored = (cwd, slug) => {
23842
24072
  const sddDir = path15.join(cwd, "docs", slug, "sdd");
23843
- if (!existsSync9(sddDir))
24073
+ if (!existsSync10(sddDir))
23844
24074
  return true;
23845
24075
  try {
23846
24076
  execFileSync3("git", ["-C", cwd, "rev-parse", "--is-inside-work-tree"], { stdio: "pipe" });
@@ -23920,11 +24150,11 @@ var init_plan_tasks = __esm(() => {
23920
24150
  var init_core3 = () => {};
23921
24151
 
23922
24152
  // packages/workit-core/src/core/handoff-context.ts
23923
- import { existsSync as existsSync10, readFileSync as readFileSync11, readdirSync as readdirSync5, statSync as statSync5 } from "node:fs";
24153
+ import { existsSync as existsSync11, readFileSync as readFileSync11, readdirSync as readdirSync6, statSync as statSync6 } from "node:fs";
23924
24154
  import path17 from "node:path";
23925
24155
  var DOC_RE, listMd = (dir) => {
23926
24156
  try {
23927
- return readdirSync5(dir).filter((f) => f.endsWith(".md")).sort();
24157
+ return readdirSync6(dir).filter((f) => f.endsWith(".md")).sort();
23928
24158
  } catch {
23929
24159
  return [];
23930
24160
  }
@@ -23938,7 +24168,7 @@ var DOC_RE, listMd = (dir) => {
23938
24168
  const slug = slugs[0];
23939
24169
  const plan = `docs/${slug}/plan.md`;
23940
24170
  const spec = `docs/${slug}/spec.md`;
23941
- if (!existsSync10(path17.join(root, plan)) || !existsSync10(path17.join(root, spec))) {
24171
+ if (!existsSync11(path17.join(root, plan)) || !existsSync11(path17.join(root, spec))) {
23942
24172
  return { error: `docs/${slug}/ must contain both plan.md and spec.md` };
23943
24173
  }
23944
24174
  return { spec, plan, source: "message_paths" };
@@ -23947,7 +24177,7 @@ var DOC_RE, listMd = (dir) => {
23947
24177
  let best = null;
23948
24178
  let entries = [];
23949
24179
  try {
23950
- entries = readdirSync5(docsDir);
24180
+ entries = readdirSync6(docsDir);
23951
24181
  } catch {
23952
24182
  return { error: "no pair" };
23953
24183
  }
@@ -23956,9 +24186,9 @@ var DOC_RE, listMd = (dir) => {
23956
24186
  continue;
23957
24187
  const plan = path17.join("docs", slug, "plan.md");
23958
24188
  const spec = path17.join("docs", slug, "spec.md");
23959
- if (!existsSync10(path17.join(root, plan)) || !existsSync10(path17.join(root, spec)))
24189
+ if (!existsSync11(path17.join(root, plan)) || !existsSync11(path17.join(root, spec)))
23960
24190
  continue;
23961
- const score = Math.max(statSync5(path17.join(root, spec)).mtimeMs, statSync5(path17.join(root, plan)).mtimeMs);
24191
+ const score = Math.max(statSync6(path17.join(root, spec)).mtimeMs, statSync6(path17.join(root, plan)).mtimeMs);
23962
24192
  if (best === null || score > best.score || score === best.score && slug < best.spec.split("/")[1]) {
23963
24193
  best = { score, spec, plan, source: "active_pair" };
23964
24194
  }
@@ -23976,7 +24206,7 @@ var DOC_RE, listMd = (dir) => {
23976
24206
  if (!("error" in active))
23977
24207
  return active;
23978
24208
  const docsDir = path17.join(root, "docs");
23979
- if (!existsSync10(docsDir) || listMd(docsDir).length === 0) {
24209
+ if (!existsSync11(docsDir) || listMd(docsDir).length === 0) {
23980
24210
  return { error: "no docs/<slug>/ features found under docs/" };
23981
24211
  }
23982
24212
  return {
@@ -24051,10 +24281,10 @@ var init_handoff_tools = __esm(() => {
24051
24281
  // packages/workit-core/src/core/sdd.ts
24052
24282
  import {
24053
24283
  appendFileSync as appendFileSync2,
24054
- existsSync as existsSync11,
24284
+ existsSync as existsSync12,
24055
24285
  mkdirSync as mkdirSync6,
24056
24286
  readFileSync as readFileSync12,
24057
- statSync as statSync6,
24287
+ statSync as statSync7,
24058
24288
  writeFileSync as writeFileSync5
24059
24289
  } from "node:fs";
24060
24290
  import { execFileSync as execFileSync4 } from "node:child_process";
@@ -24078,7 +24308,7 @@ function ledgerCompletion(root, slug) {
24078
24308
  let started = false;
24079
24309
  const completed = [];
24080
24310
  const absProgress = path19.join(root, "docs", slug, "sdd", "progress.md");
24081
- if (existsSync11(absProgress)) {
24311
+ if (existsSync12(absProgress)) {
24082
24312
  try {
24083
24313
  for (const line of readFileSync12(absProgress, "utf8").split(`
24084
24314
  `)) {
@@ -24094,7 +24324,7 @@ function ledgerCompletion(root, slug) {
24094
24324
  const required2 = [];
24095
24325
  try {
24096
24326
  const absPlan = path19.join(root, "docs", slug, "plan.md");
24097
- if (existsSync11(absPlan)) {
24327
+ if (existsSync12(absPlan)) {
24098
24328
  for (const task of parseTasksFromPlan(readFileSync12(absPlan, "utf8")))
24099
24329
  required2.push(task.id);
24100
24330
  }
@@ -24127,7 +24357,7 @@ function sddContext({
24127
24357
  let progress_lines = [];
24128
24358
  let completed_task_ids = [];
24129
24359
  const absProgress = path19.join(resolved.layout.sdd, "progress.md");
24130
- if (existsSync11(absProgress)) {
24360
+ if (existsSync12(absProgress)) {
24131
24361
  progress_lines = readFileSync12(absProgress, "utf8").split(`
24132
24362
  `).map((ln) => ln.trim()).filter(Boolean);
24133
24363
  const pat = /^Task\s+(\d+):\s+complete\b/i;
@@ -24135,7 +24365,7 @@ function sddContext({
24135
24365
  }
24136
24366
  let manifest = {};
24137
24367
  const absManifest = path19.join(resolved.layout.sdd, "manifest.json");
24138
- if (existsSync11(absManifest)) {
24368
+ if (existsSync12(absManifest)) {
24139
24369
  try {
24140
24370
  manifest = JSON.parse(readFileSync12(absManifest, "utf8"));
24141
24371
  } catch {
@@ -24143,7 +24373,7 @@ function sddContext({
24143
24373
  }
24144
24374
  }
24145
24375
  const legacy_path = path19.join(cwd, ".superpowers/sdd");
24146
- const legacy_exists = existsSync11(legacy_path);
24376
+ const legacy_exists = existsSync12(legacy_path);
24147
24377
  let todos = [];
24148
24378
  let task_count = 0;
24149
24379
  if (plan_path) {
@@ -24174,7 +24404,7 @@ function sddContext({
24174
24404
  progress_lines,
24175
24405
  completed_task_ids,
24176
24406
  manifest,
24177
- created: existsSync11(path19.join(cwd, sdd_dir)),
24407
+ created: existsSync12(path19.join(cwd, sdd_dir)),
24178
24408
  forbidden_legacy_path: ".superpowers/sdd",
24179
24409
  legacy_sdd_exists: legacy_exists,
24180
24410
  warning: legacy_exists ? "Ignore .superpowers/sdd — use sdd_dir from this tool only" : undefined,
@@ -24257,7 +24487,7 @@ function sddAppendProgress({
24257
24487
  if (!match || match[1].toLowerCase() === match[2].toLowerCase()) {
24258
24488
  return { error: "invalid progress line format" };
24259
24489
  }
24260
- if (existsSync11(path_) && statSync6(path_).isDirectory()) {
24490
+ if (existsSync12(path_) && statSync7(path_).isDirectory()) {
24261
24491
  return { error: `progress path is a directory: ${progress_path}` };
24262
24492
  }
24263
24493
  mkdirSync6(path19.dirname(path_), { recursive: true });
@@ -24305,7 +24535,7 @@ function sddAppendAdvisory({
24305
24535
  if (!contained.ok)
24306
24536
  return { error: contained.error, code: "advisory_path_invalid" };
24307
24537
  const abs = contained.path;
24308
- if (existsSync11(abs) && statSync6(abs).isDirectory()) {
24538
+ if (existsSync12(abs) && statSync7(abs).isDirectory()) {
24309
24539
  return {
24310
24540
  error: `advisory target is a directory: ${advisories_path}`,
24311
24541
  code: "advisory_target_invalid"
@@ -24333,20 +24563,20 @@ var init_menu = () => {};
24333
24563
  // packages/workit-core/src/core/flow-state.ts
24334
24564
  import {
24335
24565
  closeSync,
24336
- existsSync as existsSync12,
24566
+ existsSync as existsSync13,
24337
24567
  fstatSync,
24338
24568
  fsyncSync,
24339
24569
  mkdirSync as mkdirSync7,
24340
24570
  openSync,
24341
- readdirSync as readdirSync6,
24571
+ readdirSync as readdirSync7,
24342
24572
  readFileSync as readFileSync13,
24343
- renameSync,
24344
- rmSync,
24345
- statSync as statSync7,
24573
+ renameSync as renameSync2,
24574
+ rmSync as rmSync2,
24575
+ statSync as statSync8,
24346
24576
  unlinkSync as unlinkSync3,
24347
24577
  writeFileSync as writeFileSync6
24348
24578
  } from "node:fs";
24349
- import { createHash } from "node:crypto";
24579
+ import { createHash as createHash2 } from "node:crypto";
24350
24580
  import path20 from "node:path";
24351
24581
 
24352
24582
  class HostReceiptStore {
@@ -24500,7 +24730,7 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
24500
24730
  updated_at: Date.now()
24501
24731
  }), readFlowState = (root, slug) => {
24502
24732
  const file = flowPath(root, slug);
24503
- if (!existsSync12(file))
24733
+ if (!existsSync13(file))
24504
24734
  return emptyState(slug);
24505
24735
  try {
24506
24736
  return normalizeState(JSON.parse(readFileSync13(file, "utf8")), slug);
@@ -24635,7 +24865,7 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
24635
24865
  }, readFlowStrict = (root, slug) => {
24636
24866
  const file = flowPath(root, slug);
24637
24867
  const rel = path20.posix.join("docs", slug, "sdd", "flow.json");
24638
- if (!existsSync12(file)) {
24868
+ if (!existsSync13(file)) {
24639
24869
  return err2("flow_not_activated", `flow not activated for ${slug} — run workit_flow_status first`);
24640
24870
  }
24641
24871
  let text;
@@ -24670,26 +24900,26 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
24670
24900
  fsyncSync(fd);
24671
24901
  closeSync(fd);
24672
24902
  fd = null;
24673
- renameSync(tmp, file);
24903
+ renameSync2(tmp, file);
24674
24904
  } finally {
24675
24905
  try {
24676
24906
  if (fd !== null)
24677
24907
  closeSync(fd);
24678
24908
  } catch {}
24679
24909
  try {
24680
- if (existsSync12(tmp))
24681
- rmSync(tmp, { force: true });
24910
+ if (existsSync13(tmp))
24911
+ rmSync2(tmp, { force: true });
24682
24912
  } catch {}
24683
24913
  }
24684
24914
  }, MAX_WRITE_ATTEMPTS = 5, STALE_LOCK_MS = 1000, lockMtimeMs = (lock) => {
24685
24915
  try {
24686
- return statSync7(lock).mtimeMs;
24916
+ return statSync8(lock).mtimeMs;
24687
24917
  } catch {
24688
24918
  return null;
24689
24919
  }
24690
24920
  }, lockOwnedBy = (fd, lock) => {
24691
24921
  try {
24692
- return fstatSync(fd).ino === statSync7(lock).ino;
24922
+ return fstatSync(fd).ino === statSync8(lock).ino;
24693
24923
  } catch {
24694
24924
  return false;
24695
24925
  }
@@ -24704,7 +24934,7 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
24704
24934
  const tmp = uniqueTempPath(file);
24705
24935
  let fd = null;
24706
24936
  try {
24707
- const currentText = existsSync12(file) ? readFileSync13(file, "utf8") : null;
24937
+ const currentText = existsSync13(file) ? readFileSync13(file, "utf8") : null;
24708
24938
  if (currentText !== expectedText)
24709
24939
  return { ok: false, conflict: true };
24710
24940
  mkdirSync7(path20.dirname(file), { recursive: true });
@@ -24713,10 +24943,10 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
24713
24943
  fsyncSync(fd);
24714
24944
  closeSync(fd);
24715
24945
  fd = null;
24716
- const reRead = existsSync12(file) ? readFileSync13(file, "utf8") : null;
24946
+ const reRead = existsSync13(file) ? readFileSync13(file, "utf8") : null;
24717
24947
  if (reRead !== expectedText)
24718
24948
  return { ok: false, conflict: true };
24719
- renameSync(tmp, file);
24949
+ renameSync2(tmp, file);
24720
24950
  return { ok: true };
24721
24951
  } catch (error2) {
24722
24952
  return { ok: false, io_error: error2 instanceof Error ? error2.message : String(error2) };
@@ -24726,8 +24956,8 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
24726
24956
  closeSync(fd);
24727
24957
  } catch {}
24728
24958
  try {
24729
- if (existsSync12(tmp))
24730
- rmSync(tmp, { force: true });
24959
+ if (existsSync13(tmp))
24960
+ rmSync2(tmp, { force: true });
24731
24961
  } catch {}
24732
24962
  }
24733
24963
  }, readCanonicalDigest = (root, rel) => {
@@ -24747,7 +24977,7 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
24747
24977
  } catch {
24748
24978
  return { ok: false, code: "document_unreadable" };
24749
24979
  }
24750
- return { ok: true, text, digest: createHash("sha256").update(bytes).digest("hex") };
24980
+ return { ok: true, text, digest: createHash2("sha256").update(bytes).digest("hex") };
24751
24981
  }, resetForSpecDrift = (state) => ({
24752
24982
  ...state,
24753
24983
  spec: { ...state.spec, status: "draft", evidence: null, approved_digest: null },
@@ -24816,11 +25046,11 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
24816
25046
  return { state, changed: false };
24817
25047
  }, withFlowLock = (file, fn) => {
24818
25048
  const lock = `${file}.lock`;
24819
- if (!existsSync12(path20.dirname(file)))
25049
+ if (!existsSync13(path20.dirname(file)))
24820
25050
  return { locked: true, value: fn() };
24821
25051
  try {
24822
- if (existsSync12(`${lock}.stale`))
24823
- rmSync(`${lock}.stale`, { force: true });
25052
+ if (existsSync13(`${lock}.stale`))
25053
+ rmSync2(`${lock}.stale`, { force: true });
24824
25054
  } catch {}
24825
25055
  const wait = new Int32Array(new SharedArrayBuffer(4));
24826
25056
  let fd = null;
@@ -24839,7 +25069,7 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
24839
25069
  const mtime = lockMtimeMs(lock);
24840
25070
  if (mtime !== null && Date.now() - mtime > STALE_LOCK_MS) {
24841
25071
  try {
24842
- renameSync(lock, `${lock}.stale`);
25072
+ renameSync2(lock, `${lock}.stale`);
24843
25073
  unlinkSync3(`${lock}.stale`);
24844
25074
  } catch {}
24845
25075
  try {
@@ -24875,7 +25105,7 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
24875
25105
  } finally {
24876
25106
  try {
24877
25107
  if (fd !== null && lockOwnedBy(fd, lock))
24878
- rmSync(lock, { force: true });
25108
+ rmSync2(lock, { force: true });
24879
25109
  } catch {}
24880
25110
  try {
24881
25111
  if (fd !== null)
@@ -25073,7 +25303,7 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
25073
25303
  const planPath = path20.posix.join("docs", slug, "plan.md");
25074
25304
  const file = flowPath(root, slug);
25075
25305
  const locked = withFlowLock(file, () => {
25076
- if (!existsSync12(file)) {
25306
+ if (!existsSync13(file)) {
25077
25307
  writeFlowFileAtomic(file, {
25078
25308
  slug,
25079
25309
  activated: true,
@@ -25113,7 +25343,7 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
25113
25343
  return err2("path_invalid", doc2.error);
25114
25344
  const relPath = path20.posix.join("docs", slug, "spec.md");
25115
25345
  return readModifyWrite(root, slug, (state) => {
25116
- if (!existsSync12(doc2.path))
25346
+ if (!existsSync13(doc2.path))
25117
25347
  return err2("spec_missing", `spec not found: ${specPath}`);
25118
25348
  if (state.spec.status === "draft" || state.spec.status === "self_reviewed") {
25119
25349
  const digest = readCanonicalDigest(root, relPath);
@@ -25157,7 +25387,7 @@ var COORDINATOR_RECOVERY_TEXT, CURSOR_SUBAGENT_UNSUPPORTED_TEXT, MENU_CHOICES, e
25157
25387
  return err2("path_invalid", doc2.error);
25158
25388
  const relPath = path20.posix.join("docs", slug, "plan.md");
25159
25389
  return readModifyWrite(root, slug, (state) => {
25160
- if (!existsSync12(doc2.path))
25390
+ if (!existsSync13(doc2.path))
25161
25391
  return err2("plan_missing", `plan not found: ${planPath}`);
25162
25392
  if (state.spec.status !== "approved") {
25163
25393
  return err2("spec_not_approved", "spec must be approved before the plan can be approved");
@@ -25593,15 +25823,15 @@ var init_flow_evidence = __esm(() => {
25593
25823
  // packages/workit-core/src/core/docs-migration.ts
25594
25824
  import { execFileSync as execFileSync5 } from "node:child_process";
25595
25825
  import {
25596
- existsSync as existsSync13,
25826
+ existsSync as existsSync14,
25597
25827
  lstatSync as lstatSync2,
25598
25828
  mkdirSync as mkdirSync8,
25599
- readdirSync as readdirSync7,
25829
+ readdirSync as readdirSync8,
25600
25830
  readFileSync as readFileSync14,
25601
25831
  realpathSync as realpathSync3,
25602
- renameSync as renameSync2,
25603
- rmSync as rmSync2,
25604
- statSync as statSync8,
25832
+ renameSync as renameSync3,
25833
+ rmSync as rmSync3,
25834
+ statSync as statSync9,
25605
25835
  writeFileSync as writeFileSync7
25606
25836
  } from "node:fs";
25607
25837
  import path21 from "node:path";
@@ -25640,14 +25870,14 @@ var LEGACY_DIR = "docs/superpowers", MIGRATION_CHOICES, SLUG_RE3, RESERVED_SLUG
25640
25870
  }, detectLegacyDocs = (workspace_root) => {
25641
25871
  const root = legacyRoot(workspace_root);
25642
25872
  const raw = [];
25643
- if (existsSync13(root)) {
25644
- for (const entry of readdirSync7(root, { withFileTypes: true })) {
25873
+ if (existsSync14(root)) {
25874
+ for (const entry of readdirSync8(root, { withFileTypes: true })) {
25645
25875
  const abs = path21.join(root, entry.name);
25646
25876
  const rel = posix3(path21.relative(workspace_root, abs));
25647
25877
  if (entry.isDirectory()) {
25648
- const hasSpec = existsSync13(path21.join(abs, "spec.md"));
25649
- const hasPlan = existsSync13(path21.join(abs, "plan.md"));
25650
- if (!hasSpec && !hasPlan && !existsSync13(path21.join(abs, "sdd")))
25878
+ const hasSpec = existsSync14(path21.join(abs, "spec.md"));
25879
+ const hasPlan = existsSync14(path21.join(abs, "plan.md"));
25880
+ if (!hasSpec && !hasPlan && !existsSync14(path21.join(abs, "sdd")))
25651
25881
  continue;
25652
25882
  const explicit = explicitTargetSlug(hasPlan ? readFileSafe(path21.join(abs, "plan.md")) : null);
25653
25883
  raw.push({
@@ -25655,7 +25885,7 @@ var LEGACY_DIR = "docs/superpowers", MIGRATION_CHOICES, SLUG_RE3, RESERVED_SLUG
25655
25885
  legacy_dir: rel,
25656
25886
  spec: hasSpec ? posix3(path21.join(rel, "spec.md")) : null,
25657
25887
  plan: hasPlan ? posix3(path21.join(rel, "plan.md")) : null,
25658
- sdd: existsSync13(path21.join(abs, "sdd")),
25888
+ sdd: existsSync14(path21.join(abs, "sdd")),
25659
25889
  explicit: explicit !== null
25660
25890
  });
25661
25891
  } else if (entry.name === "spec.md" || entry.name === "plan.md") {
@@ -25775,7 +26005,7 @@ var LEGACY_DIR = "docs/superpowers", MIGRATION_CHOICES, SLUG_RE3, RESERVED_SLUG
25775
26005
  if (visits.has(real))
25776
26006
  return { ok: true };
25777
26007
  visits.add(real);
25778
- for (const entry of readdirSync7(real, { withFileTypes: true })) {
26008
+ for (const entry of readdirSync8(real, { withFileTypes: true })) {
25779
26009
  const fromAbs = path21.join(real, entry.name);
25780
26010
  const fromRel = posix3(path21.join(legacyRel, entry.name));
25781
26011
  const toRel = posix3(path21.join(destRelRoot, entry.name));
@@ -25795,7 +26025,7 @@ var LEGACY_DIR = "docs/superpowers", MIGRATION_CHOICES, SLUG_RE3, RESERVED_SLUG
25795
26025
  if (target !== workspaceReal && !target.startsWith(workspaceReal + path21.sep)) {
25796
26026
  return { ok: false, error: `symlink escape refused: ${fromRel}` };
25797
26027
  }
25798
- if (statSync8(target).isDirectory()) {
26028
+ if (statSync9(target).isDirectory()) {
25799
26029
  const sub = planTree(workspace, fromAbs, fromRel, toRel, path21.join(destAbsRoot, entry.name), legacyName, slug, plan, visits);
25800
26030
  if (!sub.ok)
25801
26031
  return sub;
@@ -25898,7 +26128,7 @@ var LEGACY_DIR = "docs/superpowers", MIGRATION_CHOICES, SLUG_RE3, RESERVED_SLUG
25898
26128
  }
25899
26129
  const collisions = [];
25900
26130
  for (const item of plan) {
25901
- if (!existsSync13(item.destAbs))
26131
+ if (!existsSync14(item.destAbs))
25902
26132
  continue;
25903
26133
  let identical = false;
25904
26134
  try {
@@ -25939,10 +26169,10 @@ var LEGACY_DIR = "docs/superpowers", MIGRATION_CHOICES, SLUG_RE3, RESERVED_SLUG
25939
26169
  try {
25940
26170
  mkdirSync8(path21.dirname(item.destAbs), { recursive: true });
25941
26171
  writeFileSync7(tmp, item.bytes);
25942
- renameSync2(tmp, item.destAbs);
26172
+ renameSync3(tmp, item.destAbs);
25943
26173
  } catch (error2) {
25944
26174
  try {
25945
- rmSync2(tmp, { force: true });
26175
+ rmSync3(tmp, { force: true });
25946
26176
  } catch {}
25947
26177
  return abort(`legacy migration retry required: failed to copy ${item.fromRel}: ${error2 instanceof Error ? error2.message : String(error2)}`);
25948
26178
  }
@@ -25964,7 +26194,7 @@ var init_docs_migration = __esm(() => {
25964
26194
  });
25965
26195
 
25966
26196
  // packages/workit-core/src/core/docs-repo.ts
25967
- import { existsSync as existsSync14, mkdirSync as mkdirSync9, readFileSync as readFileSync15, writeFileSync as writeFileSync8, readdirSync as readdirSync8 } from "node:fs";
26197
+ import { existsSync as existsSync15, mkdirSync as mkdirSync9, readFileSync as readFileSync15, writeFileSync as writeFileSync8, readdirSync as readdirSync9 } from "node:fs";
25968
26198
  import { execFileSync as execFileSync6 } from "node:child_process";
25969
26199
  import path22 from "node:path";
25970
26200
  var configPath = () => process.env.WORKFLOW_DOCS_REPO_CONFIG ?? path22.join(configDir(), "docs-repo.json"), readDocsRepoConfig = () => {
@@ -25980,7 +26210,7 @@ var configPath = () => process.env.WORKFLOW_DOCS_REPO_CONFIG ?? path22.join(conf
25980
26210
  writeFileSync8(file, JSON.stringify({ path: docsPath }, null, 2) + `
25981
26211
  `, "utf8");
25982
26212
  }, docsRepoPath = () => readDocsRepoConfig()?.path ?? null, validateDocsRepo = (docsPath) => {
25983
- if (!existsSync14(docsPath))
26213
+ if (!existsSync15(docsPath))
25984
26214
  return { ok: false, error: `docs repo path does not exist: ${docsPath}` };
25985
26215
  try {
25986
26216
  execFileSync6("git", ["-C", docsPath, "rev-parse", "--is-inside-work-tree"], { stdio: "pipe" });
@@ -25988,7 +26218,7 @@ var configPath = () => process.env.WORKFLOW_DOCS_REPO_CONFIG ?? path22.join(conf
25988
26218
  return { ok: false, error: `docs repo is not a git repository: ${docsPath}` };
25989
26219
  }
25990
26220
  const featuresDir = path22.join(docsPath, "features");
25991
- if (!existsSync14(featuresDir))
26221
+ if (!existsSync15(featuresDir))
25992
26222
  mkdirSync9(featuresDir, { recursive: true });
25993
26223
  return { ok: true };
25994
26224
  }, linkDocsRepo = (docsPath, confirmed) => {
@@ -26003,19 +26233,19 @@ var configPath = () => process.env.WORKFLOW_DOCS_REPO_CONFIG ?? path22.join(conf
26003
26233
  const repoPath = docsRepoPath();
26004
26234
  const specs = [];
26005
26235
  const docsDir = path22.join(workspaceRoot, "docs");
26006
- if (existsSync14(docsDir)) {
26007
- for (const slug of readdirSync8(docsDir)) {
26236
+ if (existsSync15(docsDir)) {
26237
+ for (const slug of readdirSync9(docsDir)) {
26008
26238
  if (slug.startsWith("."))
26009
26239
  continue;
26010
26240
  const spec = path22.posix.join("docs", slug, "spec.md");
26011
- if (!existsSync14(path22.join(workspaceRoot, spec)))
26241
+ if (!existsSync15(path22.join(workspaceRoot, spec)))
26012
26242
  continue;
26013
26243
  let promoted = false;
26014
26244
  let target = null;
26015
26245
  if (repoPath) {
26016
26246
  const featuresDir = path22.join(repoPath, "features");
26017
- if (existsSync14(featuresDir)) {
26018
- const match = readdirSync8(featuresDir).find((d) => new RegExp(`^20\\d{2}-\\d{2}-${slug}$`).test(d));
26247
+ if (existsSync15(featuresDir)) {
26248
+ const match = readdirSync9(featuresDir).find((d) => new RegExp(`^20\\d{2}-\\d{2}-${slug}$`).test(d));
26019
26249
  if (match) {
26020
26250
  promoted = true;
26021
26251
  target = path22.join(repoPath, "features", match);
@@ -26084,7 +26314,7 @@ var configPath = () => process.env.WORKFLOW_DOCS_REPO_CONFIG ?? path22.join(conf
26084
26314
  }
26085
26315
  if (!opts.force) {
26086
26316
  const sddDir = path22.join(workspaceRootCanonical, "docs", slug, "sdd");
26087
- if (existsSync14(sddDir)) {
26317
+ if (existsSync15(sddDir)) {
26088
26318
  try {
26089
26319
  execFileSync6("git", [
26090
26320
  "-C",
@@ -26102,7 +26332,7 @@ var configPath = () => process.env.WORKFLOW_DOCS_REPO_CONFIG ?? path22.join(conf
26102
26332
  }
26103
26333
  const prefix = monthPrefix();
26104
26334
  const featuresDir = path22.join(repoPath, "features");
26105
- const existing = existsSync14(featuresDir) ? readdirSync8(featuresDir).find((d) => new RegExp(`^20\\d{2}-\\d{2}-${slug}$`).test(d)) : undefined;
26335
+ const existing = existsSync15(featuresDir) ? readdirSync9(featuresDir).find((d) => new RegExp(`^20\\d{2}-\\d{2}-${slug}$`).test(d)) : undefined;
26106
26336
  const targetDir = path22.join(featuresDir, existing ?? `${prefix}-${slug}`);
26107
26337
  mkdirSync9(targetDir, { recursive: true });
26108
26338
  const files = ["spec.md"];
@@ -26164,13 +26394,13 @@ var init_docs_repo = __esm(() => {
26164
26394
  });
26165
26395
 
26166
26396
  // packages/workit-core/src/core/gitignore.ts
26167
- import { existsSync as existsSync15, readFileSync as readFileSync16, writeFileSync as writeFileSync9 } from "node:fs";
26397
+ import { existsSync as existsSync16, readFileSync as readFileSync16, writeFileSync as writeFileSync9 } from "node:fs";
26168
26398
  import path23 from "node:path";
26169
26399
  var GITIGNORE_ENTRIES, ensureProjectGitignore = (workspaceRoot, confirmed) => {
26170
26400
  if (!confirmed)
26171
26401
  return { ok: false, error: "confirmed: true required" };
26172
26402
  const file = path23.join(workspaceRoot, ".gitignore");
26173
- const existing = existsSync15(file) ? readFileSync16(file, "utf8") : "";
26403
+ const existing = existsSync16(file) ? readFileSync16(file, "utf8") : "";
26174
26404
  const existingLines = new Set(existing.split(`
26175
26405
  `).map((l) => l.trim()).filter(Boolean));
26176
26406
  const added = [];
@@ -26189,7 +26419,7 @@ var GITIGNORE_ENTRIES, ensureProjectGitignore = (workspaceRoot, confirmed) => {
26189
26419
  ` : "") + append.join(`
26190
26420
  `) + `
26191
26421
  `, "utf8");
26192
- } else if (!existsSync15(file)) {
26422
+ } else if (!existsSync16(file)) {
26193
26423
  writeFileSync9(file, "", "utf8");
26194
26424
  }
26195
26425
  return { ok: true, path: file, added };
@@ -26214,11 +26444,11 @@ var init_gitignore = __esm(() => {
26214
26444
  });
26215
26445
 
26216
26446
  // packages/workit-core/src/core/templates.ts
26217
- import { existsSync as existsSync16, mkdirSync as mkdirSync10, readFileSync as readFileSync17, writeFileSync as writeFileSync10 } from "node:fs";
26447
+ import { existsSync as existsSync17, mkdirSync as mkdirSync10, readFileSync as readFileSync17, writeFileSync as writeFileSync10 } from "node:fs";
26218
26448
  import path24 from "node:path";
26219
26449
  var repoRoot4, templatePath = (name) => path24.join(configDir(), "templates", `${name}.md`), readTemplate = (name) => {
26220
26450
  const cfg = templatePath(name);
26221
- if (existsSync16(cfg))
26451
+ if (existsSync17(cfg))
26222
26452
  return { source: "config", content: readFileSync17(cfg, "utf8") };
26223
26453
  return {
26224
26454
  source: "repo",
@@ -26234,9 +26464,9 @@ var repoRoot4, templatePath = (name) => path24.join(configDir(), "templates", `$
26234
26464
  }, listTemplates = () => ["issue-update", "greeting", "headers"].map((name) => {
26235
26465
  const cfg = templatePath(name);
26236
26466
  const repoFile = path24.join(repoRoot4, "templates", `${name}.md`);
26237
- if (existsSync16(cfg))
26467
+ if (existsSync17(cfg))
26238
26468
  return { name, source: "config", path: cfg };
26239
- if (existsSync16(repoFile))
26469
+ if (existsSync17(repoFile))
26240
26470
  return { name, source: "repo", path: repoFile };
26241
26471
  return { name, source: "missing", path: cfg };
26242
26472
  });
@@ -26247,7 +26477,7 @@ var init_templates = __esm(() => {
26247
26477
  });
26248
26478
 
26249
26479
  // packages/workit-core/src/core/rules.ts
26250
- import { existsSync as existsSync17, mkdirSync as mkdirSync11, readFileSync as readFileSync18, readdirSync as readdirSync9, writeFileSync as writeFileSync11 } from "node:fs";
26480
+ import { existsSync as existsSync18, mkdirSync as mkdirSync11, readFileSync as readFileSync18, readdirSync as readdirSync10, writeFileSync as writeFileSync11 } from "node:fs";
26251
26481
  import path25 from "node:path";
26252
26482
  var rulesDir = () => path25.join(configDir(), "rules"), parseRule = (markdown) => {
26253
26483
  const fm = markdown.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
@@ -26276,10 +26506,10 @@ var rulesDir = () => path25.join(configDir(), "rules"), parseRule = (markdown) =
26276
26506
  }, listRules = () => {
26277
26507
  const result = [];
26278
26508
  const dir = rulesDir();
26279
- if (existsSync17(dir)) {
26280
- for (const entry of readdirSync9(dir)) {
26509
+ if (existsSync18(dir)) {
26510
+ for (const entry of readdirSync10(dir)) {
26281
26511
  const file = path25.join(dir, entry, "rule.md");
26282
- if (!existsSync17(file))
26512
+ if (!existsSync18(file))
26283
26513
  continue;
26284
26514
  const parsed = parseRule(readFileSync18(file, "utf8"));
26285
26515
  if ("error" in parsed)
@@ -26394,16 +26624,16 @@ var init_setup_state = __esm(() => {
26394
26624
 
26395
26625
  // packages/workit-core/src/core/setup.ts
26396
26626
  import {
26397
- copyFileSync as copyFileSync2,
26398
- cpSync as cpSync2,
26399
- existsSync as existsSync18,
26627
+ copyFileSync as copyFileSync3,
26628
+ cpSync as cpSync3,
26629
+ existsSync as existsSync19,
26400
26630
  mkdirSync as mkdirSync12,
26401
26631
  mkdtempSync,
26402
26632
  readFileSync as readFileSync19,
26403
- readdirSync as readdirSync10,
26404
- renameSync as renameSync3,
26405
- rmSync as rmSync3,
26406
- statSync as statSync9,
26633
+ readdirSync as readdirSync11,
26634
+ renameSync as renameSync4,
26635
+ rmSync as rmSync4,
26636
+ statSync as statSync10,
26407
26637
  writeFileSync as writeFileSync13
26408
26638
  } from "node:fs";
26409
26639
  import path26 from "node:path";
@@ -27999,7 +28229,8 @@ var init_server3 = __esm(async () => {
27999
28229
  sdd_dir,
28000
28230
  target_branch,
28001
28231
  stash,
28002
- workspace_root
28232
+ workspace_root,
28233
+ log: (message) => logger.info(message)
28003
28234
  });
28004
28235
  if (data.error)
28005
28236
  return jsonResult({ error: data.error });
@@ -28348,7 +28579,7 @@ var init_server3 = __esm(async () => {
28348
28579
  return jsonResult(result);
28349
28580
  }
28350
28581
  if (action === "config") {
28351
- if (locale !== undefined && !/^[a-z]{2,3}(-[A-Z]{2})?$/.test(locale)) {
28582
+ if (locale !== undefined && !/^[a-z]{2,3}(-(?:[A-Z]{2}|[0-9]{3}))?$/.test(locale)) {
28352
28583
  return jsonResult({
28353
28584
  error: `invalid locale: ${JSON.stringify(locale)} — expected BCP-47 like en or es-CL`
28354
28585
  });
@@ -28710,17 +28941,17 @@ var init_server3 = __esm(async () => {
28710
28941
  });
28711
28942
 
28712
28943
  // packages/workit-cursor/mcp/run-server.ts
28713
- import { existsSync as existsSync19, readFileSync as readFileSync21 } from "node:fs";
28944
+ import { existsSync as existsSync20, readFileSync as readFileSync21 } from "node:fs";
28714
28945
  import path29 from "node:path";
28715
28946
  import { fileURLToPath as fileURLToPath2 } from "node:url";
28716
28947
  var mcpDir = path29.dirname(fileURLToPath2(import.meta.url));
28717
28948
  var pluginDir = path29.resolve(mcpDir, "..");
28718
28949
  var marker = path29.join(pluginDir, ".workit-root");
28719
28950
  var resolveRoot = () => {
28720
- if (process.env.WORKFLOW_TOOLKIT_ROOT && existsSync19(path29.join(process.env.WORKFLOW_TOOLKIT_ROOT, "scripts"))) {
28951
+ if (process.env.WORKFLOW_TOOLKIT_ROOT && existsSync20(path29.join(process.env.WORKFLOW_TOOLKIT_ROOT, "scripts"))) {
28721
28952
  return process.env.WORKFLOW_TOOLKIT_ROOT;
28722
28953
  }
28723
- if (existsSync19(marker)) {
28954
+ if (existsSync20(marker)) {
28724
28955
  return readFileSync21(marker, "utf8").replace(/\n+$/, "");
28725
28956
  }
28726
28957
  return pluginDir;