@millstone/synapse-cli 0.1.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 +135 -0
- package/bin/synapse.js +3 -0
- package/dist/commands/eject.d.ts +19 -0
- package/dist/commands/eject.d.ts.map +1 -0
- package/dist/commands/eject.js +146 -0
- package/dist/commands/eject.js.map +1 -0
- package/dist/commands/fetch-reference.d.ts +19 -0
- package/dist/commands/fetch-reference.d.ts.map +1 -0
- package/dist/commands/fetch-reference.js +93 -0
- package/dist/commands/fetch-reference.js.map +1 -0
- package/dist/commands/format.d.ts +26 -0
- package/dist/commands/format.d.ts.map +1 -0
- package/dist/commands/format.js +126 -0
- package/dist/commands/format.js.map +1 -0
- package/dist/commands/generate-pdf.d.ts +19 -0
- package/dist/commands/generate-pdf.d.ts.map +1 -0
- package/dist/commands/generate-pdf.js +140 -0
- package/dist/commands/generate-pdf.js.map +1 -0
- package/dist/commands/index.d.ts +17 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +26 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/init.d.ts +58 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +234 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/migrate.d.ts +29 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +297 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/scaffold.d.ts +24 -0
- package/dist/commands/scaffold.d.ts.map +1 -0
- package/dist/commands/scaffold.js +244 -0
- package/dist/commands/scaffold.js.map +1 -0
- package/dist/commands/update.d.ts +25 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +253 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/validate.d.ts +37 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +526 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +277 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/bodyRules.d.ts +70 -0
- package/dist/lib/bodyRules.d.ts.map +1 -0
- package/dist/lib/bodyRules.js +711 -0
- package/dist/lib/bodyRules.js.map +1 -0
- package/dist/lib/config.d.ts +49 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +91 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/git.d.ts +99 -0
- package/dist/lib/git.d.ts.map +1 -0
- package/dist/lib/git.js +266 -0
- package/dist/lib/git.js.map +1 -0
- package/dist/lib/graph.d.ts +6 -0
- package/dist/lib/graph.d.ts.map +1 -0
- package/dist/lib/graph.js +6 -0
- package/dist/lib/graph.js.map +1 -0
- package/dist/lib/homepage.d.ts +10 -0
- package/dist/lib/homepage.d.ts.map +1 -0
- package/dist/lib/homepage.js +172 -0
- package/dist/lib/homepage.js.map +1 -0
- package/dist/lib/markdown.d.ts +107 -0
- package/dist/lib/markdown.d.ts.map +1 -0
- package/dist/lib/markdown.js +318 -0
- package/dist/lib/markdown.js.map +1 -0
- package/dist/lib/mode-detection.d.ts +10 -0
- package/dist/lib/mode-detection.d.ts.map +1 -0
- package/dist/lib/mode-detection.js +29 -0
- package/dist/lib/mode-detection.js.map +1 -0
- package/dist/lib/naming.d.ts +47 -0
- package/dist/lib/naming.d.ts.map +1 -0
- package/dist/lib/naming.js +403 -0
- package/dist/lib/naming.js.map +1 -0
- package/dist/lib/schemas.d.ts +38 -0
- package/dist/lib/schemas.d.ts.map +1 -0
- package/dist/lib/schemas.js +248 -0
- package/dist/lib/schemas.js.map +1 -0
- package/dist/lib/templateLint.d.ts +21 -0
- package/dist/lib/templateLint.d.ts.map +1 -0
- package/dist/lib/templateLint.js +243 -0
- package/dist/lib/templateLint.js.map +1 -0
- package/dist/lib/templates.d.ts +53 -0
- package/dist/lib/templates.d.ts.map +1 -0
- package/dist/lib/templates.js +128 -0
- package/dist/lib/templates.js.map +1 -0
- package/dist/lib/tracking.d.ts +52 -0
- package/dist/lib/tracking.d.ts.map +1 -0
- package/dist/lib/tracking.js +135 -0
- package/dist/lib/tracking.js.map +1 -0
- package/dist/lib/types.generated.d.ts +54 -0
- package/dist/lib/types.generated.d.ts.map +1 -0
- package/dist/lib/types.generated.js +144 -0
- package/dist/lib/types.generated.js.map +1 -0
- package/dist/lib/validate-plugins.d.ts +22 -0
- package/dist/lib/validate-plugins.d.ts.map +1 -0
- package/dist/lib/validate-plugins.js +851 -0
- package/dist/lib/validate-plugins.js.map +1 -0
- package/package.json +85 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mode-detection.js","sourceRoot":"","sources":["../../src/lib/mode-detection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAIvC;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAY;IAC5C,MAAM,OAAO,GAAG,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAErC,oDAAoD;IACpD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;IAC7D,IAAI,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAChC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,2CAA2C;IAC3C,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC;QAClE,OAAO,CAAC,OAAO,CAAC,+BAA+B,CAAC,CAAC;QACjD,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACP,wBAAwB;IAC1B,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { DocType } from "./types.generated.js";
|
|
2
|
+
/**
|
|
3
|
+
* Validation issue structure for consistent error reporting
|
|
4
|
+
*/
|
|
5
|
+
export interface ValidationIssue {
|
|
6
|
+
notePath: string;
|
|
7
|
+
type: "error" | "warning";
|
|
8
|
+
code: string;
|
|
9
|
+
message: string;
|
|
10
|
+
field?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Get the expected folder path for a document type
|
|
14
|
+
* Now delegates to config.ts which handles config-based overrides
|
|
15
|
+
* @param type - The document type
|
|
16
|
+
* @param cwd - Optional working directory for config lookup
|
|
17
|
+
* @returns The expected folder path relative to content directory
|
|
18
|
+
*/
|
|
19
|
+
export declare function expectedFolder(type: DocType, cwd?: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* Validate that a file is in the correct folder for its type
|
|
22
|
+
* @param notePath - The path to the note file
|
|
23
|
+
* @param type - The document type
|
|
24
|
+
* @returns Array of validation issues (errors for incorrect placement)
|
|
25
|
+
*/
|
|
26
|
+
export declare function validateFolderForType(notePath: string, type: DocType, cwd?: string): ValidationIssue[];
|
|
27
|
+
/**
|
|
28
|
+
* Validate the filename pattern for a document
|
|
29
|
+
* @param notePath - The path to the note file
|
|
30
|
+
* @param type - The document type
|
|
31
|
+
* @param id - The document ID from frontmatter
|
|
32
|
+
* @param title - The document title from frontmatter
|
|
33
|
+
* @param strict - Whether to use strict mode (default: true - elevates warnings to errors)
|
|
34
|
+
* @returns Array of validation issues
|
|
35
|
+
*/
|
|
36
|
+
export declare function validateFilenamePattern(notePath: string, type: DocType, id: string, title: string, strict?: boolean, // Default to strict mode
|
|
37
|
+
frontmatter?: Record<string, any>): ValidationIssue[];
|
|
38
|
+
/**
|
|
39
|
+
* Comprehensive validation of naming and placement rules
|
|
40
|
+
* @param notePath - The path to the note file
|
|
41
|
+
* @param frontmatter - The parsed frontmatter data
|
|
42
|
+
* @param strict - Whether to use strict mode (default: true)
|
|
43
|
+
* @param cwd - Optional working directory for config lookup
|
|
44
|
+
* @returns Array of validation issues
|
|
45
|
+
*/
|
|
46
|
+
export declare function validateNaming(notePath: string, frontmatter: Record<string, any>, strict?: boolean, cwd?: string): ValidationIssue[];
|
|
47
|
+
//# sourceMappingURL=naming.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"naming.d.ts","sourceRoot":"","sources":["../../src/lib/naming.ts"],"names":[],"mappings":"AACA,OAAO,EACL,OAAO,EAGR,MAAM,sBAAsB,CAAC;AAsE9B;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,OAAO,GAAG,SAAS,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAMlE;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,EACb,GAAG,CAAC,EAAE,MAAM,GACX,eAAe,EAAE,CAwBnB;AAiBD;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,EACb,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,OAAc,EAAE,yBAAyB;AACjD,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAChC,eAAe,EAAE,CA6NnB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAChC,MAAM,GAAE,OAAc,EACtB,GAAG,CAAC,EAAE,MAAM,GACX,eAAe,EAAE,CAsEnB"}
|
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
import * as path from "path";
|
|
2
|
+
import { isDocType, } from "./types.generated.js";
|
|
3
|
+
import { getExpectedFolder, getFolderName } from "./config.js";
|
|
4
|
+
/**
|
|
5
|
+
* Extract a source prefix from an upstream URL for reference documents
|
|
6
|
+
* @param upstreamUrl - The upstream URL from frontmatter
|
|
7
|
+
* @returns A source prefix string (e.g., "claude-code", "dora", "mercury")
|
|
8
|
+
*/
|
|
9
|
+
function extractSourcePrefix(upstreamUrl) {
|
|
10
|
+
try {
|
|
11
|
+
const url = new URL(upstreamUrl);
|
|
12
|
+
const hostname = url.hostname.toLowerCase();
|
|
13
|
+
// Domain-based mapping with heuristics
|
|
14
|
+
// Prioritize specific known sources first
|
|
15
|
+
const domainMappings = {
|
|
16
|
+
'docs.claude.com': 'claude-code',
|
|
17
|
+
'claude.ai': 'claude',
|
|
18
|
+
'dora.dev': 'dora',
|
|
19
|
+
'docs.mercury.com': 'mercury',
|
|
20
|
+
'api.mercury.com': 'mercury',
|
|
21
|
+
'huggingface.co': 'huggingface',
|
|
22
|
+
'readme.io': 'readme',
|
|
23
|
+
};
|
|
24
|
+
// Check exact domain matches first
|
|
25
|
+
if (domainMappings[hostname]) {
|
|
26
|
+
return domainMappings[hostname];
|
|
27
|
+
}
|
|
28
|
+
// Handle docs.X.com pattern
|
|
29
|
+
const docsMatch = hostname.match(/^docs\.([a-z0-9-]+)\.[a-z]+$/);
|
|
30
|
+
if (docsMatch) {
|
|
31
|
+
return docsMatch[1];
|
|
32
|
+
}
|
|
33
|
+
// Handle api.X.com pattern
|
|
34
|
+
const apiMatch = hostname.match(/^api\.([a-z0-9-]+)\.[a-z]+$/);
|
|
35
|
+
if (apiMatch) {
|
|
36
|
+
return apiMatch[1];
|
|
37
|
+
}
|
|
38
|
+
// For other domains, use the primary domain name (without TLD)
|
|
39
|
+
// e.g., "example.com" → "example", "my-site.org" → "my-site"
|
|
40
|
+
const parts = hostname.split('.');
|
|
41
|
+
if (parts.length >= 2) {
|
|
42
|
+
// Get the second-to-last part (domain before TLD)
|
|
43
|
+
const domainName = parts[parts.length - 2];
|
|
44
|
+
// Skip generic domains that aren't meaningful as prefixes
|
|
45
|
+
const genericDomains = ['github', 'stackoverflow', 'medium', 'dev', 'substack'];
|
|
46
|
+
if (!genericDomains.includes(domainName)) {
|
|
47
|
+
return domainName;
|
|
48
|
+
}
|
|
49
|
+
// For generic domains, try to extract from path
|
|
50
|
+
const pathSegments = url.pathname.split('/').filter(s => s.length > 0);
|
|
51
|
+
if (pathSegments.length > 0) {
|
|
52
|
+
// Use first path segment as prefix for generic domains
|
|
53
|
+
return toSlugCase(pathSegments[0]);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Fallback: use domain name without TLD
|
|
57
|
+
return hostname.split('.')[0];
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
// If URL parsing fails, return empty string (will trigger validation error)
|
|
61
|
+
return '';
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Get the expected folder path for a document type
|
|
66
|
+
* Now delegates to config.ts which handles config-based overrides
|
|
67
|
+
* @param type - The document type
|
|
68
|
+
* @param cwd - Optional working directory for config lookup
|
|
69
|
+
* @returns The expected folder path relative to content directory
|
|
70
|
+
*/
|
|
71
|
+
export function expectedFolder(type, cwd) {
|
|
72
|
+
// Check if type is valid
|
|
73
|
+
if (!isDocType(type)) {
|
|
74
|
+
throw new Error(`Unknown document type: ${type}`);
|
|
75
|
+
}
|
|
76
|
+
return getExpectedFolder(type, cwd);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Validate that a file is in the correct folder for its type
|
|
80
|
+
* @param notePath - The path to the note file
|
|
81
|
+
* @param type - The document type
|
|
82
|
+
* @returns Array of validation issues (errors for incorrect placement)
|
|
83
|
+
*/
|
|
84
|
+
export function validateFolderForType(notePath, type, cwd) {
|
|
85
|
+
const issues = [];
|
|
86
|
+
const normalizedPath = notePath.replace(/\\/g, "/");
|
|
87
|
+
// Get folder configuration (respects config overrides)
|
|
88
|
+
const expectedFolderPath = expectedFolder(type, cwd);
|
|
89
|
+
const expectedFolderName = getFolderName(type, cwd);
|
|
90
|
+
// Check if the file is in the expected folder
|
|
91
|
+
// Accept either the full path (content/10_Policies) or just the folder name (10_Policies)
|
|
92
|
+
if (!normalizedPath.includes(expectedFolderPath) &&
|
|
93
|
+
!normalizedPath.includes(expectedFolderName)) {
|
|
94
|
+
issues.push({
|
|
95
|
+
notePath,
|
|
96
|
+
type: "error",
|
|
97
|
+
code: "WRONG_FOLDER",
|
|
98
|
+
message: `Document of type '${type}' must be placed in ${expectedFolderPath}`,
|
|
99
|
+
field: "path",
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return issues;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Convert a string to slug case
|
|
106
|
+
* @param str - The string to convert
|
|
107
|
+
* @returns The slug-case version
|
|
108
|
+
*/
|
|
109
|
+
function toSlugCase(str) {
|
|
110
|
+
return str
|
|
111
|
+
.toLowerCase()
|
|
112
|
+
.trim()
|
|
113
|
+
.replace(/[^\w\s-]/g, "") // Remove special characters
|
|
114
|
+
.replace(/\s+/g, "-") // Replace spaces with dashes
|
|
115
|
+
.replace(/-+/g, "-") // Replace multiple dashes with single dash
|
|
116
|
+
.replace(/^-+|-+$/g, ""); // Remove leading/trailing dashes
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Validate the filename pattern for a document
|
|
120
|
+
* @param notePath - The path to the note file
|
|
121
|
+
* @param type - The document type
|
|
122
|
+
* @param id - The document ID from frontmatter
|
|
123
|
+
* @param title - The document title from frontmatter
|
|
124
|
+
* @param strict - Whether to use strict mode (default: true - elevates warnings to errors)
|
|
125
|
+
* @returns Array of validation issues
|
|
126
|
+
*/
|
|
127
|
+
export function validateFilenamePattern(notePath, type, id, title, strict = true, // Default to strict mode
|
|
128
|
+
frontmatter) {
|
|
129
|
+
const issues = [];
|
|
130
|
+
const filename = path.basename(notePath, ".md");
|
|
131
|
+
if (type === "meeting") {
|
|
132
|
+
// Meeting filenames must start with YYYY-MM-DD- date prefix
|
|
133
|
+
const meetingDate = frontmatter?.meeting_date;
|
|
134
|
+
if (!meetingDate) {
|
|
135
|
+
issues.push({
|
|
136
|
+
notePath,
|
|
137
|
+
type: "error",
|
|
138
|
+
code: "MISSING_MEETING_DATE",
|
|
139
|
+
message: "Meeting documents require 'meeting_date' in frontmatter for filename validation",
|
|
140
|
+
field: "meeting_date",
|
|
141
|
+
});
|
|
142
|
+
return issues;
|
|
143
|
+
}
|
|
144
|
+
// Extract date from meeting_date (handle ISO 8601 format)
|
|
145
|
+
let datePrefix;
|
|
146
|
+
try {
|
|
147
|
+
const date = new Date(meetingDate);
|
|
148
|
+
if (isNaN(date.getTime())) {
|
|
149
|
+
throw new Error("Invalid date");
|
|
150
|
+
}
|
|
151
|
+
const year = date.getFullYear();
|
|
152
|
+
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
153
|
+
const day = String(date.getDate()).padStart(2, '0');
|
|
154
|
+
datePrefix = `${year}-${month}-${day}`;
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
issues.push({
|
|
158
|
+
notePath,
|
|
159
|
+
type: "error",
|
|
160
|
+
code: "INVALID_MEETING_DATE",
|
|
161
|
+
message: `Invalid meeting_date format '${meetingDate}'. Must be a valid ISO 8601 date string.`,
|
|
162
|
+
field: "meeting_date",
|
|
163
|
+
});
|
|
164
|
+
return issues;
|
|
165
|
+
}
|
|
166
|
+
// Check if filename starts with date prefix
|
|
167
|
+
const expectedPattern = `${datePrefix}-`;
|
|
168
|
+
if (!filename.startsWith(expectedPattern)) {
|
|
169
|
+
issues.push({
|
|
170
|
+
notePath,
|
|
171
|
+
type: "error",
|
|
172
|
+
code: "MISSING_DATE_PREFIX",
|
|
173
|
+
message: `Meeting filename must start with date prefix '${datePrefix}-' (from meeting_date '${meetingDate}'). Expected pattern: 'YYYY-MM-DD-company-topic.md'`,
|
|
174
|
+
field: "filename",
|
|
175
|
+
});
|
|
176
|
+
return issues;
|
|
177
|
+
}
|
|
178
|
+
// Validate the rest of the filename is slug-case
|
|
179
|
+
const slugPart = filename.substring(datePrefix.length + 1); // +1 for the hyphen
|
|
180
|
+
const isSlugCase = /^[a-z0-9-]+$/.test(slugPart);
|
|
181
|
+
if (!isSlugCase) {
|
|
182
|
+
issues.push({
|
|
183
|
+
notePath,
|
|
184
|
+
type: "error",
|
|
185
|
+
code: "INVALID_FILENAME_FORMAT",
|
|
186
|
+
message: `Meeting filename after date prefix must be in slug-case (lowercase, hyphens only), got '${slugPart}'`,
|
|
187
|
+
field: "filename",
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
else if (type === "adr") {
|
|
192
|
+
// ADR has strict requirements
|
|
193
|
+
// 1. ID must match pattern ADR-####
|
|
194
|
+
const adrIdPattern = /^ADR-\d{4,}$/;
|
|
195
|
+
if (!adrIdPattern.test(id)) {
|
|
196
|
+
issues.push({
|
|
197
|
+
notePath,
|
|
198
|
+
type: "error",
|
|
199
|
+
code: "INVALID_ADR_ID",
|
|
200
|
+
message: `ADR id must match pattern ADR-#### (e.g., ADR-0001), got '${id}'`,
|
|
201
|
+
field: "id",
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
// 2. Filename must be ADR-####-slug.md
|
|
205
|
+
const adrFilenamePattern = /^ADR-\d{4,}-[a-z0-9-]+$/;
|
|
206
|
+
if (!adrFilenamePattern.test(filename)) {
|
|
207
|
+
issues.push({
|
|
208
|
+
notePath,
|
|
209
|
+
type: "error",
|
|
210
|
+
code: "INVALID_ADR_FILENAME",
|
|
211
|
+
message: `ADR filename must match pattern ADR-####-slug.md (e.g., ADR-0001-api-design.md), got '${filename}.md'`,
|
|
212
|
+
field: "filename",
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
// Check that the ADR number in filename matches the ID
|
|
217
|
+
const filenameAdrNumber = filename.match(/^ADR-(\d{4,})/)?.[1];
|
|
218
|
+
const idAdrNumber = id.match(/^ADR-(\d{4,})/)?.[1];
|
|
219
|
+
if (filenameAdrNumber &&
|
|
220
|
+
idAdrNumber &&
|
|
221
|
+
filenameAdrNumber !== idAdrNumber) {
|
|
222
|
+
issues.push({
|
|
223
|
+
notePath,
|
|
224
|
+
type: "error",
|
|
225
|
+
code: "ADR_ID_MISMATCH",
|
|
226
|
+
message: `ADR number in filename (${filenameAdrNumber}) does not match id (${idAdrNumber})`,
|
|
227
|
+
field: "filename",
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
else if (type === "reference") {
|
|
233
|
+
// Reference type: enforce source prefix from upstream_url
|
|
234
|
+
const isSlugCase = /^[a-z0-9-]+$/.test(filename);
|
|
235
|
+
if (!isSlugCase) {
|
|
236
|
+
issues.push({
|
|
237
|
+
notePath,
|
|
238
|
+
type: "error",
|
|
239
|
+
code: "INVALID_FILENAME_FORMAT",
|
|
240
|
+
message: `Filename must be in slug-case (lowercase, hyphens only), got '${filename}'`,
|
|
241
|
+
field: "filename",
|
|
242
|
+
});
|
|
243
|
+
return issues; // Can't continue with invalid format
|
|
244
|
+
}
|
|
245
|
+
// Check for upstream_url in frontmatter
|
|
246
|
+
const upstreamUrl = frontmatter?.upstream_url;
|
|
247
|
+
const manualPrefix = frontmatter?.source_prefix;
|
|
248
|
+
if (!upstreamUrl) {
|
|
249
|
+
issues.push({
|
|
250
|
+
notePath,
|
|
251
|
+
type: "error",
|
|
252
|
+
code: "MISSING_UPSTREAM_URL",
|
|
253
|
+
message: "Reference documents require 'upstream_url' in frontmatter for source prefix validation",
|
|
254
|
+
field: "upstream_url",
|
|
255
|
+
});
|
|
256
|
+
return issues; // Can't validate prefix without upstream_url
|
|
257
|
+
}
|
|
258
|
+
// Extract or use manual source prefix
|
|
259
|
+
const sourcePrefix = manualPrefix || extractSourcePrefix(upstreamUrl);
|
|
260
|
+
if (!sourcePrefix) {
|
|
261
|
+
issues.push({
|
|
262
|
+
notePath,
|
|
263
|
+
type: "error",
|
|
264
|
+
code: "CANNOT_EXTRACT_SOURCE_PREFIX",
|
|
265
|
+
message: `Cannot extract source prefix from upstream_url '${upstreamUrl}'. Add 'source_prefix' field to frontmatter to manually specify the prefix.`,
|
|
266
|
+
field: "upstream_url",
|
|
267
|
+
});
|
|
268
|
+
return issues;
|
|
269
|
+
}
|
|
270
|
+
// Validate filename starts with source prefix
|
|
271
|
+
const expectedPattern = `${sourcePrefix}-`;
|
|
272
|
+
if (!filename.startsWith(expectedPattern)) {
|
|
273
|
+
issues.push({
|
|
274
|
+
notePath,
|
|
275
|
+
type: "error",
|
|
276
|
+
code: "MISSING_SOURCE_PREFIX",
|
|
277
|
+
message: `Reference filename must start with source prefix '${sourcePrefix}-' (derived from upstream_url '${upstreamUrl}'). Expected pattern: '${sourcePrefix}-{slug}.md'`,
|
|
278
|
+
field: "filename",
|
|
279
|
+
});
|
|
280
|
+
return issues;
|
|
281
|
+
}
|
|
282
|
+
// Extract the slug part (after prefix)
|
|
283
|
+
const slugPart = filename.substring(sourcePrefix.length + 1); // +1 for the hyphen
|
|
284
|
+
// Generate expected slug from title, removing the source prefix if it appears in the title
|
|
285
|
+
// e.g., "Claude Code Plugins" -> "plugins" (not "claude-code-plugins")
|
|
286
|
+
// e.g., "DORA 2025 Analysis" -> "2025-analysis" (not "dora-2025-analysis")
|
|
287
|
+
let titleForSlug = title;
|
|
288
|
+
const titleSlug = toSlugCase(title);
|
|
289
|
+
// If the title slug starts with the source prefix, remove it
|
|
290
|
+
if (titleSlug.startsWith(sourcePrefix + '-')) {
|
|
291
|
+
titleForSlug = titleSlug.substring(sourcePrefix.length + 1);
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
titleForSlug = titleSlug;
|
|
295
|
+
}
|
|
296
|
+
// Validate the slug part matches the cleaned title slug
|
|
297
|
+
if (slugPart !== titleForSlug) {
|
|
298
|
+
const severity = strict ? "error" : "warning";
|
|
299
|
+
issues.push({
|
|
300
|
+
notePath,
|
|
301
|
+
type: severity,
|
|
302
|
+
code: "FILENAME_TITLE_MISMATCH",
|
|
303
|
+
message: `Filename slug '${slugPart}' does not match expected slug from title '${title}' (expected: '${sourcePrefix}-${titleForSlug}.md')`,
|
|
304
|
+
field: "filename",
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
// Other document types: slug-case filename validation
|
|
310
|
+
const expectedSlug = toSlugCase(title);
|
|
311
|
+
const isSlugCase = /^[a-z0-9-]+$/.test(filename);
|
|
312
|
+
if (!isSlugCase) {
|
|
313
|
+
issues.push({
|
|
314
|
+
notePath,
|
|
315
|
+
type: "error",
|
|
316
|
+
code: "INVALID_FILENAME_FORMAT",
|
|
317
|
+
message: `Filename must be in slug-case (lowercase, hyphens only), got '${filename}'`,
|
|
318
|
+
field: "filename",
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
else if (filename !== expectedSlug) {
|
|
322
|
+
// Check if filename matches the title slug
|
|
323
|
+
const severity = strict ? "error" : "warning";
|
|
324
|
+
issues.push({
|
|
325
|
+
notePath,
|
|
326
|
+
type: severity,
|
|
327
|
+
code: "FILENAME_TITLE_MISMATCH",
|
|
328
|
+
message: `Filename '${filename}' does not match expected slug from title '${title}' (expected: '${expectedSlug}')`,
|
|
329
|
+
field: "filename",
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
return issues;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Comprehensive validation of naming and placement rules
|
|
337
|
+
* @param notePath - The path to the note file
|
|
338
|
+
* @param frontmatter - The parsed frontmatter data
|
|
339
|
+
* @param strict - Whether to use strict mode (default: true)
|
|
340
|
+
* @param cwd - Optional working directory for config lookup
|
|
341
|
+
* @returns Array of validation issues
|
|
342
|
+
*/
|
|
343
|
+
export function validateNaming(notePath, frontmatter, strict = true, cwd) {
|
|
344
|
+
const issues = [];
|
|
345
|
+
// Skip naming validation for example files
|
|
346
|
+
if (notePath.includes("00_Guides/Examples/") ||
|
|
347
|
+
frontmatter.example === true) {
|
|
348
|
+
return issues;
|
|
349
|
+
}
|
|
350
|
+
// Extract required fields
|
|
351
|
+
const type = frontmatter.type;
|
|
352
|
+
const id = frontmatter.id;
|
|
353
|
+
const title = frontmatter.title;
|
|
354
|
+
// Validate type is present and valid
|
|
355
|
+
if (!type) {
|
|
356
|
+
issues.push({
|
|
357
|
+
notePath,
|
|
358
|
+
type: "error",
|
|
359
|
+
code: "MISSING_TYPE",
|
|
360
|
+
message: "Document type is missing from frontmatter",
|
|
361
|
+
field: "type",
|
|
362
|
+
});
|
|
363
|
+
return issues; // Can't continue without type
|
|
364
|
+
}
|
|
365
|
+
if (!isDocType(type)) {
|
|
366
|
+
issues.push({
|
|
367
|
+
notePath,
|
|
368
|
+
type: "error",
|
|
369
|
+
code: "INVALID_TYPE",
|
|
370
|
+
message: `Invalid document type: '${type}'`,
|
|
371
|
+
field: "type",
|
|
372
|
+
});
|
|
373
|
+
return issues; // Can't continue with invalid type
|
|
374
|
+
}
|
|
375
|
+
// Validate required fields for naming checks
|
|
376
|
+
if (!id) {
|
|
377
|
+
issues.push({
|
|
378
|
+
notePath,
|
|
379
|
+
type: "error",
|
|
380
|
+
code: "MISSING_ID",
|
|
381
|
+
message: "Document id is missing from frontmatter",
|
|
382
|
+
field: "id",
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
if (!title) {
|
|
386
|
+
issues.push({
|
|
387
|
+
notePath,
|
|
388
|
+
type: "error",
|
|
389
|
+
code: "MISSING_TITLE",
|
|
390
|
+
message: "Document title is missing from frontmatter",
|
|
391
|
+
field: "title",
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
// If we have all required fields, perform naming validation
|
|
395
|
+
if (type && id && title) {
|
|
396
|
+
// Validate folder placement
|
|
397
|
+
issues.push(...validateFolderForType(notePath, type, cwd));
|
|
398
|
+
// Validate filename pattern (pass frontmatter for reference type)
|
|
399
|
+
issues.push(...validateFilenamePattern(notePath, type, id, title, strict, frontmatter));
|
|
400
|
+
}
|
|
401
|
+
return issues;
|
|
402
|
+
}
|
|
403
|
+
//# sourceMappingURL=naming.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"naming.js","sourceRoot":"","sources":["../../src/lib/naming.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { DocType } from './types.generated.js';
|
|
2
|
+
export type { DocType } from './types.generated.js';
|
|
3
|
+
export { isDocType, DOC_TYPES } from './types.generated.js';
|
|
4
|
+
export type JSONSchema = any;
|
|
5
|
+
/**
|
|
6
|
+
* Load a schema for a specific document type
|
|
7
|
+
* Resolves $ref references to base.schema.json automatically
|
|
8
|
+
*/
|
|
9
|
+
export declare function loadSchema(type: DocType, dir?: string): Promise<JSONSchema>;
|
|
10
|
+
/**
|
|
11
|
+
* List all available schema types in the schema directory
|
|
12
|
+
*/
|
|
13
|
+
export declare function listSchemas(dir?: string): Promise<string[]>;
|
|
14
|
+
/**
|
|
15
|
+
* Validate frontmatter data against a JSON schema
|
|
16
|
+
*/
|
|
17
|
+
export declare function validateFrontmatter(data: any, schema: JSONSchema): {
|
|
18
|
+
valid: boolean;
|
|
19
|
+
errors?: Array<{
|
|
20
|
+
path: string;
|
|
21
|
+
message: string;
|
|
22
|
+
}>;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Validate that all expected document types have schemas
|
|
26
|
+
* Returns an object with validation results
|
|
27
|
+
*/
|
|
28
|
+
export declare function validateSchemasCoverage(dir?: string): Promise<{
|
|
29
|
+
success: boolean;
|
|
30
|
+
coverage: {
|
|
31
|
+
expected: DocType[];
|
|
32
|
+
found: string[];
|
|
33
|
+
missing: string[];
|
|
34
|
+
extra: string[];
|
|
35
|
+
};
|
|
36
|
+
errors: string[];
|
|
37
|
+
}>;
|
|
38
|
+
//# sourceMappingURL=schemas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/lib/schemas.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,EAAwB,MAAM,sBAAsB,CAAC;AAGrE,YAAY,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAG5D,MAAM,MAAM,UAAU,GAAG,GAAG,CAAC;AAqD7B;;;GAGG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CA0DjF;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAoBjE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,GAAG,EACT,MAAM,EAAE,UAAU,GACjB;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CA0DvE;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACnE,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE;QACR,QAAQ,EAAE,OAAO,EAAE,CAAC;QACpB,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,KAAK,EAAE,MAAM,EAAE,CAAC;KACjB,CAAC;IACF,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC,CA6DD"}
|