@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.
- package/WORKSPACE-EXCLUSION-FIX.md +99 -0
- package/dist/constants.js +1 -1
- package/dist/mcp-server.js +68 -38
- package/dist/mcp-server.js.map +4 -4
- package/package.json +4 -4
|
@@ -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.
|
|
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';
|
package/dist/mcp-server.js
CHANGED
|
@@ -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.
|
|
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
|
|
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
|
|
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
|
|
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 : [
|
|
15093
|
+
const packagesToCheck = isTree ? packageJsonFiles : [path4.join(directory, "package.json")];
|
|
15039
15094
|
for (const pkgJsonPath of packagesToCheck) {
|
|
15040
|
-
const pkgDir =
|
|
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 ||
|
|
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 ??
|
|
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
|
|
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 ??
|
|
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
|
|
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 ??
|
|
15907
|
+
const excludeSubprojects = config2?.workspace?.excludeSubprojects ?? DEFAULT_EXCLUDE_SUBPROJECTS5;
|
|
15878
15908
|
const excludedPatterns = [
|
|
15879
15909
|
"**/node_modules/**",
|
|
15880
15910
|
"**/dist/**",
|