projscan 3.4.1 → 3.6.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.
- package/README.md +26 -21
- package/dist/cli/commands/claim.d.ts +5 -0
- package/dist/cli/commands/claim.js +139 -0
- package/dist/cli/commands/claim.js.map +1 -0
- package/dist/cli/commands/collision.d.ts +5 -0
- package/dist/cli/commands/collision.js +55 -0
- package/dist/cli/commands/collision.js.map +1 -0
- package/dist/cli/commands/coordinate.d.ts +5 -0
- package/dist/cli/commands/coordinate.js +43 -0
- package/dist/cli/commands/coordinate.js.map +1 -0
- package/dist/cli/commands/mergeRisk.d.ts +5 -0
- package/dist/cli/commands/mergeRisk.js +58 -0
- package/dist/cli/commands/mergeRisk.js.map +1 -0
- package/dist/cli/commands/plugin.js +124 -0
- package/dist/cli/commands/plugin.js.map +1 -1
- package/dist/cli/commands/route.d.ts +5 -0
- package/dist/cli/commands/route.js +53 -0
- package/dist/cli/commands/route.js.map +1 -0
- package/dist/cli/index.js +10 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/core/claims.d.ts +60 -0
- package/dist/core/claims.js +139 -0
- package/dist/core/claims.js.map +1 -0
- package/dist/core/collisionDetector.d.ts +55 -0
- package/dist/core/collisionDetector.js +156 -0
- package/dist/core/collisionDetector.js.map +1 -0
- package/dist/core/coordination.d.ts +49 -0
- package/dist/core/coordination.js +71 -0
- package/dist/core/coordination.js.map +1 -0
- package/dist/core/embeddings.js +30 -17
- package/dist/core/embeddings.js.map +1 -1
- package/dist/core/intentRouter.d.ts +40 -0
- package/dist/core/intentRouter.js +213 -0
- package/dist/core/intentRouter.js.map +1 -0
- package/dist/core/mergeRisk.d.ts +42 -0
- package/dist/core/mergeRisk.js +71 -0
- package/dist/core/mergeRisk.js.map +1 -0
- package/dist/core/pluginTrust.d.ts +56 -0
- package/dist/core/pluginTrust.js +138 -0
- package/dist/core/pluginTrust.js.map +1 -0
- package/dist/core/plugins.d.ts +1 -1
- package/dist/core/plugins.js +33 -0
- package/dist/core/plugins.js.map +1 -1
- package/dist/core/privacy.js +2 -2
- package/dist/core/privacy.js.map +1 -1
- package/dist/core/roadmapCatalog.js +50 -50
- package/dist/core/roadmapCatalog.js.map +1 -1
- package/dist/fixes/eslintFix.js +6 -2
- package/dist/fixes/eslintFix.js.map +1 -1
- package/dist/fixes/prettierFix.js +5 -2
- package/dist/fixes/prettierFix.js.map +1 -1
- package/dist/fixes/testFix.js +8 -2
- package/dist/fixes/testFix.js.map +1 -1
- package/dist/mcp/tools/claim.d.ts +7 -0
- package/dist/mcp/tools/claim.js +69 -0
- package/dist/mcp/tools/claim.js.map +1 -0
- package/dist/mcp/tools/collision.d.ts +7 -0
- package/dist/mcp/tools/collision.js +24 -0
- package/dist/mcp/tools/collision.js.map +1 -0
- package/dist/mcp/tools/coordinate.d.ts +7 -0
- package/dist/mcp/tools/coordinate.js +24 -0
- package/dist/mcp/tools/coordinate.js.map +1 -0
- package/dist/mcp/tools/mergeRisk.d.ts +7 -0
- package/dist/mcp/tools/mergeRisk.js +24 -0
- package/dist/mcp/tools/mergeRisk.js.map +1 -0
- package/dist/mcp/tools/plugin.js +24 -16
- package/dist/mcp/tools/plugin.js.map +1 -1
- package/dist/mcp/tools/route.d.ts +7 -0
- package/dist/mcp/tools/route.js +24 -0
- package/dist/mcp/tools/route.js.map +1 -0
- package/dist/mcp/tools.js +10 -0
- package/dist/mcp/tools.js.map +1 -1
- package/dist/projscan-sbom.cdx.json +6 -6
- package/dist/tool-manifest.json +95 -4
- package/dist/utils/formatSupport.d.ts +11 -0
- package/dist/utils/formatSupport.js +11 -0
- package/dist/utils/formatSupport.js.map +1 -1
- package/docs/PLUGIN-AUTHORING.md +35 -6
- package/package.json +1 -1
|
@@ -76,23 +76,23 @@ const ROADMAP_3_2_CATALOG = {
|
|
|
76
76
|
'3.5.x': {
|
|
77
77
|
line: '3.5.x',
|
|
78
78
|
track: {
|
|
79
|
-
theme: '
|
|
80
|
-
outcome: '
|
|
79
|
+
theme: 'Plugin Trust',
|
|
80
|
+
outcome: 'The surfaces that touch untrusted repositories cannot execute their code without explicit approval.',
|
|
81
81
|
includedInPlan: true,
|
|
82
|
-
scope: ['
|
|
83
|
-
successCriteria: ['
|
|
82
|
+
scope: ['fix-layer --ignore-scripts', 'plugin trust-on-first-use', 'embedding model graceful degradation'],
|
|
83
|
+
successCriteria: ['projscan fix never runs a scanned repo lifecycle script', 'plugins execute only after projscan plugin trust', 'an embedding model-load failure degrades to BM25 instead of throwing'],
|
|
84
84
|
},
|
|
85
85
|
tasks: [
|
|
86
86
|
{
|
|
87
|
-
id: 'rt-3-5-
|
|
87
|
+
id: 'rt-3-5-plugin-trust',
|
|
88
88
|
priority: 'p1',
|
|
89
|
-
title: '
|
|
90
|
-
why: '
|
|
89
|
+
title: 'Gate untrusted-repo code execution',
|
|
90
|
+
why: 'A scanned repo is untrusted input; fix-layer installs and local plugins must not execute its code without explicit, per-artifact approval.',
|
|
91
91
|
track: '3.5.x',
|
|
92
|
-
files: ['src/
|
|
92
|
+
files: ['src/fixes/eslintFix.ts', 'src/core/pluginTrust.ts', 'src/core/plugins.ts'],
|
|
93
93
|
verification: {
|
|
94
|
-
commands: ['
|
|
95
|
-
expected: '
|
|
94
|
+
commands: ['npm test', 'projscan plugin trust --all'],
|
|
95
|
+
expected: 'Fix installs use --ignore-scripts and plugins run only once trusted.',
|
|
96
96
|
},
|
|
97
97
|
},
|
|
98
98
|
],
|
|
@@ -100,23 +100,23 @@ const ROADMAP_3_2_CATALOG = {
|
|
|
100
100
|
'3.6.x': {
|
|
101
101
|
line: '3.6.x',
|
|
102
102
|
track: {
|
|
103
|
-
theme: '
|
|
104
|
-
outcome: '
|
|
103
|
+
theme: 'Swarm Collision Detection',
|
|
104
|
+
outcome: 'When two in-flight worktrees have overlapping blast radius, an agent learns before the changes collide.',
|
|
105
105
|
includedInPlan: true,
|
|
106
|
-
scope: ['
|
|
107
|
-
successCriteria: ['
|
|
106
|
+
scope: ['per-worktree changed-symbol blast radius', 'pairwise overlap detection', 'projscan_collision MCP + CLI'],
|
|
107
|
+
successCriteria: ['collision report names overlapping worktree pairs with the files and symbols at risk', 'blast radius reuses the impact graph', 'stays local-first over sibling git worktrees'],
|
|
108
108
|
},
|
|
109
109
|
tasks: [
|
|
110
110
|
{
|
|
111
|
-
id: 'rt-3-6-
|
|
111
|
+
id: 'rt-3-6-collision-detection',
|
|
112
112
|
priority: 'p1',
|
|
113
|
-
title: '
|
|
114
|
-
why: '
|
|
113
|
+
title: 'Detect cross-worktree change collisions',
|
|
114
|
+
why: 'Parallel agents editing one repo collide when their blast radii overlap; surfacing that pre-merge is the flagship coordination value.',
|
|
115
115
|
track: '3.6.x',
|
|
116
|
-
files: ['src/core/
|
|
116
|
+
files: ['src/core/collisionDetector.ts', 'src/mcp/tools/collision.ts', 'src/cli/commands/collision.ts'],
|
|
117
117
|
verification: {
|
|
118
|
-
commands: ['
|
|
119
|
-
expected: '
|
|
118
|
+
commands: ['projscan collisions --format json'],
|
|
119
|
+
expected: 'Report lists worktree pairs whose changed-symbol blast radii overlap.',
|
|
120
120
|
},
|
|
121
121
|
},
|
|
122
122
|
],
|
|
@@ -124,23 +124,23 @@ const ROADMAP_3_2_CATALOG = {
|
|
|
124
124
|
'3.7.x': {
|
|
125
125
|
line: '3.7.x',
|
|
126
126
|
track: {
|
|
127
|
-
theme: '
|
|
128
|
-
outcome: '
|
|
127
|
+
theme: 'Claims And Leases',
|
|
128
|
+
outcome: 'An agent can claim a file, symbol, or subsystem so the swarm sees who owns what and warns on contention.',
|
|
129
129
|
includedInPlan: true,
|
|
130
|
-
scope: ['
|
|
131
|
-
successCriteria: ['
|
|
130
|
+
scope: ['local claim store under .projscan-cache', 'contention warnings', 'projscan_claim MCP + CLI'],
|
|
131
|
+
successCriteria: ['claims persist locally and are scoped to the active repo', 'overlapping claims surface a contention warning', 'claims can be released explicitly'],
|
|
132
132
|
},
|
|
133
133
|
tasks: [
|
|
134
134
|
{
|
|
135
|
-
id: 'rt-3-7-
|
|
135
|
+
id: 'rt-3-7-claims-leases',
|
|
136
136
|
priority: 'p1',
|
|
137
|
-
title: 'Add
|
|
138
|
-
why: '
|
|
137
|
+
title: 'Add local claims / leases for swarm work',
|
|
138
|
+
why: 'Coordination needs a lightweight ownership signal so two agents do not silently take the same file or symbol.',
|
|
139
139
|
track: '3.7.x',
|
|
140
|
-
files: ['src/core/
|
|
140
|
+
files: ['src/core/claims.ts', 'src/mcp/tools/claim.ts', 'src/cli/commands/claim.ts'],
|
|
141
141
|
verification: {
|
|
142
|
-
commands: ['projscan
|
|
143
|
-
expected: '
|
|
142
|
+
commands: ['projscan claim add src/auth.ts --agent a', 'projscan claim list --format json'],
|
|
143
|
+
expected: 'Claims persist locally and overlapping claims warn on contention.',
|
|
144
144
|
},
|
|
145
145
|
},
|
|
146
146
|
],
|
|
@@ -148,23 +148,23 @@ const ROADMAP_3_2_CATALOG = {
|
|
|
148
148
|
'3.8.x': {
|
|
149
149
|
line: '3.8.x',
|
|
150
150
|
track: {
|
|
151
|
-
theme: '
|
|
152
|
-
outcome: '
|
|
151
|
+
theme: 'Merge-Risk Preflight',
|
|
152
|
+
outcome: 'Given the set of in-flight worktrees, preflight returns the safe integration order and where conflict risk concentrates.',
|
|
153
153
|
includedInPlan: true,
|
|
154
|
-
scope: ['
|
|
155
|
-
successCriteria: ['
|
|
154
|
+
scope: ['multi-branch preflight verdict', 'integration order', 'conflict-risk concentration'],
|
|
155
|
+
successCriteria: ['preflight accepts multiple in-flight worktrees', 'returns a safe integration order', 'flags files where multiple branches and blast radii concentrate'],
|
|
156
156
|
},
|
|
157
157
|
tasks: [
|
|
158
158
|
{
|
|
159
|
-
id: 'rt-3-8-
|
|
159
|
+
id: 'rt-3-8-merge-risk-preflight',
|
|
160
160
|
priority: 'p1',
|
|
161
|
-
title: '
|
|
162
|
-
why: '
|
|
161
|
+
title: 'Extend preflight to a multi-branch integration verdict',
|
|
162
|
+
why: 'Once collisions and claims exist, teams need an ordering: which in-flight branch is safe to merge first.',
|
|
163
163
|
track: '3.8.x',
|
|
164
|
-
files: ['src/core/
|
|
164
|
+
files: ['src/core/preflight.ts', 'src/core/collisionDetector.ts'],
|
|
165
165
|
verification: {
|
|
166
|
-
commands: ['projscan
|
|
167
|
-
expected: '
|
|
166
|
+
commands: ['projscan preflight --mode before_merge --format json'],
|
|
167
|
+
expected: 'Preflight returns integration order and conflict-risk concentration across in-flight worktrees.',
|
|
168
168
|
},
|
|
169
169
|
},
|
|
170
170
|
],
|
|
@@ -172,23 +172,23 @@ const ROADMAP_3_2_CATALOG = {
|
|
|
172
172
|
'3.9.x': {
|
|
173
173
|
line: '3.9.x',
|
|
174
174
|
track: {
|
|
175
|
-
theme: '
|
|
176
|
-
outcome: 'Agents
|
|
175
|
+
theme: 'Agent Ergonomics And Coordination Proof',
|
|
176
|
+
outcome: 'Agents reach the right capability through one budget-shaped entry point, and the coordination layer is measured for outcome value.',
|
|
177
177
|
includedInPlan: true,
|
|
178
|
-
scope: ['
|
|
179
|
-
successCriteria: ['
|
|
178
|
+
scope: ['adaptive intent router over the tool surface', 'budget-shaped next actions', 'with/without coordination outcome metrics'],
|
|
179
|
+
successCriteria: ['a single entry tool routes to the right capability', 'router output is budget-shaped and shrinks the tool-list footprint', 'dogfood/trial reports compare task success and token cost with vs without coordination'],
|
|
180
180
|
},
|
|
181
181
|
tasks: [
|
|
182
182
|
{
|
|
183
|
-
id: 'rt-3-9-
|
|
183
|
+
id: 'rt-3-9-agent-ergonomics-and-proof',
|
|
184
184
|
priority: 'p1',
|
|
185
|
-
title: 'Add
|
|
186
|
-
why: '
|
|
185
|
+
title: 'Add an intent router and coordination outcome proof',
|
|
186
|
+
why: 'A 41-tool surface costs context every turn; one adaptive entry point plus measured outcomes proves the coordination arc earns its keep.',
|
|
187
187
|
track: '3.9.x',
|
|
188
|
-
files: ['src/
|
|
188
|
+
files: ['src/mcp/tools', 'src/core/dogfood.ts', 'src/core/trial.ts'],
|
|
189
189
|
verification: {
|
|
190
|
-
commands: ['projscan
|
|
191
|
-
expected: '
|
|
190
|
+
commands: ['projscan dogfood --format json'],
|
|
191
|
+
expected: 'Routing shrinks the tool footprint and proof reports compare with/without coordination.',
|
|
192
192
|
},
|
|
193
193
|
},
|
|
194
194
|
],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"roadmapCatalog.js","sourceRoot":"","sources":["../../src/core/roadmapCatalog.ts"],"names":[],"mappings":"AAQA,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAU,CAAC;AACnH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,OAAO,CAAU,CAAC;AAEpD,MAAM,mBAAmB,GAAwC;IAC/D,OAAO,EAAE;QACP,IAAI,EAAE,OAAO;QACb,KAAK,EAAE;YACL,KAAK,EAAE,0BAA0B;YACjC,OAAO,EAAE,mGAAmG;YAC5G,cAAc,EAAE,IAAI;YACpB,KAAK,EAAE,CAAC,8BAA8B,EAAE,iCAAiC,EAAE,6BAA6B,CAAC;YACzG,eAAe,EAAE,CAAC,0DAA0D,EAAE,4CAA4C,EAAE,mCAAmC,CAAC;SACjK;QACD,KAAK,EAAE;YACL;gBACE,EAAE,EAAE,iCAAiC;gBACrC,QAAQ,EAAE,IAAI;gBACd,KAAK,EAAE,oCAAoC;gBAC3C,GAAG,EAAE,8FAA8F;gBACnG,KAAK,EAAE,OAAO;gBACd,KAAK,EAAE,CAAC,4BAA4B,EAAE,0BAA0B,EAAE,iBAAiB,CAAC;gBACpF,YAAY,EAAE;oBACZ,QAAQ,EAAE,CAAC,sCAAsC,EAAE,UAAU,CAAC;oBAC9D,QAAQ,EAAE,8FAA8F;iBACzG;aACF;SACF;KACF;IACD,OAAO,EAAE;QACP,IAAI,EAAE,OAAO;QACb,KAAK,EAAE;YACL,KAAK,EAAE,uBAAuB;YAC9B,OAAO,EAAE,2EAA2E;YACpF,cAAc,EAAE,IAAI;YACpB,KAAK,EAAE,CAAC,sBAAsB,EAAE,kCAAkC,EAAE,2BAA2B,CAAC;YAChG,eAAe,EAAE,CAAC,mCAAmC,EAAE,gDAAgD,EAAE,6DAA6D,CAAC;SACxK;QACD,KAAK,EAAE;YACL;gBACE,EAAE,EAAE,8BAA8B;gBAClC,QAAQ,EAAE,IAAI;gBACd,KAAK,EAAE,8BAA8B;gBACrC,GAAG,EAAE,+FAA+F;gBACpG,KAAK,EAAE,OAAO;gBACd,KAAK,EAAE,CAAC,qBAAqB,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,2BAA2B,CAAC;gBAC1G,YAAY,EAAE;oBACZ,QAAQ,EAAE,CAAC,mHAAmH,CAAC;oBAC/H,QAAQ,EAAE,4GAA4G;iBACvH;aACF;SACF;KACF;IACD,OAAO,EAAE;QACP,IAAI,EAAE,OAAO;QACb,KAAK,EAAE;YACL,KAAK,EAAE,oBAAoB;YAC3B,OAAO,EAAE,gIAAgI;YACzI,cAAc,EAAE,IAAI;YACpB,KAAK,EAAE,CAAC,gBAAgB,EAAE,kBAAkB,EAAE,cAAc,EAAE,2BAA2B,EAAE,0BAA0B,CAAC;YACtH,eAAe,EAAE,CAAC,mEAAmE,EAAE,0CAA0C,EAAE,gDAAgD,CAAC;SACrL;QACD,KAAK,EAAE;YACL;gBACE,EAAE,EAAE,2BAA2B;gBAC/B,QAAQ,EAAE,IAAI;gBACd,KAAK,EAAE,+BAA+B;gBACtC,GAAG,EAAE,kJAAkJ;gBACvJ,KAAK,EAAE,OAAO;gBACd,KAAK,EAAE,CAAC,wBAAwB,EAAE,gCAAgC,EAAE,6BAA6B,EAAE,WAAW,EAAE,+BAA+B,CAAC;gBAChJ,YAAY,EAAE;oBACZ,QAAQ,EAAE,CAAC,8CAA8C,EAAE,iDAAiD,EAAE,UAAU,CAAC;oBACzH,QAAQ,EAAE,6GAA6G;iBACxH;aACF;SACF;KACF;IACD,OAAO,EAAE;QACP,IAAI,EAAE,OAAO;QACb,KAAK,EAAE;YACL,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"roadmapCatalog.js","sourceRoot":"","sources":["../../src/core/roadmapCatalog.ts"],"names":[],"mappings":"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"}
|
package/dist/fixes/eslintFix.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
2
|
import fs from 'node:fs/promises';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { fileExists } from '../utils/fileHelpers.js';
|
|
@@ -13,7 +13,11 @@ export const eslintFix = {
|
|
|
13
13
|
if (hasTypeScript) {
|
|
14
14
|
packages.push('@typescript-eslint/parser', '@typescript-eslint/eslint-plugin');
|
|
15
15
|
}
|
|
16
|
-
|
|
16
|
+
// execFile (no shell) keeps the package names off any shell command line,
|
|
17
|
+
// and `--ignore-scripts` blocks the scanned repo's npm lifecycle scripts —
|
|
18
|
+
// rootPath is potentially untrusted, so a plain `npm install` here would be
|
|
19
|
+
// an RCE vector the moment a user runs `projscan fix`. See testFix.
|
|
20
|
+
execFileSync('npm', ['install', '--save-dev', '--ignore-scripts', ...packages], {
|
|
17
21
|
cwd: rootPath,
|
|
18
22
|
stdio: 'pipe',
|
|
19
23
|
timeout: 60_000,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eslintFix.js","sourceRoot":"","sources":["../../src/fixes/eslintFix.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"eslintFix.js","sourceRoot":"","sources":["../../src/fixes/eslintFix.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,MAAM,CAAC,MAAM,SAAS,GAAQ;IAC5B,EAAE,EAAE,YAAY;IAChB,KAAK,EAAE,8BAA8B;IACrC,WAAW,EAAE,kDAAkD;IAC/D,OAAO,EAAE,gBAAgB;IAEzB,KAAK,CAAC,KAAK,CAAC,QAAgB;QAC1B,MAAM,aAAa,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC;QAE7E,MAAM,QAAQ,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC5B,IAAI,aAAa,EAAE,CAAC;YAClB,QAAQ,CAAC,IAAI,CAAC,2BAA2B,EAAE,kCAAkC,CAAC,CAAC;QACjF,CAAC;QAED,0EAA0E;QAC1E,2EAA2E;QAC3E,4EAA4E;QAC5E,oEAAoE;QACpE,YAAY,CAAC,KAAK,EAAE,CAAC,SAAS,EAAE,YAAY,EAAE,kBAAkB,EAAE,GAAG,QAAQ,CAAC,EAAE;YAC9E,GAAG,EAAE,QAAQ;YACb,KAAK,EAAE,MAAM;YACb,OAAO,EAAE,MAAM;SAChB,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,aAAa;YAC1B,CAAC,CAAC;gBACE,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;gBACjC,MAAM,EAAE,2BAA2B;gBACnC,OAAO,EAAE,CAAC,oBAAoB,CAAC;gBAC/B,OAAO,EAAE,CAAC,oBAAoB,EAAE,uCAAuC,CAAC;gBACxE,aAAa,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE;gBAC9D,KAAK,EAAE,EAAE;aACV;YACH,CAAC,CAAC;gBACE,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;gBACjC,OAAO,EAAE,CAAC,oBAAoB,CAAC;gBAC/B,aAAa,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE;gBAC9D,KAAK,EAAE,EAAE;aACV,CAAC;QAEN,MAAM,EAAE,CAAC,SAAS,CAChB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,gBAAgB,CAAC,EACrC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EACtC,OAAO,CACR,CAAC;IACJ,CAAC;CACF,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
2
|
import fs from 'node:fs/promises';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
export const prettierFix = {
|
|
@@ -7,7 +7,10 @@ export const prettierFix = {
|
|
|
7
7
|
description: 'Installs Prettier and creates a configuration file',
|
|
8
8
|
issueId: 'missing-prettier',
|
|
9
9
|
async apply(rootPath) {
|
|
10
|
-
|
|
10
|
+
// `--ignore-scripts`: see testFix — rootPath is untrusted, so block the
|
|
11
|
+
// scanned repo's npm lifecycle scripts (RCE vector). execFile (no shell)
|
|
12
|
+
// avoids putting anything on a shell command line.
|
|
13
|
+
execFileSync('npm', ['install', '--save-dev', '--ignore-scripts', 'prettier'], {
|
|
11
14
|
cwd: rootPath,
|
|
12
15
|
stdio: 'pipe',
|
|
13
16
|
timeout: 60_000,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prettierFix.js","sourceRoot":"","sources":["../../src/fixes/prettierFix.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"prettierFix.js","sourceRoot":"","sources":["../../src/fixes/prettierFix.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,MAAM,CAAC,MAAM,WAAW,GAAQ;IAC9B,EAAE,EAAE,cAAc;IAClB,KAAK,EAAE,gCAAgC;IACvC,WAAW,EAAE,oDAAoD;IACjE,OAAO,EAAE,kBAAkB;IAE3B,KAAK,CAAC,KAAK,CAAC,QAAgB;QAC1B,wEAAwE;QACxE,yEAAyE;QACzE,mDAAmD;QACnD,YAAY,CAAC,KAAK,EAAE,CAAC,SAAS,EAAE,YAAY,EAAE,kBAAkB,EAAE,UAAU,CAAC,EAAE;YAC7E,GAAG,EAAE,QAAQ;YACb,KAAK,EAAE,MAAM;YACb,OAAO,EAAE,MAAM;SAChB,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG;YACb,IAAI,EAAE,IAAI;YACV,WAAW,EAAE,IAAI;YACjB,aAAa,EAAE,KAAK;YACpB,UAAU,EAAE,GAAG;YACf,QAAQ,EAAE,CAAC;SACZ,CAAC;QAEF,MAAM,EAAE,CAAC,SAAS,CAChB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,EAClC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EACtC,OAAO,CACR,CAAC;QAEF,mDAAmD;QACnD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QACpD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAChD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAE5B,IAAI,CAAC,GAAG,CAAC,OAAO;gBAAE,GAAG,CAAC,OAAO,GAAG,EAAE,CAAC;YACnC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;gBACxB,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,oBAAoB,CAAC;gBAC1C,MAAM,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;YAC5E,CAAC;QACH,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,IAAI,GAAG,YAAY,KAAK,IAAI,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACnE,OAAO,CAAC,sCAAsC;YAChD,CAAC;YACD,MAAM,GAAG,CAAC,CAAC,oDAAoD;QACjE,CAAC;IACH,CAAC;CACF,CAAC"}
|
package/dist/fixes/testFix.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
2
|
import fs from 'node:fs/promises';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { fileExists } from '../utils/fileHelpers.js';
|
|
@@ -8,7 +8,13 @@ export const testFix = {
|
|
|
8
8
|
description: 'Installs Vitest and creates a sample test file',
|
|
9
9
|
issueId: 'missing-test-framework',
|
|
10
10
|
async apply(rootPath) {
|
|
11
|
-
|
|
11
|
+
// `--ignore-scripts`: rootPath is the scanned (potentially untrusted) repo.
|
|
12
|
+
// Without it, `npm install` would run that repo's preinstall/install/
|
|
13
|
+
// postinstall/prepare lifecycle scripts — and any installed dependency's
|
|
14
|
+
// install scripts — turning `projscan fix` into arbitrary code execution
|
|
15
|
+
// on a hostile repo. execFile (no shell) also keeps package names off any
|
|
16
|
+
// shell command line.
|
|
17
|
+
execFileSync('npm', ['install', '--save-dev', '--ignore-scripts', 'vitest'], {
|
|
12
18
|
cwd: rootPath,
|
|
13
19
|
stdio: 'pipe',
|
|
14
20
|
timeout: 60_000,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testFix.js","sourceRoot":"","sources":["../../src/fixes/testFix.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"testFix.js","sourceRoot":"","sources":["../../src/fixes/testFix.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,MAAM,CAAC,MAAM,OAAO,GAAQ;IAC1B,EAAE,EAAE,WAAW;IACf,KAAK,EAAE,8BAA8B;IACrC,WAAW,EAAE,gDAAgD;IAC7D,OAAO,EAAE,wBAAwB;IAEjC,KAAK,CAAC,KAAK,CAAC,QAAgB;QAC1B,4EAA4E;QAC5E,sEAAsE;QACtE,yEAAyE;QACzE,yEAAyE;QACzE,0EAA0E;QAC1E,sBAAsB;QACtB,YAAY,CAAC,KAAK,EAAE,CAAC,SAAS,EAAE,YAAY,EAAE,kBAAkB,EAAE,QAAQ,CAAC,EAAE;YAC3E,GAAG,EAAE,QAAQ;YACb,KAAK,EAAE,MAAM;YACb,OAAO,EAAE,MAAM;SAChB,CAAC,CAAC;QAEH,kCAAkC;QAClC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QACpD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAChD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAE5B,IAAI,CAAC,GAAG,CAAC,OAAO;gBAAE,GAAG,CAAC,OAAO,GAAG,EAAE,CAAC;YACnC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;gBACtB,GAAG,CAAC,OAAO,CAAC,IAAI,GAAG,YAAY,CAAC;YAClC,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;gBAC/B,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,QAAQ,CAAC;YACvC,CAAC;YAED,MAAM,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;QAC5E,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,IAAI,GAAG,YAAY,KAAK,IAAI,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACnE,OAAO,CAAC,sCAAsC;YAChD,CAAC;YACD,MAAM,GAAG,CAAC,CAAC,oDAAoD;QACjE,CAAC;QAED,yCAAyC;QACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC9C,MAAM,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE9C,MAAM,aAAa,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC;QAC7E,MAAM,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;QAExC,MAAM,UAAU,GAAG;;;;;;;CAOtB,CAAC;QAEE,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,gBAAgB,GAAG,EAAE,CAAC,CAAC;QAChE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,YAAY,CAAC,CAAC;QAC9C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,EAAE,CAAC,SAAS,CAAC,YAAY,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { McpTool } from './_shared.js';
|
|
2
|
+
/**
|
|
3
|
+
* `projscan_claim` (4.x coordination arc) — advisory claims / leases so parallel
|
|
4
|
+
* agents see who owns which file, directory, or symbol. Shared across the
|
|
5
|
+
* repo's git worktrees; local-first.
|
|
6
|
+
*/
|
|
7
|
+
export declare const claimTool: McpTool;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { addClaim, listClaims, releaseClaim, pruneClaims } from '../../core/claims.js';
|
|
2
|
+
/**
|
|
3
|
+
* `projscan_claim` (4.x coordination arc) — advisory claims / leases so parallel
|
|
4
|
+
* agents see who owns which file, directory, or symbol. Shared across the
|
|
5
|
+
* repo's git worktrees; local-first.
|
|
6
|
+
*/
|
|
7
|
+
export const claimTool = {
|
|
8
|
+
name: 'projscan_claim',
|
|
9
|
+
description: "Coordinate parallel agents with advisory claims/leases over files, directories, or symbols, shared across the repo's git worktrees. action:\"add\" records a claim (optionally a lease with `ttl_seconds`) and returns any `contention` (another agent already holding an overlapping, non-expired claim); \"list\" returns claims; \"release\" drops a claim by `id`, by `target`, or all of an `agent`'s; \"prune\" removes expired-lease claims. Local-first and advisory — claiming an already-claimed target still succeeds, but surfaces contention so the swarm can coordinate.",
|
|
10
|
+
inputSchema: {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
action: {
|
|
14
|
+
type: 'string',
|
|
15
|
+
enum: ['add', 'list', 'release', 'prune'],
|
|
16
|
+
description: 'Default "list". "add" records a claim; "release" drops one; "prune" removes expired leases.',
|
|
17
|
+
},
|
|
18
|
+
target: {
|
|
19
|
+
type: 'string',
|
|
20
|
+
description: '"add"/"release" — a repo-relative file or directory path, or a symbol name.',
|
|
21
|
+
},
|
|
22
|
+
agent: {
|
|
23
|
+
type: 'string',
|
|
24
|
+
description: '"add" — who holds the claim. "release" — scope the release to this agent.',
|
|
25
|
+
},
|
|
26
|
+
note: { type: 'string', description: '"add" — optional human-readable note.' },
|
|
27
|
+
ttl_seconds: { type: 'number', description: '"add" — lease duration in seconds; the claim expires after it. Omit for a permanent claim.' },
|
|
28
|
+
id: { type: 'string', description: '"release" — the claim id to drop.' },
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
handler: async (args, rootPath) => {
|
|
32
|
+
const action = typeof args.action === 'string' ? args.action : 'list';
|
|
33
|
+
switch (action) {
|
|
34
|
+
case 'add': {
|
|
35
|
+
const target = typeof args.target === 'string' ? args.target : '';
|
|
36
|
+
const agent = typeof args.agent === 'string' ? args.agent : '';
|
|
37
|
+
if (!target || !agent) {
|
|
38
|
+
throw new Error('projscan_claim add requires both `target` and `agent`.');
|
|
39
|
+
}
|
|
40
|
+
const note = typeof args.note === 'string' && args.note.length > 0 ? args.note : undefined;
|
|
41
|
+
const ttlSeconds = typeof args.ttl_seconds === 'number' && args.ttl_seconds > 0 ? args.ttl_seconds : undefined;
|
|
42
|
+
return addClaim(rootPath, {
|
|
43
|
+
target,
|
|
44
|
+
agent,
|
|
45
|
+
...(note ? { note } : {}),
|
|
46
|
+
...(ttlSeconds !== undefined ? { ttlSeconds } : {}),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
case 'release': {
|
|
50
|
+
const selector = {
|
|
51
|
+
id: typeof args.id === 'string' && args.id.length > 0 ? args.id : undefined,
|
|
52
|
+
target: typeof args.target === 'string' && args.target.length > 0 ? args.target : undefined,
|
|
53
|
+
agent: typeof args.agent === 'string' && args.agent.length > 0 ? args.agent : undefined,
|
|
54
|
+
};
|
|
55
|
+
if (!selector.id && !selector.target && !selector.agent) {
|
|
56
|
+
throw new Error('projscan_claim release requires one of `id`, `target`, or `agent`.');
|
|
57
|
+
}
|
|
58
|
+
return { released: await releaseClaim(rootPath, selector) };
|
|
59
|
+
}
|
|
60
|
+
case 'prune':
|
|
61
|
+
return { pruned: await pruneClaims(rootPath) };
|
|
62
|
+
case 'list':
|
|
63
|
+
return { claims: await listClaims(rootPath) };
|
|
64
|
+
default:
|
|
65
|
+
throw new Error(`Unknown action "${action}". Known: add, list, release, prune.`);
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
//# sourceMappingURL=claim.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claim.js","sourceRoot":"","sources":["../../../src/mcp/tools/claim.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { McpTool } from './_shared.js';
|
|
2
|
+
/**
|
|
3
|
+
* `projscan_collision` (4.x coordination arc) — detect change collisions across
|
|
4
|
+
* the repo's in-flight git worktrees, so parallel agents see overlaps before
|
|
5
|
+
* their branches merge. Local-first; reads `git worktree list` only.
|
|
6
|
+
*/
|
|
7
|
+
export declare const collisionTool: McpTool;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { detectCollisions } from '../../core/collisionDetector.js';
|
|
2
|
+
/**
|
|
3
|
+
* `projscan_collision` (4.x coordination arc) — detect change collisions across
|
|
4
|
+
* the repo's in-flight git worktrees, so parallel agents see overlaps before
|
|
5
|
+
* their branches merge. Local-first; reads `git worktree list` only.
|
|
6
|
+
*/
|
|
7
|
+
export const collisionTool = {
|
|
8
|
+
name: 'projscan_collision',
|
|
9
|
+
description: "Detect change collisions across the repo's in-flight git worktrees (parallel agents). Reports same-file edits (two worktrees changed the same file) and dependency overlaps (one worktree changed a file another's change imports, via the import graph) BEFORE the branches merge. Local-first; needs at least two worktrees. Each collision has `kind` (same-file | dependency), `severity` (high | medium), the two worktree paths, and the files at risk. Use this when coordinating multiple agents/sub-agents working the same repo.",
|
|
10
|
+
inputSchema: {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
base_ref: {
|
|
14
|
+
type: 'string',
|
|
15
|
+
description: 'Base ref each worktree is diffed against to compute its changed files. Default: origin/main → main → master → HEAD~1, then the working tree.',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
handler: async (args, rootPath) => {
|
|
20
|
+
const baseRef = typeof args.base_ref === 'string' && args.base_ref.length > 0 ? args.base_ref : undefined;
|
|
21
|
+
return detectCollisions(rootPath, baseRef ? { baseRef } : {});
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=collision.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collision.js","sourceRoot":"","sources":["../../../src/mcp/tools/collision.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAGnE;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAY;IACpC,IAAI,EAAE,oBAAoB;IAC1B,WAAW,EACT,4gBAA4gB;IAC9gB,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,QAAQ,EAAE;gBACR,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,8IAA8I;aACjJ;SACF;KACF;IACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;QAChC,MAAM,OAAO,GAAG,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;QAC1G,OAAO,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAChE,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { McpTool } from './_shared.js';
|
|
2
|
+
/**
|
|
3
|
+
* `projscan_coordinate` (4.x arc, epic 5 — capstone) — one-call coordination
|
|
4
|
+
* read across the repo's in-flight worktrees, composing collisions, claims, and
|
|
5
|
+
* merge-risk into a single readiness verdict + counts. Local-first.
|
|
6
|
+
*/
|
|
7
|
+
export declare const coordinateTool: McpTool;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { computeCoordination } from '../../core/coordination.js';
|
|
2
|
+
/**
|
|
3
|
+
* `projscan_coordinate` (4.x arc, epic 5 — capstone) — one-call coordination
|
|
4
|
+
* read across the repo's in-flight worktrees, composing collisions, claims, and
|
|
5
|
+
* merge-risk into a single readiness verdict + counts. Local-first.
|
|
6
|
+
*/
|
|
7
|
+
export const coordinateTool = {
|
|
8
|
+
name: 'projscan_coordinate',
|
|
9
|
+
description: "One-call coordination read across the repo's in-flight git worktrees (parallel agents). Composes collisions, claims, and merge-risk into a `readiness` verdict (clear | caution | conflicted) plus counts (collisions by severity, contended claim targets, merge hotspots) and the recommended integration order. The single entry point for swarm coordination — use it before continuing parallel work. Local-first; needs at least two worktrees.",
|
|
10
|
+
inputSchema: {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
base_ref: {
|
|
14
|
+
type: 'string',
|
|
15
|
+
description: 'Base ref each worktree is diffed against. Default: origin/main → main → master → HEAD~1.',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
handler: async (args, rootPath) => {
|
|
20
|
+
const baseRef = typeof args.base_ref === 'string' && args.base_ref.length > 0 ? args.base_ref : undefined;
|
|
21
|
+
return computeCoordination(rootPath, baseRef ? { baseRef } : {});
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=coordinate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordinate.js","sourceRoot":"","sources":["../../../src/mcp/tools/coordinate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAGjE;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAY;IACrC,IAAI,EAAE,qBAAqB;IAC3B,WAAW,EACT,ubAAub;IACzb,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,QAAQ,EAAE;gBACR,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,0FAA0F;aACxG;SACF;KACF;IACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;QAChC,MAAM,OAAO,GAAG,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;QAC1G,OAAO,mBAAmB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACnE,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { McpTool } from './_shared.js';
|
|
2
|
+
/**
|
|
3
|
+
* `projscan_merge_risk` (4.x coordination arc, epic 3) — given the repo's
|
|
4
|
+
* in-flight worktrees and their collisions, return a safe integration order and
|
|
5
|
+
* the files where conflict risk concentrates. Builds on `projscan_collision`.
|
|
6
|
+
*/
|
|
7
|
+
export declare const mergeRiskTool: McpTool;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { computeMergeRisk } from '../../core/mergeRisk.js';
|
|
2
|
+
/**
|
|
3
|
+
* `projscan_merge_risk` (4.x coordination arc, epic 3) — given the repo's
|
|
4
|
+
* in-flight worktrees and their collisions, return a safe integration order and
|
|
5
|
+
* the files where conflict risk concentrates. Builds on `projscan_collision`.
|
|
6
|
+
*/
|
|
7
|
+
export const mergeRiskTool = {
|
|
8
|
+
name: 'projscan_merge_risk',
|
|
9
|
+
description: "Merge-risk preflight across the repo's in-flight git worktrees (parallel agents). Given each worktree's changes and the collisions between them, returns `integrationOrder` (merge the least-entangled branch first, each with a risk score) and `hotFiles` (files changed by two or more worktrees — where merge conflict risk concentrates). Builds on projscan_collision; local-first; needs at least two worktrees.",
|
|
10
|
+
inputSchema: {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
base_ref: {
|
|
14
|
+
type: 'string',
|
|
15
|
+
description: 'Base ref each worktree is diffed against. Default: origin/main → main → master → HEAD~1.',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
handler: async (args, rootPath) => {
|
|
20
|
+
const baseRef = typeof args.base_ref === 'string' && args.base_ref.length > 0 ? args.base_ref : undefined;
|
|
21
|
+
return computeMergeRisk(rootPath, baseRef ? { baseRef } : {});
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=mergeRisk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mergeRisk.js","sourceRoot":"","sources":["../../../src/mcp/tools/mergeRisk.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAG3D;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAY;IACpC,IAAI,EAAE,qBAAqB;IAC3B,WAAW,EACT,yZAAyZ;IAC3Z,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,QAAQ,EAAE;gBACR,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,0FAA0F;aACxG;SACF;KACF;IACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;QAChC,MAAM,OAAO,GAAG,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;QAC1G,OAAO,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAChE,CAAC;CACF,CAAC"}
|
package/dist/mcp/tools/plugin.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { PLUGIN_DIR, PLUGIN_MANIFEST_EXT, PLUGIN_PREVIEW_FLAG, discoverPluginManifests, pluginsEnabled, readPluginManifestFile, } from '../../core/plugins.js';
|
|
4
|
+
import { getPluginTrustStatus } from '../../core/pluginTrust.js';
|
|
4
5
|
/**
|
|
5
6
|
* `projscan_plugin` — discover and validate stable local analyzer/reporter
|
|
6
7
|
* plugins under `<root>/.projscan-plugins/*.projscan-plugin.json`.
|
|
@@ -11,7 +12,7 @@ import { PLUGIN_DIR, PLUGIN_MANIFEST_EXT, PLUGIN_PREVIEW_FLAG, discoverPluginMan
|
|
|
11
12
|
*/
|
|
12
13
|
export const pluginTool = {
|
|
13
14
|
name: 'projscan_plugin',
|
|
14
|
-
description: 'Discover and validate stable local analyzer and reporter plugins under .projscan-plugins/. Execution is opt-in via the PROJSCAN_PLUGINS_PREVIEW=1 env flag
|
|
15
|
+
description: 'Discover and validate stable local analyzer and reporter plugins under .projscan-plugins/. Execution is opt-in via the PROJSCAN_PLUGINS_PREVIEW=1 env flag AND each module must be approved with trust-on-first-use; the list reports a per-plugin `trust` status (trusted / untrusted / changed). Approving a plugin is a deliberate human action via the `projscan plugin trust <name>` CLI — it is intentionally not exposed here. Use action:"list" to see what is discoverable and whether it would run, action:"validate" to check a manifest before committing it.',
|
|
15
16
|
inputSchema: {
|
|
16
17
|
type: 'object',
|
|
17
18
|
properties: {
|
|
@@ -31,25 +32,32 @@ export const pluginTool = {
|
|
|
31
32
|
switch (action) {
|
|
32
33
|
case 'list': {
|
|
33
34
|
const entries = await discoverPluginManifests(rootPath);
|
|
35
|
+
const plugins = await Promise.all(entries.map(async (e) => {
|
|
36
|
+
if (!e.manifest) {
|
|
37
|
+
return { manifestPath: e.manifestPath, ok: false, error: e.error, diagnostic: e.diagnostic };
|
|
38
|
+
}
|
|
39
|
+
const modulePath = path.resolve(path.dirname(e.manifestPath), e.manifest.module);
|
|
40
|
+
const trust = await getPluginTrustStatus(modulePath);
|
|
41
|
+
return {
|
|
42
|
+
manifestPath: e.manifestPath,
|
|
43
|
+
ok: true,
|
|
44
|
+
name: e.manifest.name,
|
|
45
|
+
kind: e.manifest.kind,
|
|
46
|
+
module: e.manifest.module,
|
|
47
|
+
...(e.manifest.kind === 'analyzer'
|
|
48
|
+
? { category: e.manifest.category }
|
|
49
|
+
: { commands: e.manifest.commands }),
|
|
50
|
+
description: e.manifest.description,
|
|
51
|
+
// Whether this module would actually execute: even with the
|
|
52
|
+
// preview flag on, an untrusted/changed module is skipped.
|
|
53
|
+
trust: trust.status,
|
|
54
|
+
};
|
|
55
|
+
}));
|
|
34
56
|
return {
|
|
35
57
|
enabled: pluginsEnabled(),
|
|
36
58
|
envFlag: PLUGIN_PREVIEW_FLAG,
|
|
37
59
|
count: entries.length,
|
|
38
|
-
plugins
|
|
39
|
-
manifestPath: e.manifestPath,
|
|
40
|
-
ok: e.manifest !== null,
|
|
41
|
-
...(e.manifest
|
|
42
|
-
? {
|
|
43
|
-
name: e.manifest.name,
|
|
44
|
-
kind: e.manifest.kind,
|
|
45
|
-
module: e.manifest.module,
|
|
46
|
-
...(e.manifest.kind === 'analyzer'
|
|
47
|
-
? { category: e.manifest.category }
|
|
48
|
-
: { commands: e.manifest.commands }),
|
|
49
|
-
description: e.manifest.description,
|
|
50
|
-
}
|
|
51
|
-
: { error: e.error, diagnostic: e.diagnostic }),
|
|
52
|
-
})),
|
|
60
|
+
plugins,
|
|
53
61
|
};
|
|
54
62
|
}
|
|
55
63
|
case 'validate': {
|