@grunnverk/kodrdriv 1.5.1 → 1.5.2

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.
@@ -0,0 +1,99 @@
1
+ # Workspace Exclusion Fix
2
+
3
+ ## Problem
4
+
5
+ The `check_development` MCP prompt was incorrectly identifying test directories and documentation directories as packages that needed to be checked. This resulted in false positives for packages like:
6
+
7
+ - `kodrdriv-docs` (in `doc/` or `docs/`)
8
+ - `@test/external-unlink-test` (in `test-*/`)
9
+ - `@test/app` (in `test-*/`)
10
+ - `test-project` (in `test-*/`)
11
+
12
+ These directories should be excluded from workspace scanning as they are not real packages that need development readiness checks.
13
+
14
+ ## Root Cause
15
+
16
+ Two functions were calling `scanForPackageJsonFiles` without passing exclusion patterns:
17
+
18
+ 1. **`check-development.ts`** - The `executeCheckDevelopment` function
19
+ 2. **`shared.ts`** - The `discoverTreePackages` function (used by all tree tools)
20
+
21
+ The `workspace.ts` resource already had the correct exclusion logic, but it wasn't being used consistently across all tools.
22
+
23
+ ## Solution
24
+
25
+ Added the same exclusion pattern logic to both files:
26
+
27
+ ### Default Exclusion Patterns
28
+
29
+ ```typescript
30
+ const DEFAULT_EXCLUDE_SUBPROJECTS = [
31
+ 'doc/',
32
+ 'docs/',
33
+ 'test-*/',
34
+ ];
35
+ ```
36
+
37
+ ### Implementation
38
+
39
+ Both files now:
40
+
41
+ 1. Load the kodrdriv config to get custom exclusions (if any)
42
+ 2. Build a comprehensive list of exclusion patterns:
43
+ - Standard build artifacts: `node_modules/`, `dist/`, `build/`, `.git/`
44
+ - Subproject exclusions from config or defaults
45
+ 3. Pass these patterns to `scanForPackageJsonFiles`
46
+
47
+ ### Files Modified
48
+
49
+ - **`src/mcp/tools/check-development.ts`**
50
+ - Added `loadConfig` import
51
+ - Added `DEFAULT_EXCLUDE_SUBPROJECTS` constant
52
+ - Modified `executeCheckDevelopment` to load config and build exclusion patterns
53
+
54
+ - **`src/mcp/tools/shared.ts`**
55
+ - Added `loadConfig` import
56
+ - Added `DEFAULT_EXCLUDE_SUBPROJECTS` constant
57
+ - Modified `discoverTreePackages` to load config and build exclusion patterns
58
+
59
+ ## Configuration
60
+
61
+ Users can customize exclusions in their `.kodrdrivrc.json`:
62
+
63
+ ```json
64
+ {
65
+ "workspace": {
66
+ "excludeSubprojects": [
67
+ "doc/",
68
+ "docs/",
69
+ "test-*/",
70
+ "examples/",
71
+ "custom-test-dir/"
72
+ ]
73
+ }
74
+ }
75
+ ```
76
+
77
+ ## Impact
78
+
79
+ This fix affects:
80
+
81
+ - **`check_development` prompt** - Now correctly ignores test/doc directories
82
+ - **All tree tools** - `tree_commit`, `tree_publish`, `tree_link`, etc. now use consistent exclusions
83
+ - **Workspace resource** - Already had correct behavior, now consistent with tools
84
+
85
+ ## Testing
86
+
87
+ All precommit checks pass:
88
+ - ✅ Linting
89
+ - ✅ TypeScript compilation
90
+ - ✅ Unit tests (1055 tests passed)
91
+ - ✅ MCP compliance tests
92
+
93
+ ## Related Files
94
+
95
+ The exclusion pattern logic is now consistent across:
96
+ - `src/mcp/resources/workspace.ts` (original implementation)
97
+ - `src/mcp/resources/tree-graph.ts` (already using exclusions)
98
+ - `src/mcp/tools/check-development.ts` (fixed)
99
+ - `src/mcp/tools/shared.ts` (fixed)
package/dist/constants.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import os from 'os';
2
2
  import path from 'path';
3
3
 
4
- /** Version string populated at build time with git and system information */ const VERSION = '1.5.1 (HEAD/5728d3e T:v1.5.1 2026-01-27 23:31:39 -0800) linux x64 v24.13.0';
4
+ /** Version string populated at build time with git and system information */ const VERSION = '1.5.2 (HEAD/fe55baf T:v1.5.2 2026-01-28 00:30:31 -0800) linux x64 v24.13.0';
5
5
  /** The program name used in CLI help and error messages */ const PROGRAM_NAME = 'kodrdriv';
6
6
  const DEFAULT_OVERRIDES = false;
7
7
  const DATE_FORMAT_YEAR_MONTH_DAY_HOURS_MINUTES_SECONDS_MILLISECONDS = 'YYYY-MM-DD-HHmmss.SSS';
@@ -13915,7 +13915,7 @@ import path2 from "path";
13915
13915
  // src/constants.ts
13916
13916
  import os from "os";
13917
13917
  import path from "path";
13918
- var VERSION = "1.5.1 (HEAD/5728d3e T:v1.5.1 2026-01-27 23:31:39 -0800) linux x64 v24.13.0";
13918
+ var VERSION = "1.5.2 (HEAD/fe55baf T:v1.5.2 2026-01-28 00:30:31 -0800) linux x64 v24.13.0";
13919
13919
  var PROGRAM_NAME = "kodrdriv";
13920
13920
  var DATE_FORMAT_YEAR_MONTH_DAY_HOURS_MINUTES_SECONDS_MILLISECONDS = "YYYY-MM-DD-HHmmss.SSS";
13921
13921
  var DEFAULT_OUTPUT_DIRECTORY = "output/kodrdriv";
@@ -14144,6 +14144,36 @@ function installLogCapture() {
14144
14144
  // src/mcp/tools/shared.ts
14145
14145
  import { scanForPackageJsonFiles, buildDependencyGraph, topologicalSort } from "@grunnverk/tree-core";
14146
14146
  import { setLogger as setTreeExecutionLogger } from "@grunnverk/tree-execution";
14147
+
14148
+ // src/utils/config.ts
14149
+ import fs2 from "fs/promises";
14150
+ import path3 from "path";
14151
+ var CONFIG_FILES = [".kodrdrivrc.json", ".kodrdrivrc", "kodrdriv.config.json"];
14152
+ async function loadConfig(cwd = process.cwd()) {
14153
+ const logger2 = getLogger();
14154
+ for (const filename of CONFIG_FILES) {
14155
+ const configPath = path3.join(cwd, filename);
14156
+ try {
14157
+ const content = await fs2.readFile(configPath, "utf-8");
14158
+ const config2 = JSON.parse(content);
14159
+ logger2.verbose(`Loaded configuration from ${configPath}`);
14160
+ return config2;
14161
+ } catch (error48) {
14162
+ if (error48.code !== "ENOENT") {
14163
+ logger2.warn(`CONFIG_LOAD_FAILED: Failed to load configuration file | Path: ${configPath} | Error: ${error48.message} | Action: Using defaults`);
14164
+ }
14165
+ }
14166
+ }
14167
+ logger2.verbose("No configuration file found, using defaults");
14168
+ return null;
14169
+ }
14170
+
14171
+ // src/mcp/tools/shared.ts
14172
+ var DEFAULT_EXCLUDE_SUBPROJECTS = [
14173
+ "doc/",
14174
+ "docs/",
14175
+ "test-*/"
14176
+ ];
14147
14177
  function configureTreeExecutionLogger() {
14148
14178
  const coreLogger = getCoreLogger();
14149
14179
  setTreeExecutionLogger({
@@ -14204,7 +14234,17 @@ function setupPackageFocusCallback(config2, context) {
14204
14234
  }
14205
14235
  async function discoverTreePackages(directory, packages, startFrom) {
14206
14236
  try {
14207
- const packageJsonPaths = await scanForPackageJsonFiles(directory);
14237
+ const config2 = await loadConfig(directory);
14238
+ const excludeSubprojects = config2?.workspace?.excludeSubprojects ?? DEFAULT_EXCLUDE_SUBPROJECTS;
14239
+ const excludedPatterns = [
14240
+ "**/node_modules/**",
14241
+ "**/dist/**",
14242
+ "**/build/**",
14243
+ "**/.git/**",
14244
+ // Add subproject exclusions
14245
+ ...excludeSubprojects.map((pattern) => `**/${pattern}**`)
14246
+ ];
14247
+ const packageJsonPaths = await scanForPackageJsonFiles(directory, excludedPatterns);
14208
14248
  if (packageJsonPaths.length === 0) {
14209
14249
  return null;
14210
14250
  }
@@ -15020,13 +15060,28 @@ import { formatErrorForMCP as formatErrorForMCP2, getLogger as getCoreLogger3, i
15020
15060
  import { scanForPackageJsonFiles as scanForPackageJsonFiles2 } from "@grunnverk/tree-core";
15021
15061
  import { getGitStatusSummary, getLinkedDependencies, run } from "@grunnverk/git-tools";
15022
15062
  import { readFile } from "fs/promises";
15023
- import * as path3 from "path";
15063
+ import * as path4 from "path";
15064
+ var DEFAULT_EXCLUDE_SUBPROJECTS2 = [
15065
+ "doc/",
15066
+ "docs/",
15067
+ "test-*/"
15068
+ ];
15024
15069
  async function executeCheckDevelopment(args, _context) {
15025
15070
  const directory = args.directory || process.cwd();
15026
15071
  const { getLogs, remove } = installLogCapture();
15027
15072
  try {
15028
15073
  const logger2 = getCoreLogger3();
15029
- const packageJsonFiles = await scanForPackageJsonFiles2(directory);
15074
+ const config2 = await loadConfig(directory);
15075
+ const excludeSubprojects = config2?.workspace?.excludeSubprojects ?? DEFAULT_EXCLUDE_SUBPROJECTS2;
15076
+ const excludedPatterns = [
15077
+ "**/node_modules/**",
15078
+ "**/dist/**",
15079
+ "**/build/**",
15080
+ "**/.git/**",
15081
+ // Add subproject exclusions
15082
+ ...excludeSubprojects.map((pattern) => `**/${pattern}**`)
15083
+ ];
15084
+ const packageJsonFiles = await scanForPackageJsonFiles2(directory, excludedPatterns);
15030
15085
  const isTree = packageJsonFiles.length > 1;
15031
15086
  logger2.info(`Checking development readiness for ${isTree ? "tree" : "single package"} in ${directory}`);
15032
15087
  const checks = {
@@ -15035,12 +15090,12 @@ async function executeCheckDevelopment(args, _context) {
15035
15090
  devVersion: { passed: true, issues: [] },
15036
15091
  linkStatus: { passed: true, issues: [] }
15037
15092
  };
15038
- const packagesToCheck = isTree ? packageJsonFiles : [path3.join(directory, "package.json")];
15093
+ const packagesToCheck = isTree ? packageJsonFiles : [path4.join(directory, "package.json")];
15039
15094
  for (const pkgJsonPath of packagesToCheck) {
15040
- const pkgDir = path3.dirname(pkgJsonPath);
15095
+ const pkgDir = path4.dirname(pkgJsonPath);
15041
15096
  const pkgJsonContent = await readFile(pkgJsonPath, "utf-8");
15042
15097
  const pkgJson = JSON.parse(pkgJsonContent);
15043
- const pkgName = pkgJson.name || path3.basename(pkgDir);
15098
+ const pkgName = pkgJson.name || path4.basename(pkgDir);
15044
15099
  try {
15045
15100
  const gitStatus = await getGitStatusSummary(pkgDir);
15046
15101
  if (gitStatus.branch === "main" || gitStatus.branch === "master") {
@@ -15731,32 +15786,7 @@ async function readStatusResource(uri) {
15731
15786
 
15732
15787
  // src/mcp/resources/workspace.ts
15733
15788
  import { buildDependencyGraph as buildDependencyGraph2, scanForPackageJsonFiles as scanForPackageJsonFiles3 } from "@grunnverk/tree-core";
15734
-
15735
- // src/utils/config.ts
15736
- import fs2 from "fs/promises";
15737
- import path4 from "path";
15738
- var CONFIG_FILES = [".kodrdrivrc.json", ".kodrdrivrc", "kodrdriv.config.json"];
15739
- async function loadConfig(cwd = process.cwd()) {
15740
- const logger2 = getLogger();
15741
- for (const filename of CONFIG_FILES) {
15742
- const configPath = path4.join(cwd, filename);
15743
- try {
15744
- const content = await fs2.readFile(configPath, "utf-8");
15745
- const config2 = JSON.parse(content);
15746
- logger2.verbose(`Loaded configuration from ${configPath}`);
15747
- return config2;
15748
- } catch (error48) {
15749
- if (error48.code !== "ENOENT") {
15750
- logger2.warn(`CONFIG_LOAD_FAILED: Failed to load configuration file | Path: ${configPath} | Error: ${error48.message} | Action: Using defaults`);
15751
- }
15752
- }
15753
- }
15754
- logger2.verbose("No configuration file found, using defaults");
15755
- return null;
15756
- }
15757
-
15758
- // src/mcp/resources/workspace.ts
15759
- var DEFAULT_EXCLUDE_SUBPROJECTS = [
15789
+ var DEFAULT_EXCLUDE_SUBPROJECTS3 = [
15760
15790
  "doc/",
15761
15791
  "docs/",
15762
15792
  "test-*/"
@@ -15765,7 +15795,7 @@ async function readWorkspaceResource(uri) {
15765
15795
  const root = uri.path || process.cwd();
15766
15796
  try {
15767
15797
  const config2 = await loadConfig(root);
15768
- const excludeSubprojects = config2?.workspace?.excludeSubprojects ?? DEFAULT_EXCLUDE_SUBPROJECTS;
15798
+ const excludeSubprojects = config2?.workspace?.excludeSubprojects ?? DEFAULT_EXCLUDE_SUBPROJECTS3;
15769
15799
  const excludedPatterns = [
15770
15800
  "**/node_modules/**",
15771
15801
  "**/dist/**",
@@ -15801,7 +15831,7 @@ async function readWorkspaceResource(uri) {
15801
15831
 
15802
15832
  // src/mcp/resources/tree-graph.ts
15803
15833
  import { buildDependencyGraph as buildDependencyGraph3, scanForPackageJsonFiles as scanForPackageJsonFiles4 } from "@grunnverk/tree-core";
15804
- var DEFAULT_EXCLUDE_SUBPROJECTS2 = [
15834
+ var DEFAULT_EXCLUDE_SUBPROJECTS4 = [
15805
15835
  "doc/",
15806
15836
  "docs/",
15807
15837
  "test-*/"
@@ -15810,7 +15840,7 @@ async function readTreeGraphResource(uri) {
15810
15840
  const root = uri.path || process.cwd();
15811
15841
  try {
15812
15842
  const config2 = await loadConfig(root);
15813
- const excludeSubprojects = config2?.workspace?.excludeSubprojects ?? DEFAULT_EXCLUDE_SUBPROJECTS2;
15843
+ const excludeSubprojects = config2?.workspace?.excludeSubprojects ?? DEFAULT_EXCLUDE_SUBPROJECTS4;
15814
15844
  const excludedPatterns = [
15815
15845
  "**/node_modules/**",
15816
15846
  "**/dist/**",
@@ -15857,7 +15887,7 @@ async function readTreeGraphResource(uri) {
15857
15887
  import { parsePackageJson, scanForPackageJsonFiles as scanForPackageJsonFiles5 } from "@grunnverk/tree-core";
15858
15888
  import { resolve } from "node:path";
15859
15889
  import { existsSync } from "node:fs";
15860
- var DEFAULT_EXCLUDE_SUBPROJECTS3 = [
15890
+ var DEFAULT_EXCLUDE_SUBPROJECTS5 = [
15861
15891
  "doc/",
15862
15892
  "docs/",
15863
15893
  "test-*/"
@@ -15874,7 +15904,7 @@ async function readPackageResource(uri) {
15874
15904
  } else {
15875
15905
  const cwd = process.cwd();
15876
15906
  const config2 = await loadConfig(cwd);
15877
- const excludeSubprojects = config2?.workspace?.excludeSubprojects ?? DEFAULT_EXCLUDE_SUBPROJECTS3;
15907
+ const excludeSubprojects = config2?.workspace?.excludeSubprojects ?? DEFAULT_EXCLUDE_SUBPROJECTS5;
15878
15908
  const excludedPatterns = [
15879
15909
  "**/node_modules/**",
15880
15910
  "**/dist/**",