@yemi33/minions 0.1.2237 → 0.1.2238

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.
@@ -37,6 +37,10 @@ function _renderProjectBranch(p) {
37
37
  if (!p) return '';
38
38
  if (p.gitState === 'missing') return '<span class="project-warn" title="Project localPath does not exist on disk">(path not found)</span>';
39
39
  if (p.gitState === 'non-git') return '<span class="project-muted" title="Project path exists but is not a git repository">(not a git repo)</span>';
40
+ // opg-microsoft/minions#312 — the git-status probe timed out (e.g. a slow
41
+ // \\wsl.localhost\ 9P share). The repository is valid; show a neutral
42
+ // "checking" chip instead of the misleading "(not a git repo)" label.
43
+ if (p.gitState === 'probe-timeout') return '<span class="project-muted" title="Git status probe timed out (slow filesystem, e.g. a \\\\wsl.localhost\\ share). The repository is valid and will refresh.">(checking git…)</span>';
40
44
  if (p.gitState !== 'ok' || !p.gitBranch) return '';
41
45
  // opg-microsoft/minions#295: the engine flags `gitStale: true` when tracked
42
46
  // git refs have advanced past the cached snapshot (e.g. the operator ran
package/engine/queries.js CHANGED
@@ -2301,6 +2301,13 @@ const PROJECT_GIT_STATUS_TTL = 15000;
2301
2301
  const PROJECT_GIT_STATUS_PENDING = Object.freeze({ gitBranch: null, gitDetached: false, gitDirty: false, gitState: 'pending', remoteDefaultBranch: null, ahead: null, behind: null });
2302
2302
  const PROJECT_GIT_STATUS_MISSING = Object.freeze({ gitBranch: null, gitDetached: false, gitDirty: false, gitState: 'missing', remoteDefaultBranch: null, ahead: null, behind: null });
2303
2303
  const PROJECT_GIT_STATUS_NON_GIT = Object.freeze({ gitBranch: null, gitDetached: false, gitDirty: false, gitState: 'non-git', remoteDefaultBranch: null, ahead: null, behind: null });
2304
+ // opg-microsoft/minions#312 — distinct state for "the probe could not settle
2305
+ // in time" (or the path clearly contains a .git but rev-parse failed). A
2306
+ // probe-budget timeout is NOT evidence the path lacks a repository: slow
2307
+ // filesystems (\\wsl.localhost\ 9P shares, Defender real-time scanning) can
2308
+ // legitimately blow the 10s/15s budget on a valid repo. Collapsing that to
2309
+ // `non-git` produced the misleading "(not a git repo)" dashboard label.
2310
+ const PROJECT_GIT_STATUS_PROBE_TIMEOUT = Object.freeze({ gitBranch: null, gitDetached: false, gitDirty: false, gitState: 'probe-timeout', remoteDefaultBranch: null, ahead: null, behind: null });
2304
2311
 
2305
2312
  // Probe budget constants (W-mq19314k00101fc7). `PROBE_TIMEOUT_MS` is the
2306
2313
  // per-invocation execFile timeout; `PROBE_WATCHDOG_MS` is an OUTER
@@ -2375,6 +2382,30 @@ function _gitExec(localPath, args) {
2375
2382
  });
2376
2383
  }
2377
2384
 
2385
+ // opg-microsoft/minions#312 — classifies a `_gitExec` rejection as a
2386
+ // probe-budget timeout (the outer watchdog or execFile's own `timeout`
2387
+ // killing the child) rather than a genuine git failure such as an exit-128
2388
+ // "fatal: not a git repository". A timeout is not evidence the path lacks a
2389
+ // repo, so the caller keeps it out of the `non-git` bucket.
2390
+ function _isProbeTimeoutError(err) {
2391
+ if (!err) return false;
2392
+ if (typeof err.message === 'string' && err.message.includes('git probe watchdog')) return true;
2393
+ // execFile timeout: Node force-kills the child (killed=true) with the
2394
+ // configured kill signal, or surfaces an ETIMEDOUT code.
2395
+ if (err.killed === true) return true;
2396
+ if (err.code === 'ETIMEDOUT' || err.signal === 'SIGTERM' || err.signal === 'SIGKILL') return true;
2397
+ return false;
2398
+ }
2399
+
2400
+ // opg-microsoft/minions#312 — cheap existence check for a `.git` entry
2401
+ // (a directory for a normal repo, or a gitlink file for a worktree /
2402
+ // submodule). Used to override a failed/slow rev-parse so a path that
2403
+ // plainly contains a repository is never mislabelled "(not a git repo)".
2404
+ function _hasGitDir(localPath) {
2405
+ try { return fs.existsSync(path.join(localPath, '.git')); }
2406
+ catch { return false; }
2407
+ }
2408
+
2378
2409
  // Probe a single project. Returns the resolved status value. Used both by the
2379
2410
  // background refresh path inside getProjectGitStatus and by test code that
2380
2411
  // wants to drive a probe to completion deterministically.
@@ -2388,11 +2419,23 @@ async function _probeProjectGitStatus(localPath, configuredMainBranch) {
2388
2419
  try {
2389
2420
  if (!fs.existsSync(localPath)) return PROJECT_GIT_STATUS_MISSING;
2390
2421
  let isRepo = false;
2422
+ let probeErr = null;
2391
2423
  try {
2392
2424
  const out = (await _gitExec(localPath, ['rev-parse', '--is-inside-work-tree'])).trim();
2393
2425
  isRepo = out === 'true';
2394
- } catch { isRepo = false; }
2395
- if (!isRepo) return PROJECT_GIT_STATUS_NON_GIT;
2426
+ } catch (err) { isRepo = false; probeErr = err; }
2427
+ if (!isRepo) {
2428
+ // opg-microsoft/minions#312 — only collapse to non-git when the probe
2429
+ // genuinely found no repository. A probe-budget timeout (slow
2430
+ // \\wsl.localhost\ 9P share + Defender scanning can take >40s on a
2431
+ // valid repo) or a present `.git` entry means the path IS git-managed;
2432
+ // surface a distinct `probe-timeout` state so the dashboard never shows
2433
+ // the misleading "(not a git repo)" label for a valid repo.
2434
+ if (probeErr && (_isProbeTimeoutError(probeErr) || _hasGitDir(localPath))) {
2435
+ return PROJECT_GIT_STATUS_PROBE_TIMEOUT;
2436
+ }
2437
+ return PROJECT_GIT_STATUS_NON_GIT;
2438
+ }
2396
2439
  let branch = null;
2397
2440
  let detached = false;
2398
2441
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.2237",
3
+ "version": "0.1.2238",
4
4
  "description": "Multi-agent AI dev team that runs from ~/.minions/ — five autonomous agents share a single engine, dashboard, and knowledge base",
5
5
  "bin": {
6
6
  "minions": "bin/minions.js"