mindsystem-cc 4.0.3 → 4.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -250,6 +250,15 @@ Requirements you want but haven't shipped yet are tracked in `PROJECT.md` with o
250
250
 
251
251
  ---
252
252
 
253
+ ## Prerequisites
254
+
255
+ - [Claude Code](https://docs.anthropic.com/en/docs/claude-code)
256
+ - [Node.js](https://nodejs.org/) (for `npx`)
257
+ - [uv](https://docs.astral.sh/uv/) — Python package runner used by CLI scripts (`curl -LsSf https://astral.sh/uv/install.sh | sh`)
258
+ - Python 3.10+ (used by uv for scripts)
259
+
260
+ ---
261
+
253
262
  ## Quick start
254
263
 
255
264
  ### New project
package/bin/install.js CHANGED
@@ -420,9 +420,9 @@ function generateWrappers(claudeDir) {
420
420
  fs.mkdirSync(binDir, { recursive: true });
421
421
 
422
422
  const wrappers = {
423
- 'ms-tools': '#!/usr/bin/env bash\nexec uv run "$(dirname "$0")/../mindsystem/scripts/ms-tools.py" "$@"\n',
423
+ 'ms-tools': '#!/usr/bin/env bash\n[ -f "$HOME/.local/bin/env" ] && . "$HOME/.local/bin/env"\nexec uv run "$(dirname "$0")/../mindsystem/scripts/ms-tools.py" "$@"\n',
424
424
  'ms-lookup': '#!/usr/bin/env bash\nexec "$(dirname "$0")/../mindsystem/scripts/ms-lookup-wrapper.sh" "$@"\n',
425
- 'ms-compare-mockups': '#!/usr/bin/env bash\nexec uv run "$(dirname "$0")/../mindsystem/scripts/compare_mockups.py" "$@"\n',
425
+ 'ms-compare-mockups': '#!/usr/bin/env bash\n[ -f "$HOME/.local/bin/env" ] && . "$HOME/.local/bin/env"\nexec uv run "$(dirname "$0")/../mindsystem/scripts/compare_mockups.py" "$@"\n',
426
426
  };
427
427
 
428
428
  for (const [name, content] of Object.entries(wrappers)) {
@@ -444,11 +444,6 @@ function ensurePathHook(claudeDir, isGlobal, configDir) {
444
444
  if (!Array.isArray(settings.hooks.SessionStart))
445
445
  settings.hooks.SessionStart = [];
446
446
 
447
- // Idempotent — skip if already present
448
- const marker = 'mindsystem/bin';
449
- if (settings.hooks.SessionStart.some(e => JSON.stringify(e).includes(marker)))
450
- return;
451
-
452
447
  // Build PATH expression
453
448
  let binExpr;
454
449
  if (isGlobal) {
@@ -459,6 +454,14 @@ function ensurePathHook(claudeDir, isGlobal, configDir) {
459
454
  binExpr = '$CLAUDE_PROJECT_DIR/.claude/bin';
460
455
  }
461
456
 
457
+ // Self-healing: remove all existing Mindsystem PATH hooks, then add exactly one.
458
+ // This deduplicates any prior entries AND prevents future duplicates.
459
+ const before = settings.hooks.SessionStart.length;
460
+ settings.hooks.SessionStart = settings.hooks.SessionStart.filter(
461
+ e => !JSON.stringify(e).includes('CLAUDE_ENV_FILE')
462
+ );
463
+ const removed = before - settings.hooks.SessionStart.length;
464
+
462
465
  settings.hooks.SessionStart.push({
463
466
  matcher: '',
464
467
  hooks: [{
@@ -468,7 +471,11 @@ function ensurePathHook(claudeDir, isGlobal, configDir) {
468
471
  });
469
472
 
470
473
  fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
471
- console.log(` ${green}✓${reset} Configured PATH hook`);
474
+ if (removed > 0) {
475
+ console.log(` ${green}✓${reset} Configured PATH hook (cleaned ${removed} duplicate(s))`);
476
+ } else {
477
+ console.log(` ${green}✓${reset} Configured PATH hook`);
478
+ }
472
479
  }
473
480
 
474
481
  /**
@@ -654,6 +661,20 @@ async function install(isGlobal) {
654
661
  }
655
662
  }
656
663
 
664
+ // Phase 8b: Check uv
665
+ try {
666
+ const { execSync } = require('child_process');
667
+ const uvVersion = execSync('uv --version 2>&1', { encoding: 'utf8' }).trim();
668
+ console.log(` ${green}✓${reset} Found ${uvVersion}`);
669
+ } catch (e) {
670
+ const isWin = process.platform === 'win32';
671
+ const installCmd = isWin
672
+ ? 'powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"'
673
+ : 'curl -LsSf https://astral.sh/uv/install.sh | sh';
674
+ console.log(` ${yellow}⚠${reset} uv not found — CLI wrappers (ms-tools, ms-compare-mockups) require it`);
675
+ console.log(` Install: ${cyan}${installCmd}${reset}`);
676
+ }
677
+
657
678
  // Phase 9: Cleanup orphaned files
658
679
  if (orphans.length > 0) {
659
680
  console.log('');
@@ -13,7 +13,7 @@ allowed-tools:
13
13
  ---
14
14
 
15
15
  <objective>
16
- Run health checks on project configuration. Detect and fix structural drift across 10 categories: subsystem vocabulary, milestone directory structure, milestone naming convention, phase archival, knowledge files, phase summaries, PLAN cleanup, CLI wrappers, research API keys, and Mindsystem version.
16
+ Run health checks on project configuration. Detect and fix structural drift across 10 categories: subsystem vocabulary, milestone directory structure, milestone naming convention, phase archival, knowledge files, phase summaries, PLAN cleanup, CLI wrappers and environment diagnostics, research API keys, and Mindsystem version.
17
17
 
18
18
  Idempotent.
19
19
  </objective>
@@ -117,7 +117,7 @@ Display results as a markdown table:
117
117
  | Knowledge files | FAIL | Directory missing |
118
118
  | Phase summaries | FAIL | 2 milestones missing summaries |
119
119
  | PLAN cleanup | FAIL | 9 leftover PLAN.md files |
120
- | CLI wrappers | FAIL | ms-tools not on PATH |
120
+ | CLI wrappers | FAIL | Not resolvable; bin dir not in PATH |
121
121
  | Research API Keys | WARN | PERPLEXITY_API_KEY not set |
122
122
  | Mindsystem version | WARN | v3.21.0 → v3.22.1 available |
123
123
  ```
@@ -143,7 +143,7 @@ If "Review each" → use AskUserQuestion for each failed check with its details
143
143
 
144
144
  Apply fixes in dependency order: fix_subsystems → fix_milestone_dirs → fix_milestone_naming → fix_phase_archival → fix_plan_cleanup → fix_knowledge. Skip any fix whose check passed or was skipped by user.
145
145
 
146
- Phase summaries are resolved by fix_phase_archival. CLI wrappers require manual PATH configuration (no automated fix). WARN checks (Research API Keys) are informational — no fix offered, only displayed in the report.
146
+ Phase summaries are resolved by fix_phase_archival. CLI wrapper failures have specific fixes: bin dir not in PATH restart Claude Code session; missing wrappers or bin dir → re-run `npx mindsystem-cc`; uv not found → `curl -LsSf https://astral.sh/uv/install.sh | sh`. WARN checks (Research API Keys, missing uv) are informational — no automated fix, only displayed in the report.
147
147
  </step>
148
148
 
149
149
  <step name="apply_fixes">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mindsystem-cc",
3
- "version": "4.0.3",
3
+ "version": "4.0.4",
4
4
  "description": "A meta-prompting, context engineering and spec-driven development system for Claude Code by TÂCHES.",
5
5
  "bin": {
6
6
  "mindsystem-cc": "bin/install.js"
@@ -761,19 +761,67 @@ def cmd_doctor_scan(args: argparse.Namespace) -> None:
761
761
  record("PASS", "PLAN Cleanup")
762
762
  print()
763
763
 
764
- # ---- CHECK 7: CLI Wrappers ----
764
+ # ---- CHECK 7: CLI Wrappers & Environment ----
765
765
  print("=== CLI Wrappers ===")
766
766
  wrapper_names = ["ms-tools", "ms-lookup", "ms-compare-mockups"]
767
- missing_wrappers = [w for w in wrapper_names if shutil.which(w) is None]
768
- if missing_wrappers:
767
+
768
+ # 7a: Check bin directory exists
769
+ global_bin = Path.home() / ".claude" / "bin"
770
+ local_bin = Path(".claude") / "bin"
771
+ bin_dir = global_bin if global_bin.is_dir() else (local_bin if local_bin.is_dir() else None)
772
+
773
+ if bin_dir is None:
769
774
  print("Status: FAIL")
770
- print(f"Not on PATH: {', '.join(missing_wrappers)}")
771
- print("Fix: re-run `npx mindsystem-cc` to regenerate wrappers and PATH hook")
775
+ print("Bin directory not found (~/.claude/bin/ or .claude/bin/)")
776
+ print("Fix: re-run `npx mindsystem-cc` to generate wrappers")
772
777
  record("FAIL", "CLI Wrappers")
773
778
  else:
774
- print("Status: PASS")
775
- print(f"All {len(wrapper_names)} CLI wrappers found on PATH")
776
- record("PASS", "CLI Wrappers")
779
+ # 7b: Check wrapper files present
780
+ missing_files = [w for w in wrapper_names if not (bin_dir / w).exists()]
781
+ if missing_files:
782
+ print("Status: FAIL")
783
+ print(f"Wrapper files missing from {bin_dir}: {', '.join(missing_files)}")
784
+ print("Fix: re-run `npx mindsystem-cc` to regenerate wrappers")
785
+ record("FAIL", "CLI Wrappers")
786
+ else:
787
+ # 7c: Check bin dir in PATH
788
+ path_dirs = os.environ.get("PATH", "").split(os.pathsep)
789
+ bin_in_path = str(bin_dir.resolve()) in [os.path.realpath(p) for p in path_dirs]
790
+
791
+ # 7d: Check wrappers resolvable
792
+ missing_wrappers = [w for w in wrapper_names if shutil.which(w) is None]
793
+
794
+ if missing_wrappers:
795
+ print("Status: FAIL")
796
+ print(f"Not resolvable: {', '.join(missing_wrappers)}")
797
+ if not bin_in_path:
798
+ print(f"Cause: {bin_dir} not in PATH")
799
+ print("Fix: restart Claude Code session (PATH hook fires on SessionStart)")
800
+ else:
801
+ print("Fix: re-run `npx mindsystem-cc` to regenerate wrappers and PATH hook")
802
+ record("FAIL", "CLI Wrappers")
803
+ else:
804
+ print(f"All {len(wrapper_names)} CLI wrappers found on PATH")
805
+
806
+ # 7e: Check uv available
807
+ uv_ok = shutil.which("uv") is not None
808
+ # 7f: Check Python available
809
+ py_ok = shutil.which("python3") is not None or shutil.which("python") is not None
810
+
811
+ issues = []
812
+ if not uv_ok:
813
+ issues.append("uv not found — install: `curl -LsSf https://astral.sh/uv/install.sh | sh`")
814
+ if not py_ok:
815
+ issues.append("Python not found — install Python 3.10+")
816
+
817
+ if issues:
818
+ print("Status: WARN")
819
+ for issue in issues:
820
+ print(f" {issue}")
821
+ record("WARN", "CLI Wrappers")
822
+ else:
823
+ print("Status: PASS")
824
+ record("PASS", "CLI Wrappers")
777
825
  print()
778
826
 
779
827
  # ---- CHECK 8: Milestone Naming Convention ----