@mstar-harness/cli 2.1.0 → 2.2.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.
Files changed (2) hide show
  1. package/dist/mstar-harness.js +121 -75
  2. package/package.json +2 -2
@@ -2344,13 +2344,24 @@ var require_commander = __commonJS((exports) => {
2344
2344
  });
2345
2345
 
2346
2346
  // src/index.ts
2347
- import { execFileSync as execFileSync6 } from "child_process";
2347
+ import { execFileSync as execFileSync7 } from "child_process";
2348
2348
  import fs7 from "fs";
2349
2349
  import path11 from "path";
2350
2350
 
2351
2351
  // ../../node_modules/@inquirer/core/dist/lib/key.js
2352
- var isUpKey = (key, keybindings = []) => key.name === "up" || keybindings.includes("vim") && key.name === "k" || keybindings.includes("emacs") && key.ctrl && key.name === "p";
2353
- var isDownKey = (key, keybindings = []) => key.name === "down" || keybindings.includes("vim") && key.name === "j" || keybindings.includes("emacs") && key.ctrl && key.name === "n";
2352
+ var keybindings = ["emacs", "vim"];
2353
+ var keybindingLookup = new Set(keybindings);
2354
+ function isKeybinding(value) {
2355
+ return keybindingLookup.has(value);
2356
+ }
2357
+ function getDefaultKeybindings() {
2358
+ const env = process.env["INQUIRER_KEYBINDINGS"];
2359
+ if (!env)
2360
+ return [];
2361
+ return Array.from(new Set(env.toLowerCase().split(/[\s,]+/).filter(isKeybinding)));
2362
+ }
2363
+ var isUpKey = (key, keybindings2 = []) => key.name === "up" || keybindings2.includes("vim") && key.name === "k" || keybindings2.includes("emacs") && key.ctrl && key.name === "p";
2364
+ var isDownKey = (key, keybindings2 = []) => key.name === "down" || keybindings2.includes("vim") && key.name === "j" || keybindings2.includes("emacs") && key.ctrl && key.name === "n";
2354
2365
  var isBackspaceKey = (key) => key.name === "backspace";
2355
2366
  var isNumberKey = (key) => "1234567890".includes(key.name);
2356
2367
  var isEnterKey = (key) => key.name === "enter" || key.name === "return";
@@ -2823,6 +2834,7 @@ var defaultTheme = {
2823
2834
  interval: 80,
2824
2835
  frames: ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"].map((frame) => styleText("yellow", frame))
2825
2836
  },
2837
+ keybindings: [],
2826
2838
  style: {
2827
2839
  answer: (text) => styleText("cyan", text),
2828
2840
  message: (text) => styleText("bold", text),
@@ -2833,6 +2845,12 @@ var defaultTheme = {
2833
2845
  key: (text) => styleText("cyan", styleText("bold", `<${text}>`))
2834
2846
  }
2835
2847
  };
2848
+ function getDefaultTheme() {
2849
+ return {
2850
+ ...defaultTheme,
2851
+ keybindings: getDefaultKeybindings()
2852
+ };
2853
+ }
2836
2854
 
2837
2855
  // ../../node_modules/@inquirer/core/dist/lib/make-theme.js
2838
2856
  function isPlainObject(value) {
@@ -2856,7 +2874,7 @@ function deepMerge(...objects) {
2856
2874
  }
2857
2875
  function makeTheme(...themes) {
2858
2876
  const themesToMerge = [
2859
- defaultTheme,
2877
+ getDefaultTheme(),
2860
2878
  ...themes.filter((theme) => theme != null)
2861
2879
  ];
2862
2880
  return deepMerge(...themesToMerge);
@@ -3273,7 +3291,7 @@ function wrapAnsi(string, columns, options) {
3273
3291
  // ../../node_modules/@inquirer/core/dist/lib/utils.js
3274
3292
  function breakLines(content, width) {
3275
3293
  return content.split(`
3276
- `).flatMap((line) => wrapAnsi(line, width, { trim: false, hard: true }).split(`
3294
+ `).flatMap((line) => wrapAnsi(line, width, { trim: false, wordWrap: false }).split(`
3277
3295
  `).map((str) => str.trimEnd())).join(`
3278
3296
  `);
3279
3297
  }
@@ -3638,6 +3656,7 @@ class ScreenManager {
3638
3656
  let output = cursorDown(this.extraLinesUnderPrompt);
3639
3657
  output += clearContent ? eraseLines(this.height) : `
3640
3658
  `;
3659
+ output += cursorLeft;
3641
3660
  output += cursorShow;
3642
3661
  this.write(output);
3643
3662
  this.rl.close();
@@ -3661,7 +3680,7 @@ class PromisePolyfill extends Promise {
3661
3680
  import path from "node:path";
3662
3681
  var nativeSetImmediate = globalThis.setImmediate;
3663
3682
  function getCallSites() {
3664
- const _prepareStackTrace = Error.prepareStackTrace;
3683
+ const savedPrepareStackTrace = Error.prepareStackTrace;
3665
3684
  let result = [];
3666
3685
  try {
3667
3686
  Error.prepareStackTrace = (_, callSites) => {
@@ -3673,7 +3692,7 @@ function getCallSites() {
3673
3692
  } catch {
3674
3693
  return result;
3675
3694
  }
3676
- Error.prepareStackTrace = _prepareStackTrace;
3695
+ Error.prepareStackTrace = savedPrepareStackTrace;
3677
3696
  return result;
3678
3697
  }
3679
3698
  function createPrompt(view) {
@@ -3792,8 +3811,7 @@ var selectTheme = {
3792
3811
  keysHelpTip: (keys) => keys.map(([key, action]) => `${styleText3("bold", key)} ${styleText3("dim", action)}`).join(styleText3("dim", " • "))
3793
3812
  },
3794
3813
  i18n: { disabledError: "This option is disabled and cannot be selected." },
3795
- indexMode: "hidden",
3796
- keybindings: []
3814
+ indexMode: "hidden"
3797
3815
  };
3798
3816
  function isSelectable(item) {
3799
3817
  return !Separator.isSeparator(item) && !item.disabled;
@@ -3830,11 +3848,11 @@ function normalizeChoices(choices) {
3830
3848
  var dist_default4 = createPrompt((config, done) => {
3831
3849
  const { loop = true, pageSize = 7 } = config;
3832
3850
  const theme = makeTheme(selectTheme, config.theme);
3833
- const { keybindings } = theme;
3851
+ const { keybindings: keybindings2 } = theme;
3834
3852
  const [status, setStatus] = useState("idle");
3835
3853
  const prefix = usePrefix({ status, theme });
3836
3854
  const searchTimeoutRef = useRef();
3837
- const searchEnabled = !keybindings.includes("vim");
3855
+ const searchEnabled = !keybindings2.includes("vim");
3838
3856
  const items = useMemo(() => normalizeChoices(config.choices), [config.choices]);
3839
3857
  const bounds = useMemo(() => {
3840
3858
  const first = items.findIndex(isNavigable);
@@ -3867,10 +3885,10 @@ var dist_default4 = createPrompt((config, done) => {
3867
3885
  setStatus("done");
3868
3886
  done(selectedChoice.value);
3869
3887
  }
3870
- } else if (isUpKey(key, keybindings) || isDownKey(key, keybindings)) {
3888
+ } else if (isUpKey(key, keybindings2) || isDownKey(key, keybindings2)) {
3871
3889
  rl.clearLine(0);
3872
- if (loop || isUpKey(key, keybindings) && active !== bounds.first || isDownKey(key, keybindings) && active !== bounds.last) {
3873
- const offset = isUpKey(key, keybindings) ? -1 : 1;
3890
+ if (loop || isUpKey(key, keybindings2) && active !== bounds.first || isDownKey(key, keybindings2) && active !== bounds.last) {
3891
+ const offset = isUpKey(key, keybindings2) ? -1 : 1;
3874
3892
  let next = active;
3875
3893
  do {
3876
3894
  next = (next + offset + items.length) % items.length;
@@ -3979,6 +3997,7 @@ import { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileS
3979
3997
  import { randomUUID } from "node:crypto";
3980
3998
  import { basename, dirname, join, resolve } from "node:path";
3981
3999
  import { mkdirSync as mkdirSync2, readdirSync, readFileSync as readFileSync2, statSync } from "node:fs";
4000
+ import { execFileSync } from "node:child_process";
3982
4001
  import { basename as basename2, dirname as dirname2, isAbsolute, join as join2, relative, resolve as resolve2 } from "node:path";
3983
4002
  import { existsSync as existsSync2, readFileSync as readFileSync3, readdirSync as readdirSync2 } from "node:fs";
3984
4003
  import { join as join4, resolve as resolve4 } from "node:path";
@@ -3986,10 +4005,10 @@ import { mkdirSync as mkdirSync3, rmdirSync, statSync as statSync2, unlinkSync a
3986
4005
  import { dirname as dirname3, isAbsolute as isAbsolute2, join as join3, resolve as resolve3 } from "node:path";
3987
4006
  import { setTimeout as sleep } from "node:timers/promises";
3988
4007
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
3989
- import { execFileSync } from "node:child_process";
4008
+ import { execFileSync as execFileSync2 } from "node:child_process";
3990
4009
  import { existsSync as existsSync3 } from "node:fs";
3991
4010
  import { isAbsolute as isAbsolute3, resolve as resolve5 } from "node:path";
3992
- import { execFileSync as execFileSync2 } from "node:child_process";
4011
+ import { execFileSync as execFileSync3 } from "node:child_process";
3993
4012
  import { mkdirSync as mkdirSync4, readFileSync as readFileSync4, realpathSync, statSync as statSync3, writeFileSync as writeFileSync3 } from "node:fs";
3994
4013
  import { basename as basename3, dirname as dirname4, isAbsolute as isAbsolute4, join as join5, resolve as resolve6 } from "node:path";
3995
4014
  import { existsSync as existsSync4, readdirSync as readdirSync3, readFileSync as readFileSync5 } from "node:fs";
@@ -4030,18 +4049,45 @@ function resolveHarnessDir(startDir = process.cwd(), opts = {}) {
4030
4049
  const explicit = opts.harnessDir ?? process.env.MSTAR_HARNESS_DIR;
4031
4050
  if (explicit)
4032
4051
  return resolve2(start, explicit);
4052
+ const boundary = resolve2(start, opts.workspaceRoot ?? defaultWorkspaceRoot(start));
4033
4053
  let dir = start;
4034
4054
  for (;; ) {
4055
+ if (!isAtOrBelow(dir, boundary))
4056
+ return null;
4035
4057
  for (const candidate of [join2(dir, ".mstar"), join2(dir, ".agents"), join2(dir, ".plans"), join2(dir, "plans")]) {
4036
4058
  if (isDirectory(candidate))
4037
4059
  return candidate;
4038
4060
  }
4061
+ if (dir === boundary)
4062
+ return null;
4039
4063
  const parent = dirname2(dir);
4040
4064
  if (parent === dir)
4041
4065
  return null;
4042
4066
  dir = parent;
4043
4067
  }
4044
4068
  }
4069
+ function defaultWorkspaceRoot(startDir) {
4070
+ try {
4071
+ const cdup = execFileSync("git", ["rev-parse", "--show-cdup"], {
4072
+ cwd: startDir,
4073
+ encoding: "utf8",
4074
+ stdio: ["ignore", "pipe", "ignore"]
4075
+ }).trim();
4076
+ if (!cdup)
4077
+ return startDir;
4078
+ let boundary = startDir;
4079
+ for (const segment of cdup.split(/[\\/]/)) {
4080
+ if (segment && segment !== ".")
4081
+ boundary = dirname2(boundary);
4082
+ }
4083
+ return resolve2(boundary);
4084
+ } catch {}
4085
+ return startDir;
4086
+ }
4087
+ function isAtOrBelow(dir, root) {
4088
+ const rel = relative(root, dir);
4089
+ return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
4090
+ }
4045
4091
  function resolveSpecsDir(harnessDir, opts = {}) {
4046
4092
  const harness = resolve2(harnessDir);
4047
4093
  const repoRoot = dirname2(harness);
@@ -4072,28 +4118,27 @@ function resolveSddDir(harnessDir, planId) {
4072
4118
  }
4073
4119
  var GITIGNORE_SNIPPET = `# Morning Star harness (.mstar/)
4074
4120
  # Principle: process stays local; results are shared with the team.
4075
- # Ignored (process / coordination):
4076
- .mstar/archived/
4077
- .mstar/iterations/
4078
- .mstar/plans/
4079
- .mstar/sdd/
4080
- .mstar/notes.json
4081
- .mstar/status.json
4082
- # Tracked (results): .mstar/AGENTS.md, .mstar/knowledge/, .mstar/specs/
4121
+ # Default-ignore everything under .mstar/, then re-include the tracked results.
4122
+ .mstar/**
4123
+ !.mstar/AGENTS.md
4124
+ !.mstar/knowledge/
4125
+ !.mstar/knowledge/**
4126
+ !.mstar/specs/
4127
+ !.mstar/specs/**
4083
4128
  `;
4084
4129
  var GITIGNORE_SNIPPET_AGENTS = `# Morning Star harness (.agents/) — legacy
4085
- .agents/archived/
4086
- .agents/iterations/
4087
- .agents/plans/
4088
- .agents/sdd/
4089
- .agents/notes.json
4090
- .agents/status.json
4091
- # Tracked (results): .agents/AGENTS.md, .agents/knowledge/, .agents/specs/
4130
+ # Default-ignore everything under .agents/, then re-include the tracked results.
4131
+ .agents/**
4132
+ !.agents/AGENTS.md
4133
+ !.agents/knowledge/
4134
+ !.agents/knowledge/**
4135
+ !.agents/specs/
4136
+ !.agents/specs/**
4092
4137
  `;
4093
4138
  var GITIGNORE_PROCESS_ENTRIES = GITIGNORE_SNIPPET.split(`
4094
- `).filter((line) => line.startsWith(".mstar/")).map((line) => line.trim());
4139
+ `).filter((line) => line.startsWith(".mstar/") || line.startsWith("!.mstar/")).map((line) => line.trim());
4095
4140
  var GITIGNORE_PROCESS_ENTRIES_AGENTS = GITIGNORE_SNIPPET_AGENTS.split(`
4096
- `).filter((line) => line.startsWith(".agents/")).map((line) => line.trim());
4141
+ `).filter((line) => line.startsWith(".agents/") || line.startsWith("!.agents/")).map((line) => line.trim());
4097
4142
  function isDirectory(dir) {
4098
4143
  try {
4099
4144
  return statSync(dir).isDirectory();
@@ -4566,7 +4611,7 @@ function probeBranch(worktreePath, opts) {
4566
4611
  return { branch: precomputed };
4567
4612
  const timeout = opts.timeoutMs ?? probeTimeoutMs();
4568
4613
  try {
4569
- const stdout = execFileSync(opts.gitPath ?? "git", ["-C", worktreePath, "branch", "--show-current"], {
4614
+ const stdout = execFileSync2(opts.gitPath ?? "git", ["-C", worktreePath, "branch", "--show-current"], {
4570
4615
  encoding: "utf8",
4571
4616
  stdio: ["ignore", "pipe", "pipe"],
4572
4617
  timeout
@@ -4671,7 +4716,7 @@ function isFile(file) {
4671
4716
  var GIT_CAPTURE_MAX_BYTES = 64 * 1024 * 1024;
4672
4717
  function gitOut(cwd, args) {
4673
4718
  try {
4674
- return execFileSync2("git", args, {
4719
+ return execFileSync3("git", args, {
4675
4720
  cwd,
4676
4721
  encoding: "utf8",
4677
4722
  stdio: ["ignore", "pipe", "pipe"],
@@ -4804,7 +4849,7 @@ function reviewPackage(base, head, outFile, opts = {}) {
4804
4849
  const cwd = opts.cwd ?? process.cwd();
4805
4850
  const verifyRef = (ref, what) => {
4806
4851
  try {
4807
- execFileSync2("git", ["rev-parse", "--verify", "--quiet", ref], { cwd, stdio: ["ignore", "pipe", "pipe"] });
4852
+ execFileSync3("git", ["rev-parse", "--verify", "--quiet", ref], { cwd, stdio: ["ignore", "pipe", "pipe"] });
4808
4853
  } catch {
4809
4854
  throw new SddScriptError(`bad ${what}: ${ref}`, 2);
4810
4855
  }
@@ -4824,7 +4869,7 @@ function reviewPackage(base, head, outFile, opts = {}) {
4824
4869
  const shortHead = gitOut(cwd, ["rev-parse", "--short", head]) ?? head;
4825
4870
  out = join5(sddDir, `review-${shortBase}..${shortHead}.diff`);
4826
4871
  }
4827
- const run = (args) => execFileSync2("git", args, { cwd, maxBuffer: GIT_CAPTURE_MAX_BYTES });
4872
+ const run = (args) => execFileSync3("git", args, { cwd, maxBuffer: GIT_CAPTURE_MAX_BYTES });
4828
4873
  const parts = [
4829
4874
  Buffer.from(`# Review package: ${base}..${head}
4830
4875
 
@@ -6264,6 +6309,8 @@ function detectHost(signals2) {
6264
6309
  return "opencode";
6265
6310
  if (s.has("task_agent_batch") || s.has("ask") || s.has("hub"))
6266
6311
  return "omp";
6312
+ if (s.has("subagent"))
6313
+ return "dsh";
6267
6314
  if (s.has("AgentSwarm"))
6268
6315
  return "kimi";
6269
6316
  if (s.has("Agent") || s.has("AskUserQuestion") || s.has("EnterPlanMode") || s.has("TodoWrite"))
@@ -6379,28 +6426,27 @@ function readHarnessVersion() {
6379
6426
  }
6380
6427
  var GITIGNORE_SNIPPET2 = `# Morning Star harness (.mstar/)
6381
6428
  # Principle: process stays local; results are shared with the team.
6382
- # Ignored (process / coordination):
6383
- .mstar/archived/
6384
- .mstar/iterations/
6385
- .mstar/plans/
6386
- .mstar/sdd/
6387
- .mstar/notes.json
6388
- .mstar/status.json
6389
- # Tracked (results): .mstar/AGENTS.md, .mstar/knowledge/, .mstar/specs/
6429
+ # Default-ignore everything under .mstar/, then re-include the tracked results.
6430
+ .mstar/**
6431
+ !.mstar/AGENTS.md
6432
+ !.mstar/knowledge/
6433
+ !.mstar/knowledge/**
6434
+ !.mstar/specs/
6435
+ !.mstar/specs/**
6390
6436
  `;
6391
6437
  var GITIGNORE_SNIPPET_AGENTS2 = `# Morning Star harness (.agents/) — legacy
6392
- .agents/archived/
6393
- .agents/iterations/
6394
- .agents/plans/
6395
- .agents/sdd/
6396
- .agents/notes.json
6397
- .agents/status.json
6398
- # Tracked (results): .agents/AGENTS.md, .agents/knowledge/, .agents/specs/
6438
+ # Default-ignore everything under .agents/, then re-include the tracked results.
6439
+ .agents/**
6440
+ !.agents/AGENTS.md
6441
+ !.agents/knowledge/
6442
+ !.agents/knowledge/**
6443
+ !.agents/specs/
6444
+ !.agents/specs/**
6399
6445
  `;
6400
6446
  var GITIGNORE_PROCESS_ENTRIES2 = GITIGNORE_SNIPPET2.split(`
6401
- `).filter((line) => line.startsWith(".mstar/")).map((line) => line.trim());
6447
+ `).filter((line) => line.startsWith(".mstar/") || line.startsWith("!.mstar/")).map((line) => line.trim());
6402
6448
  var GITIGNORE_PROCESS_ENTRIES_AGENTS2 = GITIGNORE_SNIPPET_AGENTS2.split(`
6403
- `).filter((line) => line.startsWith(".agents/")).map((line) => line.trim());
6449
+ `).filter((line) => line.startsWith(".agents/") || line.startsWith("!.agents/")).map((line) => line.trim());
6404
6450
  function isPlainObject4(value) {
6405
6451
  return typeof value === "object" && value !== null && !Array.isArray(value);
6406
6452
  }
@@ -6949,7 +6995,7 @@ import path5 from "node:path";
6949
6995
  import fs2 from "node:fs";
6950
6996
  import os from "node:os";
6951
6997
  import path4 from "node:path";
6952
- import { execFileSync as execFileSync3 } from "node:child_process";
6998
+ import { execFileSync as execFileSync4 } from "node:child_process";
6953
6999
  var REPO_URL = "https://github.com/btspoony/mstar-harness.git";
6954
7000
  var PLUGIN_NAME = "morning-star-harness";
6955
7001
  var HARNESS_REPO_PATH = path4.join(os.homedir(), ".mstar", "harness");
@@ -6983,7 +7029,7 @@ function ensureDir(dirPath, dryRun) {
6983
7029
  function runCommand(command, cwd, dryRun) {
6984
7030
  if (dryRun)
6985
7031
  return;
6986
- execFileSync3(command[0], command.slice(1), { cwd, stdio: "pipe", encoding: "utf8" });
7032
+ execFileSync4(command[0], command.slice(1), { cwd, stdio: "pipe", encoding: "utf8" });
6987
7033
  }
6988
7034
  function ensureLocalHarnessRepo(dryRun) {
6989
7035
  const notes = [];
@@ -7104,18 +7150,18 @@ function validateSymlink(target, linkPath) {
7104
7150
  return errors2;
7105
7151
  }
7106
7152
  var HARNESS_PROCESS_GITIGNORE = [
7107
- ".mstar/archived/",
7108
- ".mstar/iterations/",
7109
- ".mstar/plans/",
7110
- ".mstar/sdd/",
7111
- ".mstar/notes.json",
7112
- ".mstar/status.json",
7113
- ".agents/archived/",
7114
- ".agents/iterations/",
7115
- ".agents/plans/",
7116
- ".agents/sdd/",
7117
- ".agents/notes.json",
7118
- ".agents/status.json"
7153
+ ".mstar/**",
7154
+ "!.mstar/AGENTS.md",
7155
+ "!.mstar/knowledge/",
7156
+ "!.mstar/knowledge/**",
7157
+ "!.mstar/specs/",
7158
+ "!.mstar/specs/**",
7159
+ ".agents/**",
7160
+ "!.agents/AGENTS.md",
7161
+ "!.agents/knowledge/",
7162
+ "!.agents/knowledge/**",
7163
+ "!.agents/specs/",
7164
+ "!.agents/specs/**"
7119
7165
  ];
7120
7166
  function missingHarnessProcessGitignoreEntries(gitignoreContent) {
7121
7167
  const lines = gitignoreContent.split(/\r?\n/);
@@ -7469,7 +7515,7 @@ var cursorAdapter = {
7469
7515
  // src/adapters/omp.ts
7470
7516
  import fs5 from "node:fs";
7471
7517
  import path7 from "node:path";
7472
- import { execFileSync as execFileSync5 } from "node:child_process";
7518
+ import { execFileSync as execFileSync6 } from "node:child_process";
7473
7519
  var OMP_PLUGIN_MARKER = ".omp-plugin/plugin.json";
7474
7520
  var CLAUDE_PLUGIN_MARKER = ".claude-plugin/plugin.json";
7475
7521
  var PACKAGE_NAMES = new Set(["morning-star", PLUGIN_NAME, "github:btspoony/mstar-harness"]);
@@ -7477,7 +7523,7 @@ var SKILL_SMOKE = ["mstar-host", "mstar-harness-core", "pm"];
7477
7523
  var COMMAND_SMOKE = ["iteration-start", "iteration-drive", "iteration-loop", "codebase-audit"];
7478
7524
  function ompAvailable() {
7479
7525
  try {
7480
- execFileSync5("omp", ["--version"], { stdio: "pipe", encoding: "utf8" });
7526
+ execFileSync6("omp", ["--version"], { stdio: "pipe", encoding: "utf8" });
7481
7527
  return true;
7482
7528
  } catch {
7483
7529
  return false;
@@ -7486,11 +7532,11 @@ function ompAvailable() {
7486
7532
  function runOmp(args, dryRun) {
7487
7533
  if (dryRun)
7488
7534
  return;
7489
- execFileSync5("omp", args, { stdio: "pipe", encoding: "utf8" });
7535
+ execFileSync6("omp", args, { stdio: "pipe", encoding: "utf8" });
7490
7536
  }
7491
7537
  function listInstalledPlugins() {
7492
7538
  try {
7493
- const raw = execFileSync5("omp", ["plugin", "list", "--json"], {
7539
+ const raw = execFileSync6("omp", ["plugin", "list", "--json"], {
7494
7540
  stdio: "pipe",
7495
7541
  encoding: "utf8"
7496
7542
  });
@@ -7566,7 +7612,7 @@ function runInit2(scope, dryRun) {
7566
7612
  notes.push(`Would update local harness repo: git -C ${HARNESS_REPO_PATH} pull --ff-only`);
7567
7613
  } else {
7568
7614
  try {
7569
- execFileSync5("git", ["-C", HARNESS_REPO_PATH, "pull", "--ff-only"], {
7615
+ execFileSync6("git", ["-C", HARNESS_REPO_PATH, "pull", "--ff-only"], {
7570
7616
  stdio: "pipe",
7571
7617
  encoding: "utf8"
7572
7618
  });
@@ -8186,7 +8232,7 @@ pathCommand.command("resolve").description("Resolve {HARNESS_DIR} + {SPECS_DIR}
8186
8232
  const startDir = pathArg ? path11.resolve(pathArg) : process.cwd();
8187
8233
  const harnessDir = resolveHarnessDir(startDir);
8188
8234
  if (!harnessDir) {
8189
- const guidance = "no harness dir found (probed .mstar/, .agents/, .plans/, plans/ walking up from " + `${startDir}) \u2014 run \`mstar init\` to bootstrap, or pass a start dir inside a harness-enabled project`;
8235
+ const guidance = "no harness dir found \u2014 the bounded probe (.mstar/, .agents/, .plans/, plans/) walked up from " + `${startDir} only within the workspace root (git top-level of the start dir; non-git start probes only itself) \u2014 run \`mstar init\` to bootstrap, or pass a start dir inside a harness-enabled project`;
8190
8236
  if (options.json) {
8191
8237
  console.log(JSON.stringify({ ok: false, startDir, harnessDir: null, specsDir: null, guidance }));
8192
8238
  } else {
@@ -8794,7 +8840,7 @@ function resolveAuditShortSha(cwd, override) {
8794
8840
  if (override !== undefined && override !== "")
8795
8841
  return override;
8796
8842
  try {
8797
- const out = execFileSync6("git", ["rev-parse", "--short", "HEAD"], {
8843
+ const out = execFileSync7("git", ["rev-parse", "--short", "HEAD"], {
8798
8844
  cwd,
8799
8845
  encoding: "utf8",
8800
8846
  stdio: ["ignore", "pipe", "ignore"]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mstar-harness/cli",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "Morning Star harness CLI — installer bootstrap + mstar workflow verbs (path/status/lease/sdd/iteration/dispatch/worktree/lint/design-md/audit/compound/host/skill).",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -34,6 +34,6 @@
34
34
  "access": "public"
35
35
  },
36
36
  "devDependencies": {
37
- "@mstar-harness/engine": "2.1.0"
37
+ "@mstar-harness/engine": "2.2.0"
38
38
  }
39
39
  }