@vibe-agent-toolkit/resources 0.1.37 → 0.1.39-rc.1
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 +35 -26
- package/dist/ajv-factory.d.ts +33 -0
- package/dist/ajv-factory.d.ts.map +1 -0
- package/dist/ajv-factory.js +51 -0
- package/dist/ajv-factory.js.map +1 -0
- package/dist/config-parser.d.ts +0 -18
- package/dist/config-parser.d.ts.map +1 -1
- package/dist/config-parser.js +5 -46
- package/dist/config-parser.js.map +1 -1
- package/dist/frontmatter-editor.d.ts +45 -0
- package/dist/frontmatter-editor.d.ts.map +1 -0
- package/dist/frontmatter-editor.js +161 -0
- package/dist/frontmatter-editor.js.map +1 -0
- package/dist/frontmatter-link-validator.d.ts +5 -5
- package/dist/frontmatter-link-validator.d.ts.map +1 -1
- package/dist/frontmatter-link-validator.js +25 -24
- package/dist/frontmatter-link-validator.js.map +1 -1
- package/dist/frontmatter-validator.d.ts +3 -2
- package/dist/frontmatter-validator.d.ts.map +1 -1
- package/dist/frontmatter-validator.js +19 -20
- package/dist/frontmatter-validator.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/json-pointer-path.d.ts +13 -0
- package/dist/json-pointer-path.d.ts.map +1 -0
- package/dist/json-pointer-path.js +30 -0
- package/dist/json-pointer-path.js.map +1 -0
- package/dist/link-parser.js +14 -16
- package/dist/link-parser.js.map +1 -1
- package/dist/link-validator.d.ts +23 -1
- package/dist/link-validator.d.ts.map +1 -1
- package/dist/link-validator.js +107 -104
- package/dist/link-validator.js.map +1 -1
- package/dist/multi-schema-validator.d.ts.map +1 -1
- package/dist/multi-schema-validator.js +6 -8
- package/dist/multi-schema-validator.js.map +1 -1
- package/dist/resource-registry.d.ts +10 -2
- package/dist/resource-registry.d.ts.map +1 -1
- package/dist/resource-registry.js +25 -32
- package/dist/resource-registry.js.map +1 -1
- package/dist/rewriter-helpers.d.ts +49 -0
- package/dist/rewriter-helpers.d.ts.map +1 -0
- package/dist/rewriter-helpers.js +142 -0
- package/dist/rewriter-helpers.js.map +1 -0
- package/dist/schemas/project-config.d.ts +219 -171
- package/dist/schemas/project-config.d.ts.map +1 -1
- package/dist/schemas/project-config.js +2 -0
- package/dist/schemas/project-config.js.map +1 -1
- package/dist/schemas/validation-result.d.ts +36 -57
- package/dist/schemas/validation-result.d.ts.map +1 -1
- package/dist/schemas/validation-result.js +5 -27
- package/dist/schemas/validation-result.js.map +1 -1
- package/dist/types/resource-parser.d.ts.map +1 -1
- package/dist/types/resource-parser.js +2 -3
- package/dist/types/resource-parser.js.map +1 -1
- package/dist/types/resources.d.ts +1 -1
- package/dist/types/resources.d.ts.map +1 -1
- package/dist/types/resources.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils.d.ts +50 -11
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +53 -13
- package/dist/utils.js.map +1 -1
- package/package.json +5 -5
- package/src/ajv-factory.ts +56 -0
- package/src/config-parser.ts +5 -51
- package/src/frontmatter-editor.ts +214 -0
- package/src/frontmatter-link-validator.ts +23 -25
- package/src/frontmatter-validator.ts +29 -22
- package/src/index.ts +21 -2
- package/src/json-pointer-path.ts +29 -0
- package/src/link-parser.ts +27 -20
- package/src/link-validator.ts +194 -119
- package/src/multi-schema-validator.ts +10 -8
- package/src/resource-registry.ts +48 -33
- package/src/rewriter-helpers.ts +166 -0
- package/src/schemas/project-config.ts +2 -0
- package/src/schemas/validation-result.ts +5 -29
- package/src/types/resource-parser.ts +2 -3
- package/src/types/resources.ts +2 -1
- package/src/types.ts +0 -1
- package/src/utils.ts +72 -14
package/dist/link-validator.js
CHANGED
|
@@ -14,9 +14,24 @@
|
|
|
14
14
|
* - Ignored files CAN link to non-ignored files (no error)
|
|
15
15
|
* - External resources (outside project) skip git-ignore checks
|
|
16
16
|
*/
|
|
17
|
+
import fs from 'node:fs/promises';
|
|
17
18
|
import path from 'node:path';
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
19
|
+
import { createRegistryIssue } from '@vibe-agent-toolkit/agent-schema';
|
|
20
|
+
import { isGitIgnored, verifyCaseSensitiveFilename, } from '@vibe-agent-toolkit/utils';
|
|
21
|
+
import { isWithinProject, issueLocation, resolveLocalHref } from './utils.js';
|
|
22
|
+
/**
|
|
23
|
+
* Build the common `createRegistryIssue` extras for a link issue: relative
|
|
24
|
+
* location, the problematic href, the line (only when defined — required for
|
|
25
|
+
* exactOptionalPropertyTypes), and an optional suggestion.
|
|
26
|
+
*/
|
|
27
|
+
function linkExtras(link, sourceFilePath, projectRoot, suggestion) {
|
|
28
|
+
return {
|
|
29
|
+
location: issueLocation(sourceFilePath, projectRoot),
|
|
30
|
+
link: link.href,
|
|
31
|
+
...(link.line !== undefined && { line: link.line }),
|
|
32
|
+
...(suggestion !== undefined && { suggestion }),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
20
35
|
/**
|
|
21
36
|
* Validate a single link in a markdown resource.
|
|
22
37
|
*
|
|
@@ -42,7 +57,7 @@ export async function validateLink(link, sourceFilePath, headingsByFile, options
|
|
|
42
57
|
case 'local_file':
|
|
43
58
|
return await validateLocalFileLink(link, sourceFilePath, headingsByFile, options);
|
|
44
59
|
case 'anchor':
|
|
45
|
-
return await validateAnchorLink(link, sourceFilePath, headingsByFile);
|
|
60
|
+
return await validateAnchorLink(link, sourceFilePath, headingsByFile, options?.projectRoot);
|
|
46
61
|
case 'external':
|
|
47
62
|
// External URLs are not validated - don't report them
|
|
48
63
|
return null;
|
|
@@ -50,13 +65,7 @@ export async function validateLink(link, sourceFilePath, headingsByFile, options
|
|
|
50
65
|
// Email links are valid by default
|
|
51
66
|
return null;
|
|
52
67
|
case 'unknown':
|
|
53
|
-
return
|
|
54
|
-
resourcePath: sourceFilePath,
|
|
55
|
-
line: link.line,
|
|
56
|
-
type: 'unknown_link',
|
|
57
|
-
link: link.href,
|
|
58
|
-
message: 'Unknown link type',
|
|
59
|
-
};
|
|
68
|
+
return createRegistryIssue('LINK_UNKNOWN', 'Unknown link type', linkExtras(link, sourceFilePath, options?.projectRoot));
|
|
60
69
|
default: {
|
|
61
70
|
// TypeScript exhaustiveness check
|
|
62
71
|
const _exhaustive = link.type;
|
|
@@ -64,78 +73,83 @@ export async function validateLink(link, sourceFilePath, headingsByFile, options
|
|
|
64
73
|
}
|
|
65
74
|
}
|
|
66
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Convert a resolution failure kind to a broken_file ValidationIssue. Returns
|
|
78
|
+
* null for `resolved` (caller continues) and `anchor_only` (defensive no-op —
|
|
79
|
+
* the parser classifies anchor-only hrefs as 'anchor', not 'local_file').
|
|
80
|
+
*/
|
|
81
|
+
export function resolutionFailureIssue(resolved, link, sourceFilePath, projectRoot) {
|
|
82
|
+
if (resolved.kind === 'absolute_no_root') {
|
|
83
|
+
return createRegistryIssue('LINK_BROKEN_FILE', `Absolute-path link "${link.href}" requires a configured projectRoot; ` +
|
|
84
|
+
`none was provided. Configure vibe-agent-toolkit.config.yaml or run ` +
|
|
85
|
+
`from within a git repository.`, linkExtras(link, sourceFilePath, projectRoot, 'Rewrite as a source-relative link, or run from a directory with a config or git ancestor.'));
|
|
86
|
+
}
|
|
87
|
+
if (resolved.kind === 'absolute_escapes_root') {
|
|
88
|
+
return createRegistryIssue('LINK_BROKEN_FILE', `Absolute-path link "${link.href}" escapes the project root via path traversal.`, linkExtras(link, sourceFilePath, projectRoot, ''));
|
|
89
|
+
}
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Convert a non-existent file result into a broken_file ValidationIssue.
|
|
94
|
+
* Returns null when the file exists.
|
|
95
|
+
*/
|
|
96
|
+
export function fileExistenceIssue(fileResult, link, sourceFilePath, projectRoot) {
|
|
97
|
+
if (fileResult.exists)
|
|
98
|
+
return null;
|
|
99
|
+
if (fileResult.actualName) {
|
|
100
|
+
const expectedName = path.basename(fileResult.resolvedPath);
|
|
101
|
+
return createRegistryIssue('LINK_BROKEN_FILE', `File found but case mismatch: expected "${expectedName}" but found "${fileResult.actualName}". This will fail on case-sensitive filesystems (Linux). Update the link to match the actual filename.`, linkExtras(link, sourceFilePath, projectRoot, `Use "${fileResult.actualName}" instead of "${expectedName}"`));
|
|
102
|
+
}
|
|
103
|
+
return createRegistryIssue('LINK_BROKEN_FILE', `File not found: ${fileResult.resolvedPath}`, linkExtras(link, sourceFilePath, projectRoot, ''));
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Check git-ignore safety: a non-ignored source file must not link to a
|
|
107
|
+
* gitignored target. Returns a ValidationIssue when this rule is violated,
|
|
108
|
+
* null otherwise (including when checks are disabled or out of scope).
|
|
109
|
+
*/
|
|
110
|
+
export function gitIgnoreSafetyIssue(link, sourceFilePath, resolvedTarget, options) {
|
|
111
|
+
if (options?.skipGitIgnoreCheck === true ||
|
|
112
|
+
options?.projectRoot === undefined ||
|
|
113
|
+
!isWithinProject(resolvedTarget, options.projectRoot)) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
// Prefer the O(1) active-set lookup on the shared GitTracker (no spawn).
|
|
117
|
+
// isIgnoredByActiveSet falls back internally to isIgnored for paths outside
|
|
118
|
+
// the project root, so this is safe for the rare out-of-project case.
|
|
119
|
+
// When no tracker is threaded in, fall back to isGitIgnored (one-off spawn).
|
|
120
|
+
const sourceIsIgnored = options.gitTracker
|
|
121
|
+
? options.gitTracker.isIgnoredByActiveSet(sourceFilePath)
|
|
122
|
+
: isGitIgnored(sourceFilePath, options.projectRoot);
|
|
123
|
+
const targetIsIgnored = options.gitTracker
|
|
124
|
+
? options.gitTracker.isIgnoredByActiveSet(resolvedTarget)
|
|
125
|
+
: isGitIgnored(resolvedTarget, options.projectRoot);
|
|
126
|
+
if (sourceIsIgnored || !targetIsIgnored)
|
|
127
|
+
return null;
|
|
128
|
+
return createRegistryIssue('LINK_TO_GITIGNORED', `Non-ignored file links to gitignored file: ${resolvedTarget}. Gitignored files are local-only and will not exist in the repository. Remove this link or unignore the target file.`, linkExtras(link, sourceFilePath, options.projectRoot, ''));
|
|
129
|
+
}
|
|
67
130
|
/**
|
|
68
131
|
* Validate a local file link (with optional anchor).
|
|
69
132
|
*/
|
|
70
133
|
async function validateLocalFileLink(link, sourceFilePath, headingsByFile, options) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if (!fileResult.exists) {
|
|
76
|
-
// Check if it's a case mismatch
|
|
77
|
-
if (fileResult.actualName) {
|
|
78
|
-
const expectedName = path.basename(fileResult.resolvedPath);
|
|
79
|
-
return {
|
|
80
|
-
resourcePath: sourceFilePath,
|
|
81
|
-
line: link.line,
|
|
82
|
-
type: 'broken_file',
|
|
83
|
-
link: link.href,
|
|
84
|
-
message: `File found but case mismatch: expected "${expectedName}" but found "${fileResult.actualName}". This will fail on case-sensitive filesystems (Linux). Update the link to match the actual filename.`,
|
|
85
|
-
suggestion: `Use "${fileResult.actualName}" instead of "${expectedName}"`,
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
return {
|
|
89
|
-
resourcePath: sourceFilePath,
|
|
90
|
-
line: link.line,
|
|
91
|
-
type: 'broken_file',
|
|
92
|
-
link: link.href,
|
|
93
|
-
message: `File not found: ${fileResult.resolvedPath}`,
|
|
94
|
-
suggestion: '',
|
|
95
|
-
};
|
|
134
|
+
const resolved = resolveLocalHref(link.href, sourceFilePath, options?.projectRoot);
|
|
135
|
+
if (resolved.kind !== 'resolved') {
|
|
136
|
+
// anchor_only → null no-op; absolute_no_root / absolute_escapes_root → broken_file.
|
|
137
|
+
return resolutionFailureIssue(resolved, link, sourceFilePath, options?.projectRoot);
|
|
96
138
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
options?.projectRoot !== undefined &&
|
|
104
|
-
isWithinProject(fileResult.resolvedPath, options.projectRoot)) {
|
|
105
|
-
// Prefer the O(1) active-set lookup on the shared GitTracker (no spawn).
|
|
106
|
-
// isIgnoredByActiveSet falls back internally to isIgnored for paths outside
|
|
107
|
-
// the project root, so this is safe for the rare out-of-project case.
|
|
108
|
-
// When no tracker is threaded in, fall back to isGitIgnored (one-off spawn).
|
|
109
|
-
const sourceIsIgnored = options.gitTracker
|
|
110
|
-
? options.gitTracker.isIgnoredByActiveSet(sourceFilePath)
|
|
111
|
-
: isGitIgnored(sourceFilePath, options.projectRoot);
|
|
112
|
-
const targetIsIgnored = options.gitTracker
|
|
113
|
-
? options.gitTracker.isIgnoredByActiveSet(fileResult.resolvedPath)
|
|
114
|
-
: isGitIgnored(fileResult.resolvedPath, options.projectRoot);
|
|
115
|
-
// Error ONLY if: source is NOT ignored AND target IS ignored
|
|
116
|
-
if (!sourceIsIgnored && targetIsIgnored) {
|
|
117
|
-
return {
|
|
118
|
-
resourcePath: sourceFilePath,
|
|
119
|
-
line: link.line,
|
|
120
|
-
type: 'link_to_gitignored',
|
|
121
|
-
link: link.href,
|
|
122
|
-
message: `Non-ignored file links to gitignored file: ${fileResult.resolvedPath}. Gitignored files are local-only and will not exist in the repository. Remove this link or unignore the target file.`,
|
|
123
|
-
suggestion: '',
|
|
124
|
-
};
|
|
125
|
-
}
|
|
139
|
+
const fileResult = await validateResolvedFile(resolved.resolvedPath);
|
|
140
|
+
const notFound = fileExistenceIssue(fileResult, link, sourceFilePath, options?.projectRoot);
|
|
141
|
+
if (notFound)
|
|
142
|
+
return notFound;
|
|
143
|
+
if (fileResult.isDirectory) {
|
|
144
|
+
return createRegistryIssue('LINK_BROKEN_FILE', `Link target is a directory: ${fileResult.resolvedPath}`, linkExtras(link, sourceFilePath, options?.projectRoot, 'Link to a file inside the directory (e.g., README.md or index.md), or fix the link to point at the intended file.'));
|
|
126
145
|
}
|
|
127
|
-
|
|
128
|
-
if (
|
|
129
|
-
|
|
146
|
+
const gitIgnoreIssue = gitIgnoreSafetyIssue(link, sourceFilePath, fileResult.resolvedPath, options);
|
|
147
|
+
if (gitIgnoreIssue)
|
|
148
|
+
return gitIgnoreIssue;
|
|
149
|
+
if (resolved.anchor) {
|
|
150
|
+
const anchorValid = await validateAnchor(resolved.anchor, fileResult.resolvedPath, headingsByFile);
|
|
130
151
|
if (!anchorValid) {
|
|
131
|
-
return {
|
|
132
|
-
resourcePath: sourceFilePath,
|
|
133
|
-
line: link.line,
|
|
134
|
-
type: 'broken_anchor',
|
|
135
|
-
link: link.href,
|
|
136
|
-
message: `Anchor not found: #${anchor} in ${fileResult.resolvedPath}`,
|
|
137
|
-
suggestion: '',
|
|
138
|
-
};
|
|
152
|
+
return createRegistryIssue('LINK_BROKEN_ANCHOR', `Anchor not found: #${resolved.anchor} in ${fileResult.resolvedPath}`, linkExtras(link, sourceFilePath, options?.projectRoot, ''));
|
|
139
153
|
}
|
|
140
154
|
}
|
|
141
155
|
return null;
|
|
@@ -143,50 +157,39 @@ async function validateLocalFileLink(link, sourceFilePath, headingsByFile, optio
|
|
|
143
157
|
/**
|
|
144
158
|
* Validate an anchor link (within current file).
|
|
145
159
|
*/
|
|
146
|
-
async function validateAnchorLink(link, sourceFilePath, headingsByFile) {
|
|
160
|
+
async function validateAnchorLink(link, sourceFilePath, headingsByFile, projectRoot) {
|
|
147
161
|
// Extract anchor (strip leading #)
|
|
148
162
|
const anchor = link.href.startsWith('#') ? link.href.slice(1) : link.href;
|
|
149
163
|
// Validate anchor exists in current file
|
|
150
164
|
const isValid = await validateAnchor(anchor, sourceFilePath, headingsByFile);
|
|
151
165
|
if (!isValid) {
|
|
152
|
-
return {
|
|
153
|
-
resourcePath: sourceFilePath,
|
|
154
|
-
line: link.line,
|
|
155
|
-
type: 'broken_anchor',
|
|
156
|
-
link: link.href,
|
|
157
|
-
message: `Anchor not found: ${link.href}`,
|
|
158
|
-
suggestion: '',
|
|
159
|
-
};
|
|
166
|
+
return createRegistryIssue('LINK_BROKEN_ANCHOR', `Anchor not found: ${link.href}`, linkExtras(link, sourceFilePath, projectRoot, ''));
|
|
160
167
|
}
|
|
161
168
|
return null;
|
|
162
169
|
}
|
|
163
170
|
/**
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
* @param href - The href to the file (relative or absolute)
|
|
167
|
-
* @param sourceFilePath - Absolute path to the source file
|
|
168
|
-
* @returns Object with exists flag, resolved absolute path, and optional case mismatch info
|
|
171
|
+
* Verify that the resolved filesystem path exists with the correct case.
|
|
169
172
|
*
|
|
170
|
-
* @
|
|
171
|
-
*
|
|
172
|
-
* const result = await validateLocalFile('./docs/guide.md', '/project/README.md');
|
|
173
|
-
* if (result.exists) {
|
|
174
|
-
* console.log('File exists at:', result.resolvedPath);
|
|
175
|
-
* } else if (result.actualName) {
|
|
176
|
-
* console.log('Case mismatch:', result.actualName);
|
|
177
|
-
* }
|
|
178
|
-
* ```
|
|
173
|
+
* @param resolvedPath - Absolute filesystem path produced by {@link resolveLocalHref}.
|
|
174
|
+
* @returns Object with exists flag, the path, and optional case-mismatch info.
|
|
179
175
|
*/
|
|
180
|
-
async function
|
|
181
|
-
// Resolve href to filesystem path (decode percent-encoding, resolve relative to source)
|
|
182
|
-
const resolved = resolveLocalHref(href, sourceFilePath);
|
|
183
|
-
const resolvedPath = resolved?.resolvedPath ?? safePath.resolve(path.dirname(sourceFilePath), href);
|
|
184
|
-
// Check if file exists with correct case
|
|
176
|
+
async function validateResolvedFile(resolvedPath) {
|
|
185
177
|
const verification = await verifyCaseSensitiveFilename(resolvedPath);
|
|
186
|
-
|
|
178
|
+
let isDirectory = false;
|
|
179
|
+
if (verification.exists) {
|
|
180
|
+
try {
|
|
181
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- resolvedPath validated by verifyCaseSensitiveFilename
|
|
182
|
+
const stats = await fs.stat(resolvedPath);
|
|
183
|
+
isDirectory = stats.isDirectory();
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
// Stat failed after verifyCaseSensitiveFilename said exists — treat as file.
|
|
187
|
+
}
|
|
188
|
+
}
|
|
187
189
|
const result = {
|
|
188
190
|
exists: verification.exists,
|
|
189
191
|
resolvedPath,
|
|
192
|
+
isDirectory,
|
|
190
193
|
};
|
|
191
194
|
if (verification.actualName) {
|
|
192
195
|
result.actualName = verification.actualName;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link-validator.js","sourceRoot":"","sources":["../src/link-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EACL,YAAY,EAEZ,2BAA2B,
|
|
1
|
+
{"version":3,"file":"link-validator.js","sourceRoot":"","sources":["../src/link-validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"multi-schema-validator.d.ts","sourceRoot":"","sources":["../src/multi-schema-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;
|
|
1
|
+
{"version":3,"file":"multi-schema-validator.d.ts","sourceRoot":"","sources":["../src/multi-schema-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AASH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAuB5D;;;;;;;;;;;;GAYG;AACH,wBAAsB,8BAA8B,CAClD,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAChD,OAAO,EAAE,eAAe,EAAE,EAC1B,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,cAAc,EACpB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,eAAe,EAAE,CAAC,CA2C5B;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,OAAO,CAEnE;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,eAAe,EAAE,CAQhF"}
|
|
@@ -10,8 +10,10 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { promises as fs } from 'node:fs';
|
|
12
12
|
import path from 'node:path';
|
|
13
|
+
import { createRegistryIssue } from '@vibe-agent-toolkit/agent-schema';
|
|
13
14
|
import { safePath } from '@vibe-agent-toolkit/utils';
|
|
14
15
|
import { validateFrontmatter } from './frontmatter-validator.js';
|
|
16
|
+
import { issueLocation } from './utils.js';
|
|
15
17
|
/**
|
|
16
18
|
* Load a JSON Schema from a file path
|
|
17
19
|
*
|
|
@@ -49,7 +51,7 @@ export async function validateFrontmatterMultiSchema(frontmatter, schemas, resou
|
|
|
49
51
|
// Load schema
|
|
50
52
|
const schema = await loadSchema(schemaRef.schema, projectRoot);
|
|
51
53
|
// Validate frontmatter
|
|
52
|
-
const issues = validateFrontmatter(frontmatter, schema, resourcePath, mode);
|
|
54
|
+
const issues = validateFrontmatter(frontmatter, schema, resourcePath, mode, undefined, projectRoot);
|
|
53
55
|
// Update schema reference with results
|
|
54
56
|
const result = {
|
|
55
57
|
...schemaRef,
|
|
@@ -69,13 +71,9 @@ export async function validateFrontmatterMultiSchema(frontmatter, schemas, resou
|
|
|
69
71
|
...schemaRef,
|
|
70
72
|
applied: true,
|
|
71
73
|
valid: false,
|
|
72
|
-
errors: [
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
type: 'frontmatter_schema_error',
|
|
76
|
-
link: '',
|
|
77
|
-
message: `Failed to load or validate schema ${schemaRef.schema}: ${message}`,
|
|
78
|
-
}],
|
|
74
|
+
errors: [
|
|
75
|
+
createRegistryIssue('FRONTMATTER_SCHEMA_ERROR', `Failed to load or validate schema ${schemaRef.schema}: ${message}`, { location: issueLocation(resourcePath, projectRoot), line: 1 }),
|
|
76
|
+
],
|
|
79
77
|
});
|
|
80
78
|
}
|
|
81
79
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"multi-schema-validator.js","sourceRoot":"","sources":["../src/multi-schema-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAErD,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"multi-schema-validator.js","sourceRoot":"","sources":["../src/multi-schema-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAErD,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAIjE,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C;;;;;;GAMG;AACH,KAAK,UAAU,UAAU,CAAC,UAAkB,EAAE,WAAoB;IAChE,IAAI,YAAY,GAAG,UAAU,CAAC;IAE9B,6DAA6D;IAC7D,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,WAAW,EAAE,CAAC;QAChD,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IACxD,CAAC;IAED,mEAAmE;IACnE,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IACzD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAW,CAAC;AACvC,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAClD,WAAgD,EAChD,OAA0B,EAC1B,YAAoB,EACpB,IAAoB,EACpB,WAAoB;IAEpB,MAAM,OAAO,GAAsB,EAAE,CAAC;IAEtC,KAAK,MAAM,SAAS,IAAI,OAAO,EAAE,CAAC;QAChC,IAAI,CAAC;YACH,cAAc;YACd,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;YAE/D,uBAAuB;YACvB,MAAM,MAAM,GAAG,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;YAEpG,uCAAuC;YACvC,MAAM,MAAM,GAAoB;gBAC9B,GAAG,SAAS;gBACZ,OAAO,EAAE,IAAI;gBACb,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;aAC3B,CAAC;YAEF,gEAAgE;YAChE,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtB,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC;YACzB,CAAC;YAED,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,sCAAsC;YACtC,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,OAAO,CAAC,IAAI,CAAC;gBACX,GAAG,SAAS;gBACZ,OAAO,EAAE,IAAI;gBACb,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE;oBACN,mBAAmB,CACjB,0BAA0B,EAC1B,qCAAqC,SAAS,CAAC,MAAM,KAAK,OAAO,EAAE,EACnE,EAAE,QAAQ,EAAE,aAAa,CAAC,YAAY,EAAE,WAAW,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAChE;iBACF;aACF,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,OAA0B;IACxD,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;AACpD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAA0B;IAC3D,MAAM,SAAS,GAAsB,EAAE,CAAC;IACxC,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;YACf,SAAS,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* - Link resolution (setting resolvedId for local_file links)
|
|
8
8
|
* - Query capabilities (by path, ID, or glob pattern)
|
|
9
9
|
*/
|
|
10
|
+
import { type ValidationConfig } from '@vibe-agent-toolkit/agent-schema';
|
|
10
11
|
import { type GitTracker } from '@vibe-agent-toolkit/utils';
|
|
11
12
|
import type { ResourceCollectionInterface } from './resource-collection-interface.js';
|
|
12
13
|
import type { SHA256 } from './schemas/checksum.js';
|
|
@@ -53,6 +54,13 @@ export interface ValidateOptions {
|
|
|
53
54
|
checkExternalUrls?: boolean;
|
|
54
55
|
/** Disable cache for external URL checks (default: false) */
|
|
55
56
|
noCache?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Validation framework config (severity overrides + per-code allow entries).
|
|
59
|
+
* Applied INSIDE validate() via runValidationFramework — the library, not the
|
|
60
|
+
* CLI, resolves severity and drops ignored issues. Defaults to `{}` (no
|
|
61
|
+
* overrides: every issue keeps its registry default severity).
|
|
62
|
+
*/
|
|
63
|
+
validationConfig?: ValidationConfig;
|
|
56
64
|
}
|
|
57
65
|
/**
|
|
58
66
|
* Statistics about resources in the registry.
|
|
@@ -331,10 +339,10 @@ export declare class ResourceRegistry implements ResourceCollectionInterface {
|
|
|
331
339
|
*/
|
|
332
340
|
private convertValidationResultsToIssues;
|
|
333
341
|
/**
|
|
334
|
-
* Determine issue
|
|
342
|
+
* Determine the registry issue code based on the external-URL validation error.
|
|
335
343
|
* @private
|
|
336
344
|
*/
|
|
337
|
-
private
|
|
345
|
+
private determineExternalUrlIssueCode;
|
|
338
346
|
/**
|
|
339
347
|
* Resolve links between resources in the registry.
|
|
340
348
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resource-registry.d.ts","sourceRoot":"","sources":["../src/resource-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,EAA0D,KAAK,UAAU,EAAqE,MAAM,2BAA2B,CAAC;AAYvL,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACtF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,KAAK,EAAe,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACpF,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"resource-registry.d.ts","sourceRoot":"","sources":["../src/resource-registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* - Query capabilities (by path, ID, or glob pattern)
|
|
9
9
|
*/
|
|
10
10
|
import path from 'node:path';
|
|
11
|
+
import { createRegistryIssue, runValidationFramework } from '@vibe-agent-toolkit/agent-schema';
|
|
11
12
|
import { crawlDirectory, normalizedTmpdir, resolveAssetReference, safePath, toForwardSlash } from '@vibe-agent-toolkit/utils';
|
|
12
13
|
import { calculateChecksum } from './checksum.js';
|
|
13
14
|
import { getCollectionsForFile } from './collection-matcher.js';
|
|
@@ -16,7 +17,7 @@ import { validateFrontmatterLinks, } from './frontmatter-link-validator.js';
|
|
|
16
17
|
import { validateFrontmatter } from './frontmatter-validator.js';
|
|
17
18
|
import { parseMarkdown } from './link-parser.js';
|
|
18
19
|
import { validateLink } from './link-validator.js';
|
|
19
|
-
import { matchesGlobPattern, splitHrefAnchor } from './utils.js';
|
|
20
|
+
import { issueLocation, matchesGlobPattern, splitHrefAnchor } from './utils.js';
|
|
20
21
|
/**
|
|
21
22
|
* Resource registry for managing collections of markdown resources.
|
|
22
23
|
*
|
|
@@ -284,13 +285,7 @@ export class ResourceRegistry {
|
|
|
284
285
|
const issues = [];
|
|
285
286
|
for (const resource of this.resourcesByPath.values()) {
|
|
286
287
|
if (resource.frontmatterError) {
|
|
287
|
-
issues.push({
|
|
288
|
-
resourcePath: resource.filePath,
|
|
289
|
-
line: 1,
|
|
290
|
-
type: 'frontmatter_invalid_yaml',
|
|
291
|
-
link: '',
|
|
292
|
-
message: `Invalid YAML syntax in frontmatter: ${resource.frontmatterError}`,
|
|
293
|
-
});
|
|
288
|
+
issues.push(createRegistryIssue('FRONTMATTER_INVALID_YAML', `Invalid YAML syntax in frontmatter: ${resource.frontmatterError}`, { location: issueLocation(resource.filePath, this.baseDir), line: 1 }));
|
|
294
289
|
}
|
|
295
290
|
}
|
|
296
291
|
return issues;
|
|
@@ -326,7 +321,7 @@ export class ResourceRegistry {
|
|
|
326
321
|
validateAllFrontmatter(schema, mode = 'strict') {
|
|
327
322
|
const issues = [];
|
|
328
323
|
for (const resource of this.resourcesByPath.values()) {
|
|
329
|
-
const frontmatterIssues = validateFrontmatter(resource.frontmatter, schema, resource.filePath, mode);
|
|
324
|
+
const frontmatterIssues = validateFrontmatter(resource.frontmatter, schema, resource.filePath, mode, undefined, this.baseDir);
|
|
330
325
|
issues.push(...frontmatterIssues);
|
|
331
326
|
}
|
|
332
327
|
return issues;
|
|
@@ -388,7 +383,7 @@ export class ResourceRegistry {
|
|
|
388
383
|
// Determine validation mode (default to permissive)
|
|
389
384
|
const mode = validation.mode ?? 'permissive';
|
|
390
385
|
// Validate frontmatter against JSON Schema
|
|
391
|
-
const issues = validateFrontmatter(resource.frontmatter, schema, resource.filePath, mode, schemaPath);
|
|
386
|
+
const issues = validateFrontmatter(resource.frontmatter, schema, resource.filePath, mode, schemaPath, this.baseDir);
|
|
392
387
|
// New: walk URI-family frontmatter values. Default-on; explicit `false` disables.
|
|
393
388
|
if (validation.checkFrontmatterLinks !== false && resource.frontmatter) {
|
|
394
389
|
const linkOptions = this.baseDir === undefined
|
|
@@ -410,13 +405,9 @@ export class ResourceRegistry {
|
|
|
410
405
|
catch (error) {
|
|
411
406
|
// Handle missing or invalid schema files gracefully
|
|
412
407
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
413
|
-
return [
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
type: 'frontmatter_schema_error',
|
|
417
|
-
link: '',
|
|
418
|
-
message: `Failed to load or parse frontmatter schema '${validation.frontmatterSchema}': ${errorMessage}`,
|
|
419
|
-
}];
|
|
408
|
+
return [
|
|
409
|
+
createRegistryIssue('FRONTMATTER_SCHEMA_ERROR', `Failed to load or parse frontmatter schema '${validation.frontmatterSchema}': ${errorMessage}`, { location: issueLocation(resource.filePath, this.baseDir), line: 1 }),
|
|
410
|
+
];
|
|
420
411
|
}
|
|
421
412
|
}
|
|
422
413
|
/**
|
|
@@ -476,8 +467,11 @@ export class ResourceRegistry {
|
|
|
476
467
|
const externalUrlIssues = await this.validateExternalUrls(options.noCache ?? false);
|
|
477
468
|
issues.push(...externalUrlIssues);
|
|
478
469
|
}
|
|
479
|
-
//
|
|
480
|
-
|
|
470
|
+
// Resolve severity + apply allow-filter INSIDE the library (not the CLI).
|
|
471
|
+
// `emitted` = post-allow-filter, severity-resolved, with `ignore`d dropped.
|
|
472
|
+
const framework = runValidationFramework(issues, options?.validationConfig ?? {});
|
|
473
|
+
const emitted = framework.emitted;
|
|
474
|
+
const errorCount = emitted.length;
|
|
481
475
|
// Count links by type
|
|
482
476
|
const linksByType = {};
|
|
483
477
|
for (const resource of this.resourcesByPath.values()) {
|
|
@@ -490,9 +484,10 @@ export class ResourceRegistry {
|
|
|
490
484
|
totalResources: this.resourcesByPath.size,
|
|
491
485
|
totalLinks: [...this.resourcesByPath.values()].reduce((sum, r) => sum + r.links.length, 0),
|
|
492
486
|
linksByType,
|
|
493
|
-
issues,
|
|
487
|
+
issues: emitted,
|
|
494
488
|
errorCount,
|
|
495
489
|
passed: errorCount === 0,
|
|
490
|
+
hasErrors: framework.hasErrors,
|
|
496
491
|
durationMs,
|
|
497
492
|
timestamp: new Date(),
|
|
498
493
|
};
|
|
@@ -577,33 +572,31 @@ export class ResourceRegistry {
|
|
|
577
572
|
if (!locations) {
|
|
578
573
|
continue;
|
|
579
574
|
}
|
|
580
|
-
const
|
|
575
|
+
const issueCode = this.determineExternalUrlIssueCode(result.statusCode, result.error);
|
|
581
576
|
const errorMessage = result.error ?? `HTTP ${result.statusCode}`;
|
|
582
577
|
for (const location of locations) {
|
|
583
|
-
issues.push({
|
|
584
|
-
|
|
585
|
-
line: location.line,
|
|
586
|
-
type: issueType,
|
|
578
|
+
issues.push(createRegistryIssue(issueCode, `External URL failed: ${errorMessage}`, {
|
|
579
|
+
location: issueLocation(location.resourcePath, this.baseDir),
|
|
587
580
|
link: result.url,
|
|
588
|
-
|
|
589
|
-
});
|
|
581
|
+
...(location.line !== undefined && { line: location.line }),
|
|
582
|
+
}));
|
|
590
583
|
}
|
|
591
584
|
}
|
|
592
585
|
return issues;
|
|
593
586
|
}
|
|
594
587
|
/**
|
|
595
|
-
* Determine issue
|
|
588
|
+
* Determine the registry issue code based on the external-URL validation error.
|
|
596
589
|
* @private
|
|
597
590
|
*/
|
|
598
|
-
|
|
591
|
+
determineExternalUrlIssueCode(statusCode, error) {
|
|
599
592
|
if (statusCode === 0) {
|
|
600
593
|
const errorLower = error?.toString().toLowerCase();
|
|
601
594
|
if (errorLower?.includes('timeout')) {
|
|
602
|
-
return '
|
|
595
|
+
return 'EXTERNAL_URL_TIMEOUT';
|
|
603
596
|
}
|
|
604
|
-
return '
|
|
597
|
+
return 'EXTERNAL_URL_ERROR';
|
|
605
598
|
}
|
|
606
|
-
return '
|
|
599
|
+
return 'EXTERNAL_URL_DEAD';
|
|
607
600
|
}
|
|
608
601
|
/**
|
|
609
602
|
* Resolve links between resources in the registry.
|