@lousy-agents/mcp 5.20.2 → 5.21.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/dist/mcp-server.js +708 -15
- package/package.json +1 -1
package/dist/mcp-server.js
CHANGED
|
@@ -6559,7 +6559,7 @@ function escapeJsonPtr(str) {
|
|
|
6559
6559
|
|
|
6560
6560
|
|
|
6561
6561
|
},
|
|
6562
|
-
|
|
6562
|
+
7444(__unused_rspack_module, __unused_rspack___webpack_exports__, __webpack_require__) {
|
|
6563
6563
|
// NAMESPACE OBJECT: ../../node_modules/micromark/lib/constructs.js
|
|
6564
6564
|
var constructs_namespaceObject = {};
|
|
6565
6565
|
__webpack_require__.r(constructs_namespaceObject);
|
|
@@ -38932,6 +38932,612 @@ function createWorkflowGateway(cwd) {
|
|
|
38932
38932
|
}
|
|
38933
38933
|
};
|
|
38934
38934
|
|
|
38935
|
+
;// CONCATENATED MODULE: ../core/src/entities/source-position.ts
|
|
38936
|
+
/**
|
|
38937
|
+
* Pure helpers for mapping string offsets to 1-based line/column positions.
|
|
38938
|
+
*/ /** 1-based line and column within a text document */ /**
|
|
38939
|
+
* Maps a 0-based string offset into a 1-based line and column.
|
|
38940
|
+
* Offsets are clamped to [0, content.length]. Newlines (`\n`) advance the line.
|
|
38941
|
+
*/ function offsetToSourcePosition(content, offset) {
|
|
38942
|
+
const safeOffset = Math.max(0, Math.min(offset, content.length));
|
|
38943
|
+
let line = 1;
|
|
38944
|
+
let column = 1;
|
|
38945
|
+
for(let i = 0; i < safeOffset; i++){
|
|
38946
|
+
if (content[i] === "\n") {
|
|
38947
|
+
line += 1;
|
|
38948
|
+
column = 1;
|
|
38949
|
+
} else {
|
|
38950
|
+
column += 1;
|
|
38951
|
+
}
|
|
38952
|
+
}
|
|
38953
|
+
return {
|
|
38954
|
+
line,
|
|
38955
|
+
column
|
|
38956
|
+
};
|
|
38957
|
+
}
|
|
38958
|
+
|
|
38959
|
+
;// CONCATENATED MODULE: ../core/src/lib/instruction-import-expand.ts
|
|
38960
|
+
/**
|
|
38961
|
+
* Pure Claude `@` import expander that builds an ordered EffectiveDocument.
|
|
38962
|
+
*/
|
|
38963
|
+
|
|
38964
|
+
const DEFAULT_MAX_IMPORT_DEPTH = 4;
|
|
38965
|
+
const DEFAULT_MAX_UNIQUE_FILES = 64;
|
|
38966
|
+
const DEFAULT_MAX_EDGES = 256;
|
|
38967
|
+
const DEFAULT_MAX_EMITTED_BYTES = 512_000;
|
|
38968
|
+
const DEFAULT_MAX_FILE_BYTES = 1_048_576;
|
|
38969
|
+
/** Aligns with doctor HARD_IMPORT: line-start `@path` where path includes `/`. */ const HARD_IMPORT_GLOBAL_RE = /^@([^\s@][^\s]*)/gm;
|
|
38970
|
+
const FENCED_CODE_RE = /^(`{3,}|~{3,})[^\r\n]*\r?\n[\s\S]*?^\1[ \t]*$/gm;
|
|
38971
|
+
const INLINE_CODE_RE = /`+[^`\r\n]*`+/g;
|
|
38972
|
+
function resolveLimits(overrides) {
|
|
38973
|
+
return {
|
|
38974
|
+
maxDepth: overrides?.maxDepth ?? DEFAULT_MAX_IMPORT_DEPTH,
|
|
38975
|
+
maxUniqueFiles: overrides?.maxUniqueFiles ?? DEFAULT_MAX_UNIQUE_FILES,
|
|
38976
|
+
maxEdges: overrides?.maxEdges ?? DEFAULT_MAX_EDGES,
|
|
38977
|
+
maxEmittedBytes: overrides?.maxEmittedBytes ?? DEFAULT_MAX_EMITTED_BYTES,
|
|
38978
|
+
maxFileBytes: overrides?.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES
|
|
38979
|
+
};
|
|
38980
|
+
}
|
|
38981
|
+
function toPosixRelative(pathValue) {
|
|
38982
|
+
return pathValue.split(external_node_path_.sep).join("/");
|
|
38983
|
+
}
|
|
38984
|
+
function isInsideCodeRegion(index, regions) {
|
|
38985
|
+
return regions.some((region)=>index >= region.start && index < region.end);
|
|
38986
|
+
}
|
|
38987
|
+
function collectRegexRanges(content, pattern, skipInside) {
|
|
38988
|
+
const regions = [];
|
|
38989
|
+
for (const match of content.matchAll(pattern)){
|
|
38990
|
+
if (match.index === undefined) {
|
|
38991
|
+
continue;
|
|
38992
|
+
}
|
|
38993
|
+
if (skipInside && isInsideCodeRegion(match.index, skipInside)) {
|
|
38994
|
+
continue;
|
|
38995
|
+
}
|
|
38996
|
+
regions.push({
|
|
38997
|
+
start: match.index,
|
|
38998
|
+
end: match.index + match[0].length
|
|
38999
|
+
});
|
|
39000
|
+
}
|
|
39001
|
+
return regions;
|
|
39002
|
+
}
|
|
39003
|
+
function findCodeRegions(content) {
|
|
39004
|
+
const fenced = collectRegexRanges(content, FENCED_CODE_RE);
|
|
39005
|
+
const inline = collectRegexRanges(content, INLINE_CODE_RE, fenced);
|
|
39006
|
+
return [
|
|
39007
|
+
...fenced,
|
|
39008
|
+
...inline
|
|
39009
|
+
];
|
|
39010
|
+
}
|
|
39011
|
+
function findImportTokens(content) {
|
|
39012
|
+
const codeRegions = findCodeRegions(content);
|
|
39013
|
+
const tokens = [];
|
|
39014
|
+
for (const match of content.matchAll(HARD_IMPORT_GLOBAL_RE)){
|
|
39015
|
+
if (match.index === undefined) {
|
|
39016
|
+
continue;
|
|
39017
|
+
}
|
|
39018
|
+
const rawTarget = match[1];
|
|
39019
|
+
if (!rawTarget?.includes("/")) {
|
|
39020
|
+
continue;
|
|
39021
|
+
}
|
|
39022
|
+
if (isInsideCodeRegion(match.index, codeRegions)) {
|
|
39023
|
+
continue;
|
|
39024
|
+
}
|
|
39025
|
+
tokens.push({
|
|
39026
|
+
start: match.index,
|
|
39027
|
+
end: match.index + match[0].length,
|
|
39028
|
+
rawTarget
|
|
39029
|
+
});
|
|
39030
|
+
}
|
|
39031
|
+
return tokens;
|
|
39032
|
+
}
|
|
39033
|
+
function rebaseSegments(segments, offset) {
|
|
39034
|
+
return segments.map((segment)=>({
|
|
39035
|
+
...segment,
|
|
39036
|
+
effectiveRange: {
|
|
39037
|
+
start: segment.effectiveRange.start + offset,
|
|
39038
|
+
end: segment.effectiveRange.end + offset
|
|
39039
|
+
}
|
|
39040
|
+
}));
|
|
39041
|
+
}
|
|
39042
|
+
function createLiteralSegment(contentOffset, sourcePath, sourceStart, text, importChain) {
|
|
39043
|
+
if (text.length === 0) {
|
|
39044
|
+
return undefined;
|
|
39045
|
+
}
|
|
39046
|
+
return {
|
|
39047
|
+
effectiveRange: {
|
|
39048
|
+
start: contentOffset,
|
|
39049
|
+
end: contentOffset + text.length
|
|
39050
|
+
},
|
|
39051
|
+
sourcePath,
|
|
39052
|
+
sourceRange: {
|
|
39053
|
+
start: sourceStart,
|
|
39054
|
+
end: sourceStart + text.length
|
|
39055
|
+
},
|
|
39056
|
+
importChain: [
|
|
39057
|
+
...importChain
|
|
39058
|
+
]
|
|
39059
|
+
};
|
|
39060
|
+
}
|
|
39061
|
+
const RULE_ID_BY_STATUS = {
|
|
39062
|
+
unresolved: "instruction/import-unresolved",
|
|
39063
|
+
"not-regular": "instruction/import-unresolved",
|
|
39064
|
+
escape: "instruction/import-escape",
|
|
39065
|
+
absolute: "instruction/import-escape",
|
|
39066
|
+
home: "instruction/import-escape",
|
|
39067
|
+
symlink: "instruction/import-symlink",
|
|
39068
|
+
cycle: "instruction/import-cycle",
|
|
39069
|
+
"depth-exceeded": "instruction/import-depth-exceeded",
|
|
39070
|
+
"size-exceeded": "instruction/import-size-exceeded",
|
|
39071
|
+
resolved: undefined
|
|
39072
|
+
};
|
|
39073
|
+
const FAILURE_MESSAGE_BY_STATUS = {
|
|
39074
|
+
unresolved: (rawTarget)=>`Import target could not be resolved: ${rawTarget}`,
|
|
39075
|
+
escape: (rawTarget)=>`Import target escapes the repository root: ${rawTarget}`,
|
|
39076
|
+
absolute: (rawTarget)=>`Absolute import paths are not allowed: ${rawTarget}`,
|
|
39077
|
+
home: (rawTarget)=>`Home-directory import paths are not allowed: ${rawTarget}`,
|
|
39078
|
+
symlink: (rawTarget)=>`Import target path contains a symbolic link: ${rawTarget}`,
|
|
39079
|
+
cycle: (rawTarget)=>`Import cycle detected while resolving: ${rawTarget}`,
|
|
39080
|
+
"depth-exceeded": (rawTarget)=>`Import depth limit exceeded while resolving: ${rawTarget}`,
|
|
39081
|
+
"size-exceeded": (rawTarget)=>`Import expansion size or graph limit exceeded while resolving: ${rawTarget}`,
|
|
39082
|
+
"not-regular": (rawTarget)=>`Import target is not a regular file: ${rawTarget}`,
|
|
39083
|
+
resolved: ()=>""
|
|
39084
|
+
};
|
|
39085
|
+
function ruleIdForStatus(status) {
|
|
39086
|
+
return RULE_ID_BY_STATUS[status];
|
|
39087
|
+
}
|
|
39088
|
+
function messageForFailure(status, rawTarget) {
|
|
39089
|
+
return FAILURE_MESSAGE_BY_STATUS[status](rawTarget);
|
|
39090
|
+
}
|
|
39091
|
+
function classifyPathError(error) {
|
|
39092
|
+
if (!(error instanceof Error)) {
|
|
39093
|
+
return "unresolved";
|
|
39094
|
+
}
|
|
39095
|
+
const message = error.message;
|
|
39096
|
+
if (message.includes("outside target directory") || message.includes("invalid-path") || message.includes("outside-workspace")) {
|
|
39097
|
+
return "escape";
|
|
39098
|
+
}
|
|
39099
|
+
if (message.includes("Symlinks are not allowed") || message.includes("symbolic link") || message.includes("path-alias")) {
|
|
39100
|
+
return "symlink";
|
|
39101
|
+
}
|
|
39102
|
+
if (message.includes("exceeds size limit") || message.includes("too-large")) {
|
|
39103
|
+
return "size-exceeded";
|
|
39104
|
+
}
|
|
39105
|
+
return "unresolved";
|
|
39106
|
+
}
|
|
39107
|
+
function normalizeRelativeWithinRoot(importerRelativePath, rawTarget) {
|
|
39108
|
+
if (rawTarget === "~" || rawTarget.startsWith("~/") || rawTarget.startsWith("~\\")) {
|
|
39109
|
+
return {
|
|
39110
|
+
ok: false,
|
|
39111
|
+
status: "home"
|
|
39112
|
+
};
|
|
39113
|
+
}
|
|
39114
|
+
if ((0,external_node_path_.isAbsolute)(rawTarget)) {
|
|
39115
|
+
return {
|
|
39116
|
+
ok: false,
|
|
39117
|
+
status: "absolute"
|
|
39118
|
+
};
|
|
39119
|
+
}
|
|
39120
|
+
const importerDir = (0,external_node_path_.dirname)(importerRelativePath);
|
|
39121
|
+
const joined = (0,external_node_path_.normalize)((0,external_node_path_.join)(importerDir, rawTarget));
|
|
39122
|
+
const normalized = joined === "." ? "" : joined;
|
|
39123
|
+
if (normalized === ".." || normalized.startsWith(`..${external_node_path_.sep}`) || normalized.startsWith("../") || normalized.startsWith("..\\")) {
|
|
39124
|
+
return {
|
|
39125
|
+
ok: false,
|
|
39126
|
+
status: "escape"
|
|
39127
|
+
};
|
|
39128
|
+
}
|
|
39129
|
+
if (!normalized) {
|
|
39130
|
+
return {
|
|
39131
|
+
ok: false,
|
|
39132
|
+
status: "unresolved"
|
|
39133
|
+
};
|
|
39134
|
+
}
|
|
39135
|
+
return {
|
|
39136
|
+
ok: true,
|
|
39137
|
+
relativePath: toPosixRelative(normalized)
|
|
39138
|
+
};
|
|
39139
|
+
}
|
|
39140
|
+
function isUnsafeRootPath(rootRelativePath) {
|
|
39141
|
+
return !rootRelativePath || rootRelativePath === ".." || rootRelativePath.startsWith(`..${external_node_path_.sep}`) || rootRelativePath.startsWith("../") || (0,external_node_path_.isAbsolute)(rootRelativePath);
|
|
39142
|
+
}
|
|
39143
|
+
/**
|
|
39144
|
+
* Owns expansion bookkeeping for a single buildEffectiveDocument call.
|
|
39145
|
+
* Mutations stay on the session instance rather than shared parameter bags.
|
|
39146
|
+
*/ class ExpansionSession {
|
|
39147
|
+
limits;
|
|
39148
|
+
contentCache = new Map();
|
|
39149
|
+
uniqueFiles = new Set();
|
|
39150
|
+
edges = [];
|
|
39151
|
+
diagnostics = [];
|
|
39152
|
+
emittedBytes = 0;
|
|
39153
|
+
constructor(limits){
|
|
39154
|
+
this.limits = limits;
|
|
39155
|
+
}
|
|
39156
|
+
get edgeCount() {
|
|
39157
|
+
return this.edges.length;
|
|
39158
|
+
}
|
|
39159
|
+
get remainingEmitBudget() {
|
|
39160
|
+
return this.limits.maxEmittedBytes - this.emittedBytes;
|
|
39161
|
+
}
|
|
39162
|
+
isEmitBudgetExhausted() {
|
|
39163
|
+
return this.emittedBytes >= this.limits.maxEmittedBytes;
|
|
39164
|
+
}
|
|
39165
|
+
snapshot() {
|
|
39166
|
+
return {
|
|
39167
|
+
edges: [
|
|
39168
|
+
...this.edges
|
|
39169
|
+
],
|
|
39170
|
+
diagnostics: [
|
|
39171
|
+
...this.diagnostics
|
|
39172
|
+
]
|
|
39173
|
+
};
|
|
39174
|
+
}
|
|
39175
|
+
recordEdge(edge) {
|
|
39176
|
+
this.edges.push(edge);
|
|
39177
|
+
// Failures always carry ruleId; resolved edges do not.
|
|
39178
|
+
if (!edge.ruleId) {
|
|
39179
|
+
return;
|
|
39180
|
+
}
|
|
39181
|
+
this.diagnostics.push({
|
|
39182
|
+
ruleId: edge.ruleId,
|
|
39183
|
+
message: messageForFailure(edge.status, edge.rawTarget),
|
|
39184
|
+
filePath: edge.importer,
|
|
39185
|
+
range: edge.tokenRange
|
|
39186
|
+
});
|
|
39187
|
+
}
|
|
39188
|
+
recordFailure(importer, token, status, target) {
|
|
39189
|
+
this.recordEdge({
|
|
39190
|
+
importer,
|
|
39191
|
+
tokenRange: {
|
|
39192
|
+
start: token.start,
|
|
39193
|
+
end: token.end
|
|
39194
|
+
},
|
|
39195
|
+
rawTarget: token.rawTarget,
|
|
39196
|
+
target,
|
|
39197
|
+
status,
|
|
39198
|
+
ruleId: ruleIdForStatus(status)
|
|
39199
|
+
});
|
|
39200
|
+
}
|
|
39201
|
+
recordResolved(importer, token, target) {
|
|
39202
|
+
this.recordEdge({
|
|
39203
|
+
importer,
|
|
39204
|
+
tokenRange: {
|
|
39205
|
+
start: token.start,
|
|
39206
|
+
end: token.end
|
|
39207
|
+
},
|
|
39208
|
+
rawTarget: token.rawTarget,
|
|
39209
|
+
target,
|
|
39210
|
+
status: "resolved"
|
|
39211
|
+
});
|
|
39212
|
+
}
|
|
39213
|
+
/**
|
|
39214
|
+
* Emit up to `text` against the remaining byte budget.
|
|
39215
|
+
* Returns emitted text (possibly clipped) and whether the full text fit.
|
|
39216
|
+
*/ takeEmitBudget(text) {
|
|
39217
|
+
if (text.length === 0) {
|
|
39218
|
+
return {
|
|
39219
|
+
emitted: "",
|
|
39220
|
+
complete: true
|
|
39221
|
+
};
|
|
39222
|
+
}
|
|
39223
|
+
const room = this.remainingEmitBudget;
|
|
39224
|
+
if (room <= 0) {
|
|
39225
|
+
return {
|
|
39226
|
+
emitted: "",
|
|
39227
|
+
complete: false
|
|
39228
|
+
};
|
|
39229
|
+
}
|
|
39230
|
+
if (text.length <= room) {
|
|
39231
|
+
this.emittedBytes += text.length;
|
|
39232
|
+
return {
|
|
39233
|
+
emitted: text,
|
|
39234
|
+
complete: true
|
|
39235
|
+
};
|
|
39236
|
+
}
|
|
39237
|
+
this.emittedBytes += room;
|
|
39238
|
+
return {
|
|
39239
|
+
emitted: text.slice(0, room),
|
|
39240
|
+
complete: false
|
|
39241
|
+
};
|
|
39242
|
+
}
|
|
39243
|
+
async readFile(repoRoot, relativePath) {
|
|
39244
|
+
const cached = this.contentCache.get(relativePath);
|
|
39245
|
+
if (cached !== undefined) {
|
|
39246
|
+
return {
|
|
39247
|
+
ok: true,
|
|
39248
|
+
content: cached
|
|
39249
|
+
};
|
|
39250
|
+
}
|
|
39251
|
+
try {
|
|
39252
|
+
await file_system_utils_resolvePathWithinRoot(repoRoot, relativePath);
|
|
39253
|
+
} catch (error) {
|
|
39254
|
+
return {
|
|
39255
|
+
ok: false,
|
|
39256
|
+
status: classifyPathError(error)
|
|
39257
|
+
};
|
|
39258
|
+
}
|
|
39259
|
+
try {
|
|
39260
|
+
const stats = await file_system_utils_statWithinRoot(repoRoot, relativePath);
|
|
39261
|
+
if (stats.isSymbolicLink) {
|
|
39262
|
+
return {
|
|
39263
|
+
ok: false,
|
|
39264
|
+
status: "symlink"
|
|
39265
|
+
};
|
|
39266
|
+
}
|
|
39267
|
+
if (!stats.isFile) {
|
|
39268
|
+
return {
|
|
39269
|
+
ok: false,
|
|
39270
|
+
status: "not-regular"
|
|
39271
|
+
};
|
|
39272
|
+
}
|
|
39273
|
+
} catch (error) {
|
|
39274
|
+
return {
|
|
39275
|
+
ok: false,
|
|
39276
|
+
status: classifyPathError(error)
|
|
39277
|
+
};
|
|
39278
|
+
}
|
|
39279
|
+
const isNewUnique = !this.uniqueFiles.has(relativePath);
|
|
39280
|
+
if (isNewUnique && this.uniqueFiles.size >= this.limits.maxUniqueFiles) {
|
|
39281
|
+
return {
|
|
39282
|
+
ok: false,
|
|
39283
|
+
status: "size-exceeded"
|
|
39284
|
+
};
|
|
39285
|
+
}
|
|
39286
|
+
try {
|
|
39287
|
+
const content = await file_system_utils_readTextWithinRoot(repoRoot, relativePath, this.limits.maxFileBytes);
|
|
39288
|
+
this.contentCache.set(relativePath, content);
|
|
39289
|
+
if (isNewUnique) {
|
|
39290
|
+
this.uniqueFiles.add(relativePath);
|
|
39291
|
+
}
|
|
39292
|
+
return {
|
|
39293
|
+
ok: true,
|
|
39294
|
+
content
|
|
39295
|
+
};
|
|
39296
|
+
} catch (error) {
|
|
39297
|
+
return {
|
|
39298
|
+
ok: false,
|
|
39299
|
+
status: classifyPathError(error)
|
|
39300
|
+
};
|
|
39301
|
+
}
|
|
39302
|
+
}
|
|
39303
|
+
}
|
|
39304
|
+
class ContentBuilder {
|
|
39305
|
+
outputText = "";
|
|
39306
|
+
builtSegments = [];
|
|
39307
|
+
get output() {
|
|
39308
|
+
return this.outputText;
|
|
39309
|
+
}
|
|
39310
|
+
get length() {
|
|
39311
|
+
return this.outputText.length;
|
|
39312
|
+
}
|
|
39313
|
+
get segments() {
|
|
39314
|
+
return this.builtSegments;
|
|
39315
|
+
}
|
|
39316
|
+
appendLiteral(sourcePath, sourceStart, text, importChain) {
|
|
39317
|
+
const segment = createLiteralSegment(this.outputText.length, sourcePath, sourceStart, text, importChain);
|
|
39318
|
+
if (!segment) {
|
|
39319
|
+
return;
|
|
39320
|
+
}
|
|
39321
|
+
this.builtSegments.push(segment);
|
|
39322
|
+
this.outputText += text;
|
|
39323
|
+
}
|
|
39324
|
+
appendExpanded(content, segments) {
|
|
39325
|
+
this.outputText += content;
|
|
39326
|
+
this.builtSegments.push(...segments);
|
|
39327
|
+
}
|
|
39328
|
+
toResult() {
|
|
39329
|
+
return {
|
|
39330
|
+
content: this.outputText,
|
|
39331
|
+
segments: [
|
|
39332
|
+
...this.builtSegments
|
|
39333
|
+
]
|
|
39334
|
+
};
|
|
39335
|
+
}
|
|
39336
|
+
}
|
|
39337
|
+
function emitSourceSlice(session, builder, sourcePath, content, from, to, importChain) {
|
|
39338
|
+
if (to <= from) {
|
|
39339
|
+
return true;
|
|
39340
|
+
}
|
|
39341
|
+
const { emitted, complete } = session.takeEmitBudget(content.slice(from, to));
|
|
39342
|
+
builder.appendLiteral(sourcePath, from, emitted, importChain);
|
|
39343
|
+
return complete;
|
|
39344
|
+
}
|
|
39345
|
+
async function expandToken(session, repoRoot, importerPath, token, hop, stack, importChain, outputOffset) {
|
|
39346
|
+
if (session.edgeCount >= session.limits.maxEdges) {
|
|
39347
|
+
session.recordFailure(importerPath, token, "size-exceeded");
|
|
39348
|
+
return {
|
|
39349
|
+
kind: "unexpanded"
|
|
39350
|
+
};
|
|
39351
|
+
}
|
|
39352
|
+
const nextHop = hop + 1;
|
|
39353
|
+
if (nextHop > session.limits.maxDepth) {
|
|
39354
|
+
session.recordFailure(importerPath, token, "depth-exceeded");
|
|
39355
|
+
return {
|
|
39356
|
+
kind: "unexpanded"
|
|
39357
|
+
};
|
|
39358
|
+
}
|
|
39359
|
+
const normalized = normalizeRelativeWithinRoot(importerPath, token.rawTarget);
|
|
39360
|
+
if (!normalized.ok) {
|
|
39361
|
+
session.recordFailure(importerPath, token, normalized.status);
|
|
39362
|
+
return {
|
|
39363
|
+
kind: "unexpanded"
|
|
39364
|
+
};
|
|
39365
|
+
}
|
|
39366
|
+
const targetPath = normalized.relativePath;
|
|
39367
|
+
if (stack.includes(targetPath)) {
|
|
39368
|
+
session.recordFailure(importerPath, token, "cycle", targetPath);
|
|
39369
|
+
return {
|
|
39370
|
+
kind: "unexpanded"
|
|
39371
|
+
};
|
|
39372
|
+
}
|
|
39373
|
+
const readResult = await session.readFile(repoRoot, targetPath);
|
|
39374
|
+
if (!readResult.ok) {
|
|
39375
|
+
session.recordFailure(importerPath, token, readResult.status, targetPath);
|
|
39376
|
+
return {
|
|
39377
|
+
kind: "unexpanded"
|
|
39378
|
+
};
|
|
39379
|
+
}
|
|
39380
|
+
if (session.isEmitBudgetExhausted()) {
|
|
39381
|
+
session.recordFailure(importerPath, token, "size-exceeded", targetPath);
|
|
39382
|
+
return {
|
|
39383
|
+
kind: "unexpanded"
|
|
39384
|
+
};
|
|
39385
|
+
}
|
|
39386
|
+
const child = await expandContent(session, repoRoot, targetPath, readResult.content, nextHop, [
|
|
39387
|
+
...stack,
|
|
39388
|
+
targetPath
|
|
39389
|
+
], [
|
|
39390
|
+
...importChain,
|
|
39391
|
+
targetPath
|
|
39392
|
+
]);
|
|
39393
|
+
session.recordResolved(importerPath, token, targetPath);
|
|
39394
|
+
return {
|
|
39395
|
+
kind: "expanded",
|
|
39396
|
+
content: child.content,
|
|
39397
|
+
segments: rebaseSegments(child.segments, outputOffset)
|
|
39398
|
+
};
|
|
39399
|
+
}
|
|
39400
|
+
async function expandContent(session, repoRoot, sourcePath, content, hop, stack, importChain) {
|
|
39401
|
+
const tokens = findImportTokens(content);
|
|
39402
|
+
const builder = new ContentBuilder();
|
|
39403
|
+
let cursor = 0;
|
|
39404
|
+
for (const token of tokens){
|
|
39405
|
+
const literalOk = emitSourceSlice(session, builder, sourcePath, content, cursor, token.start, importChain);
|
|
39406
|
+
if (!literalOk) {
|
|
39407
|
+
session.recordFailure(sourcePath, token, "size-exceeded");
|
|
39408
|
+
emitSourceSlice(session, builder, sourcePath, content, token.start, content.length, importChain);
|
|
39409
|
+
return builder.toResult();
|
|
39410
|
+
}
|
|
39411
|
+
const expansion = await expandToken(session, repoRoot, sourcePath, token, hop, stack, importChain, builder.length);
|
|
39412
|
+
if (expansion.kind === "expanded") {
|
|
39413
|
+
builder.appendExpanded(expansion.content, expansion.segments);
|
|
39414
|
+
} else {
|
|
39415
|
+
const tokenOk = emitSourceSlice(session, builder, sourcePath, content, token.start, token.end, importChain);
|
|
39416
|
+
if (!tokenOk) {
|
|
39417
|
+
return builder.toResult();
|
|
39418
|
+
}
|
|
39419
|
+
}
|
|
39420
|
+
cursor = token.end;
|
|
39421
|
+
}
|
|
39422
|
+
emitSourceSlice(session, builder, sourcePath, content, cursor, content.length, importChain);
|
|
39423
|
+
return builder.toResult();
|
|
39424
|
+
}
|
|
39425
|
+
/**
|
|
39426
|
+
* Build an ordered effective document by expanding verified Claude `@` imports.
|
|
39427
|
+
*/ async function buildEffectiveDocument(input) {
|
|
39428
|
+
const limits = resolveLimits(input.limits);
|
|
39429
|
+
const rootRelativePath = toPosixRelative((0,external_node_path_.normalize)(input.rootRelativePath));
|
|
39430
|
+
if (isUnsafeRootPath(rootRelativePath)) {
|
|
39431
|
+
throw new Error(`Root path is outside repository root: ${input.rootRelativePath}`);
|
|
39432
|
+
}
|
|
39433
|
+
const session = new ExpansionSession(limits);
|
|
39434
|
+
const rootRead = await session.readFile(input.repoRoot, rootRelativePath);
|
|
39435
|
+
if (!rootRead.ok) {
|
|
39436
|
+
throw new Error(`Unable to read root instruction file ${rootRelativePath}: ${rootRead.status}`);
|
|
39437
|
+
}
|
|
39438
|
+
const expanded = await expandContent(session, input.repoRoot, rootRelativePath, rootRead.content, 0, [
|
|
39439
|
+
rootRelativePath
|
|
39440
|
+
], [
|
|
39441
|
+
rootRelativePath
|
|
39442
|
+
]);
|
|
39443
|
+
const snapshot = session.snapshot();
|
|
39444
|
+
return {
|
|
39445
|
+
root: rootRelativePath,
|
|
39446
|
+
content: expanded.content,
|
|
39447
|
+
orderedSegments: expanded.segments,
|
|
39448
|
+
edges: snapshot.edges,
|
|
39449
|
+
expansionDiagnostics: snapshot.diagnostics
|
|
39450
|
+
};
|
|
39451
|
+
}
|
|
39452
|
+
|
|
39453
|
+
;// CONCATENATED MODULE: ../core/src/gateways/claude-instruction-import-expander.ts
|
|
39454
|
+
/**
|
|
39455
|
+
* Adapter that expands Claude `@path` imports via the pure expander library.
|
|
39456
|
+
*/
|
|
39457
|
+
|
|
39458
|
+
|
|
39459
|
+
|
|
39460
|
+
function toRepoRelativePosix(repoRoot, absoluteFilePath) {
|
|
39461
|
+
const relativePath = (0,external_node_path_.relative)(repoRoot, absoluteFilePath);
|
|
39462
|
+
if (relativePath.length === 0 || relativePath.startsWith(`..${external_node_path_.sep}`) || relativePath === ".." || (0,external_node_path_.isAbsolute)(relativePath)) {
|
|
39463
|
+
throw new Error(`Claude instruction path is outside repository root: ${absoluteFilePath}`);
|
|
39464
|
+
}
|
|
39465
|
+
return relativePath.split(external_node_path_.sep).join("/");
|
|
39466
|
+
}
|
|
39467
|
+
function toAbsolutePath(repoRoot, relativePosixPath) {
|
|
39468
|
+
return (0,external_node_path_.join)(repoRoot, ...relativePosixPath.split("/"));
|
|
39469
|
+
}
|
|
39470
|
+
async function mapExpansionDiagnostics(repoRoot, diagnostics) {
|
|
39471
|
+
const contentByRelative = new Map();
|
|
39472
|
+
const mapped = [];
|
|
39473
|
+
for (const diagnostic of diagnostics){
|
|
39474
|
+
const absolutePath = toAbsolutePath(repoRoot, diagnostic.filePath);
|
|
39475
|
+
let content = contentByRelative.get(diagnostic.filePath);
|
|
39476
|
+
if (content === undefined) {
|
|
39477
|
+
content = await (0,promises_.readFile)(absolutePath, "utf8");
|
|
39478
|
+
contentByRelative.set(diagnostic.filePath, content);
|
|
39479
|
+
}
|
|
39480
|
+
if (diagnostic.range === undefined) {
|
|
39481
|
+
mapped.push({
|
|
39482
|
+
ruleId: diagnostic.ruleId,
|
|
39483
|
+
message: diagnostic.message,
|
|
39484
|
+
filePath: absolutePath,
|
|
39485
|
+
line: 1,
|
|
39486
|
+
column: 1
|
|
39487
|
+
});
|
|
39488
|
+
continue;
|
|
39489
|
+
}
|
|
39490
|
+
const start = offsetToSourcePosition(content, diagnostic.range.start);
|
|
39491
|
+
const end = offsetToSourcePosition(content, diagnostic.range.end);
|
|
39492
|
+
mapped.push({
|
|
39493
|
+
ruleId: diagnostic.ruleId,
|
|
39494
|
+
message: diagnostic.message,
|
|
39495
|
+
filePath: absolutePath,
|
|
39496
|
+
line: start.line,
|
|
39497
|
+
column: start.column,
|
|
39498
|
+
endLine: end.line,
|
|
39499
|
+
endColumn: end.column
|
|
39500
|
+
});
|
|
39501
|
+
}
|
|
39502
|
+
return mapped;
|
|
39503
|
+
}
|
|
39504
|
+
function collectResolvedImports(repoRoot, edges) {
|
|
39505
|
+
const resolved = [];
|
|
39506
|
+
const seen = new Set();
|
|
39507
|
+
for (const edge of edges){
|
|
39508
|
+
if (edge.status !== "resolved" || edge.target === undefined) {
|
|
39509
|
+
continue;
|
|
39510
|
+
}
|
|
39511
|
+
const absolute = toAbsolutePath(repoRoot, edge.target);
|
|
39512
|
+
if (seen.has(absolute)) {
|
|
39513
|
+
continue;
|
|
39514
|
+
}
|
|
39515
|
+
seen.add(absolute);
|
|
39516
|
+
resolved.push(absolute);
|
|
39517
|
+
}
|
|
39518
|
+
return resolved;
|
|
39519
|
+
}
|
|
39520
|
+
/**
|
|
39521
|
+
* Creates the default Claude instruction import expander used by composition roots.
|
|
39522
|
+
*/ function createClaudeInstructionImportExpander() {
|
|
39523
|
+
return {
|
|
39524
|
+
async expandClaudeEntrypoint (input) {
|
|
39525
|
+
const rootRelativePath = toRepoRelativePosix(input.repoRoot, input.absoluteFilePath);
|
|
39526
|
+
const document = await buildEffectiveDocument({
|
|
39527
|
+
repoRoot: input.repoRoot,
|
|
39528
|
+
rootRelativePath
|
|
39529
|
+
});
|
|
39530
|
+
const expansionDiagnostics = await mapExpansionDiagnostics(input.repoRoot, document.expansionDiagnostics);
|
|
39531
|
+
return {
|
|
39532
|
+
content: document.content,
|
|
39533
|
+
effectiveRoot: input.absoluteFilePath,
|
|
39534
|
+
resolvedImports: collectResolvedImports(input.repoRoot, document.edges),
|
|
39535
|
+
expansionDiagnostics
|
|
39536
|
+
};
|
|
39537
|
+
}
|
|
39538
|
+
};
|
|
39539
|
+
}
|
|
39540
|
+
|
|
38935
39541
|
;// CONCATENATED MODULE: ../core/src/gateways/instruction-file-discovery-gateway.ts
|
|
38936
39542
|
/**
|
|
38937
39543
|
* Gateway for discovering instruction files across multiple formats.
|
|
@@ -57915,10 +58521,12 @@ const HEADING_PATTERN_DESCRIPTIONS = new Map(Object.entries(HEADING_PATTERN_DESC
|
|
|
57915
58521
|
discoveryGateway;
|
|
57916
58522
|
astGateway;
|
|
57917
58523
|
commandsGateway;
|
|
57918
|
-
|
|
58524
|
+
claudeImportExpander;
|
|
58525
|
+
constructor(discoveryGateway, astGateway, commandsGateway, claudeImportExpander){
|
|
57919
58526
|
this.discoveryGateway = discoveryGateway;
|
|
57920
58527
|
this.astGateway = astGateway;
|
|
57921
58528
|
this.commandsGateway = commandsGateway;
|
|
58529
|
+
this.claudeImportExpander = claudeImportExpander;
|
|
57922
58530
|
}
|
|
57923
58531
|
/**
|
|
57924
58532
|
* Returns true if the given heading-pattern string contains any characters
|
|
@@ -58037,13 +58645,19 @@ const HEADING_PATTERN_DESCRIPTIONS = new Map(Object.entries(HEADING_PATTERN_DESC
|
|
|
58037
58645
|
diagnostics: []
|
|
58038
58646
|
};
|
|
58039
58647
|
}
|
|
58040
|
-
// Analyze each file
|
|
58648
|
+
// Analyze each file (Claude entrypoints use effective import-expanded content)
|
|
58041
58649
|
const fileStructures = new Map();
|
|
58042
58650
|
const parsingErrors = [];
|
|
58651
|
+
const importDiagnostics = [];
|
|
58652
|
+
const effectiveDocuments = [];
|
|
58043
58653
|
for (const file of discoveredFiles){
|
|
58044
58654
|
try {
|
|
58045
|
-
const
|
|
58046
|
-
fileStructures.set(file.filePath, structure);
|
|
58655
|
+
const resolved = await this.resolveAnalysisStructure(file, parsed.targetDir);
|
|
58656
|
+
fileStructures.set(file.filePath, resolved.structure);
|
|
58657
|
+
importDiagnostics.push(...resolved.importDiagnostics);
|
|
58658
|
+
if (resolved.provenance !== undefined) {
|
|
58659
|
+
effectiveDocuments.push(resolved.provenance);
|
|
58660
|
+
}
|
|
58047
58661
|
} catch (error) {
|
|
58048
58662
|
const errorMessage = error instanceof Error ? error.message : "Unknown parsing error";
|
|
58049
58663
|
parsingErrors.push({
|
|
@@ -58068,6 +58682,8 @@ const HEADING_PATTERN_DESCRIPTIONS = new Map(Object.entries(HEADING_PATTERN_DESC
|
|
|
58068
58682
|
target: "instruction"
|
|
58069
58683
|
});
|
|
58070
58684
|
}
|
|
58685
|
+
// Import-expansion failures (stable ruleIds, importer-token provenance)
|
|
58686
|
+
diagnostics.push(...importDiagnostics);
|
|
58071
58687
|
// Check each successfully parsed file for missing structural headings
|
|
58072
58688
|
const sortedFilePaths = Array.from(fileStructures.keys()).sort((a, b)=>a < b ? -1 : a > b ? 1 : 0);
|
|
58073
58689
|
for (const filePath of sortedFilePaths){
|
|
@@ -58112,17 +58728,76 @@ const HEADING_PATTERN_DESCRIPTIONS = new Map(Object.entries(HEADING_PATTERN_DESC
|
|
|
58112
58728
|
ruleId: "instruction/parse-error"
|
|
58113
58729
|
});
|
|
58114
58730
|
}
|
|
58731
|
+
const result = {
|
|
58732
|
+
discoveredFiles,
|
|
58733
|
+
commandScores,
|
|
58734
|
+
overallQualityScore,
|
|
58735
|
+
suggestions,
|
|
58736
|
+
parsingErrors,
|
|
58737
|
+
...effectiveDocuments.length > 0 ? {
|
|
58738
|
+
effectiveDocuments
|
|
58739
|
+
} : {}
|
|
58740
|
+
};
|
|
58115
58741
|
return {
|
|
58116
|
-
result
|
|
58117
|
-
discoveredFiles,
|
|
58118
|
-
commandScores,
|
|
58119
|
-
overallQualityScore,
|
|
58120
|
-
suggestions,
|
|
58121
|
-
parsingErrors
|
|
58122
|
-
},
|
|
58742
|
+
result,
|
|
58123
58743
|
diagnostics
|
|
58124
58744
|
};
|
|
58125
58745
|
}
|
|
58746
|
+
/**
|
|
58747
|
+
* Resolves the Markdown structure used for content-sensitive rules on one
|
|
58748
|
+
* discovered entrypoint. Claude entrypoints expand verified `@` imports when
|
|
58749
|
+
* an expander is injected; all other formats parse the physical file only.
|
|
58750
|
+
*/ async resolveAnalysisStructure(file, targetDir) {
|
|
58751
|
+
if (file.format === "claude-md" && this.claudeImportExpander !== undefined) {
|
|
58752
|
+
const effective = await this.claudeImportExpander.expandClaudeEntrypoint({
|
|
58753
|
+
repoRoot: targetDir,
|
|
58754
|
+
absoluteFilePath: file.filePath
|
|
58755
|
+
});
|
|
58756
|
+
const importDiagnostics = effective.expansionDiagnostics.map((diagnostic)=>AnalyzeInstructionQualityUseCase.toImportLintDiagnostic(diagnostic));
|
|
58757
|
+
importDiagnostics.sort(AnalyzeInstructionQualityUseCase.compareImportDiagnostics);
|
|
58758
|
+
return {
|
|
58759
|
+
structure: this.astGateway.parseContent(effective.content),
|
|
58760
|
+
importDiagnostics,
|
|
58761
|
+
provenance: {
|
|
58762
|
+
effectiveRoot: effective.effectiveRoot,
|
|
58763
|
+
resolvedImports: effective.resolvedImports
|
|
58764
|
+
}
|
|
58765
|
+
};
|
|
58766
|
+
}
|
|
58767
|
+
return {
|
|
58768
|
+
structure: await this.astGateway.parseFile(file.filePath),
|
|
58769
|
+
importDiagnostics: []
|
|
58770
|
+
};
|
|
58771
|
+
}
|
|
58772
|
+
static toImportLintDiagnostic(diagnostic) {
|
|
58773
|
+
return {
|
|
58774
|
+
filePath: diagnostic.filePath,
|
|
58775
|
+
line: diagnostic.line,
|
|
58776
|
+
column: diagnostic.column,
|
|
58777
|
+
endLine: diagnostic.endLine,
|
|
58778
|
+
endColumn: diagnostic.endColumn,
|
|
58779
|
+
severity: "warning",
|
|
58780
|
+
message: diagnostic.message,
|
|
58781
|
+
ruleId: diagnostic.ruleId,
|
|
58782
|
+
target: "instruction"
|
|
58783
|
+
};
|
|
58784
|
+
}
|
|
58785
|
+
static compareImportDiagnostics(a, b) {
|
|
58786
|
+
if (a.filePath !== b.filePath) {
|
|
58787
|
+
return a.filePath < b.filePath ? -1 : 1;
|
|
58788
|
+
}
|
|
58789
|
+
if (a.line !== b.line) {
|
|
58790
|
+
return a.line - b.line;
|
|
58791
|
+
}
|
|
58792
|
+
const aCol = a.column ?? 0;
|
|
58793
|
+
const bCol = b.column ?? 0;
|
|
58794
|
+
if (aCol !== bCol) {
|
|
58795
|
+
return aCol - bCol;
|
|
58796
|
+
}
|
|
58797
|
+
const aRule = a.ruleId ?? "";
|
|
58798
|
+
const bRule = b.ruleId ?? "";
|
|
58799
|
+
return aRule < bRule ? -1 : aRule > bRule ? 1 : 0;
|
|
58800
|
+
}
|
|
58126
58801
|
findBestScore(command, discoveredFiles, fileStructures, headingPatterns, proximityWindow, diagnostics) {
|
|
58127
58802
|
let bestAnalysis = null;
|
|
58128
58803
|
let bestComposite = -1;
|
|
@@ -58523,6 +59198,7 @@ const HEADING_PATTERN_DESCRIPTIONS = new Map(Object.entries(HEADING_PATTERN_DESC
|
|
|
58523
59198
|
|
|
58524
59199
|
|
|
58525
59200
|
|
|
59201
|
+
|
|
58526
59202
|
/**
|
|
58527
59203
|
* Analyzes the structural quality of feedback loop documentation in instruction files.
|
|
58528
59204
|
* Assesses structural context, execution clarity, and loop completeness.
|
|
@@ -58535,7 +59211,7 @@ const HEADING_PATTERN_DESCRIPTIONS = new Map(Object.entries(HEADING_PATTERN_DESC
|
|
|
58535
59211
|
const discoveryGateway = createInstructionFileDiscoveryGateway();
|
|
58536
59212
|
const astGateway = createMarkdownAstGateway();
|
|
58537
59213
|
const commandsGateway = createFeedbackLoopCommandsGateway();
|
|
58538
|
-
const useCase = new AnalyzeInstructionQualityUseCase(discoveryGateway, astGateway, commandsGateway);
|
|
59214
|
+
const useCase = new AnalyzeInstructionQualityUseCase(discoveryGateway, astGateway, commandsGateway, createClaudeInstructionImportExpander());
|
|
58539
59215
|
const output = await useCase.execute({
|
|
58540
59216
|
targetDir: dir
|
|
58541
59217
|
});
|
|
@@ -58558,10 +59234,27 @@ const HEADING_PATTERN_DESCRIPTIONS = new Map(Object.entries(HEADING_PATTERN_DESC
|
|
|
58558
59234
|
diagnostics: output.diagnostics.map((d)=>({
|
|
58559
59235
|
filePath: d.filePath,
|
|
58560
59236
|
line: d.line,
|
|
59237
|
+
...d.column !== undefined ? {
|
|
59238
|
+
column: d.column
|
|
59239
|
+
} : {},
|
|
59240
|
+
...d.endLine !== undefined ? {
|
|
59241
|
+
endLine: d.endLine
|
|
59242
|
+
} : {},
|
|
59243
|
+
...d.endColumn !== undefined ? {
|
|
59244
|
+
endColumn: d.endColumn
|
|
59245
|
+
} : {},
|
|
58561
59246
|
severity: d.severity,
|
|
58562
59247
|
message: d.message,
|
|
58563
59248
|
ruleId: d.ruleId
|
|
58564
|
-
}))
|
|
59249
|
+
})),
|
|
59250
|
+
...output.result.effectiveDocuments !== undefined ? {
|
|
59251
|
+
effectiveDocuments: output.result.effectiveDocuments.map((doc)=>({
|
|
59252
|
+
effectiveRoot: doc.effectiveRoot,
|
|
59253
|
+
resolvedImports: [
|
|
59254
|
+
...doc.resolvedImports
|
|
59255
|
+
]
|
|
59256
|
+
}))
|
|
59257
|
+
} : {}
|
|
58565
59258
|
});
|
|
58566
59259
|
} catch (error) {
|
|
58567
59260
|
return types_errorResponse(`Failed to analyze instruction quality: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
@@ -70391,4 +71084,4 @@ if (installedChunkData !== 0) { // 0 means "already installed".'
|
|
|
70391
71084
|
// module factories are used so entry inlining is disabled
|
|
70392
71085
|
// startup
|
|
70393
71086
|
// Load entry module and return exports
|
|
70394
|
-
var __webpack_exports__ = __webpack_require__(
|
|
71087
|
+
var __webpack_exports__ = __webpack_require__(7444);
|