forgecraft-mcp 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 +251 -0
- package/dist/analyzers/anti-pattern.d.ts +21 -0
- package/dist/analyzers/anti-pattern.d.ts.map +1 -0
- package/dist/analyzers/anti-pattern.js +130 -0
- package/dist/analyzers/anti-pattern.js.map +1 -0
- package/dist/analyzers/completeness.d.ts +15 -0
- package/dist/analyzers/completeness.d.ts.map +1 -0
- package/dist/analyzers/completeness.js +207 -0
- package/dist/analyzers/completeness.js.map +1 -0
- package/dist/analyzers/folder-structure.d.ts +35 -0
- package/dist/analyzers/folder-structure.d.ts.map +1 -0
- package/dist/analyzers/folder-structure.js +151 -0
- package/dist/analyzers/folder-structure.js.map +1 -0
- package/dist/analyzers/package-json.d.ts +22 -0
- package/dist/analyzers/package-json.d.ts.map +1 -0
- package/dist/analyzers/package-json.js +229 -0
- package/dist/analyzers/package-json.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +59 -0
- package/dist/index.js.map +1 -0
- package/dist/registry/composer.d.ts +32 -0
- package/dist/registry/composer.d.ts.map +1 -0
- package/dist/registry/composer.js +169 -0
- package/dist/registry/composer.js.map +1 -0
- package/dist/registry/loader.d.ts +37 -0
- package/dist/registry/loader.d.ts.map +1 -0
- package/dist/registry/loader.js +278 -0
- package/dist/registry/loader.js.map +1 -0
- package/dist/registry/renderer.d.ts +53 -0
- package/dist/registry/renderer.d.ts.map +1 -0
- package/dist/registry/renderer.js +275 -0
- package/dist/registry/renderer.js.map +1 -0
- package/dist/shared/config/index.d.ts +15 -0
- package/dist/shared/config/index.d.ts.map +1 -0
- package/dist/shared/config/index.js +16 -0
- package/dist/shared/config/index.js.map +1 -0
- package/dist/shared/errors/index.d.ts +30 -0
- package/dist/shared/errors/index.d.ts.map +1 -0
- package/dist/shared/errors/index.js +44 -0
- package/dist/shared/errors/index.js.map +1 -0
- package/dist/shared/logger/index.d.ts +27 -0
- package/dist/shared/logger/index.d.ts.map +1 -0
- package/dist/shared/logger/index.js +59 -0
- package/dist/shared/logger/index.js.map +1 -0
- package/dist/shared/types.d.ts +212 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/types.js +30 -0
- package/dist/shared/types.js.map +1 -0
- package/dist/tools/add-hook.d.ts +26 -0
- package/dist/tools/add-hook.d.ts.map +1 -0
- package/dist/tools/add-hook.js +82 -0
- package/dist/tools/add-hook.js.map +1 -0
- package/dist/tools/add-module.d.ts +29 -0
- package/dist/tools/add-module.d.ts.map +1 -0
- package/dist/tools/add-module.js +244 -0
- package/dist/tools/add-module.js.map +1 -0
- package/dist/tools/audit.d.ts +26 -0
- package/dist/tools/audit.d.ts.map +1 -0
- package/dist/tools/audit.js +111 -0
- package/dist/tools/audit.js.map +1 -0
- package/dist/tools/classify.d.ts +23 -0
- package/dist/tools/classify.d.ts.map +1 -0
- package/dist/tools/classify.js +73 -0
- package/dist/tools/classify.js.map +1 -0
- package/dist/tools/configure-mcp.d.ts +49 -0
- package/dist/tools/configure-mcp.d.ts.map +1 -0
- package/dist/tools/configure-mcp.js +127 -0
- package/dist/tools/configure-mcp.js.map +1 -0
- package/dist/tools/convert.d.ts +27 -0
- package/dist/tools/convert.d.ts.map +1 -0
- package/dist/tools/convert.js +154 -0
- package/dist/tools/convert.js.map +1 -0
- package/dist/tools/generate-claude-md.d.ts +29 -0
- package/dist/tools/generate-claude-md.d.ts.map +1 -0
- package/dist/tools/generate-claude-md.js +116 -0
- package/dist/tools/generate-claude-md.js.map +1 -0
- package/dist/tools/get-nfr.d.ts +20 -0
- package/dist/tools/get-nfr.d.ts.map +1 -0
- package/dist/tools/get-nfr.js +53 -0
- package/dist/tools/get-nfr.js.map +1 -0
- package/dist/tools/list.d.ts +33 -0
- package/dist/tools/list.d.ts.map +1 -0
- package/dist/tools/list.js +155 -0
- package/dist/tools/list.js.map +1 -0
- package/dist/tools/refresh-project.d.ts +34 -0
- package/dist/tools/refresh-project.d.ts.map +1 -0
- package/dist/tools/refresh-project.js +257 -0
- package/dist/tools/refresh-project.js.map +1 -0
- package/dist/tools/review.d.ts +31 -0
- package/dist/tools/review.d.ts.map +1 -0
- package/dist/tools/review.js +62 -0
- package/dist/tools/review.js.map +1 -0
- package/dist/tools/scaffold.d.ts +32 -0
- package/dist/tools/scaffold.d.ts.map +1 -0
- package/dist/tools/scaffold.js +160 -0
- package/dist/tools/scaffold.js.map +1 -0
- package/dist/tools/setup-project.d.ts +37 -0
- package/dist/tools/setup-project.d.ts.map +1 -0
- package/dist/tools/setup-project.js +270 -0
- package/dist/tools/setup-project.js.map +1 -0
- package/package.json +69 -0
- package/templates/analytics/claude-md.yaml +37 -0
- package/templates/analytics/structure.yaml +25 -0
- package/templates/api/claude-md.yaml +85 -0
- package/templates/api/nfr.yaml +23 -0
- package/templates/api/review.yaml +103 -0
- package/templates/api/structure.yaml +34 -0
- package/templates/cli/claude-md.yaml +31 -0
- package/templates/cli/review.yaml +53 -0
- package/templates/cli/structure.yaml +16 -0
- package/templates/data-pipeline/claude-md.yaml +42 -0
- package/templates/data-pipeline/nfr.yaml +39 -0
- package/templates/data-pipeline/structure.yaml +23 -0
- package/templates/fintech/claude-md.yaml +42 -0
- package/templates/fintech/nfr.yaml +46 -0
- package/templates/game/claude-md.yaml +42 -0
- package/templates/healthcare/claude-md.yaml +42 -0
- package/templates/healthcare/nfr.yaml +47 -0
- package/templates/infra/claude-md.yaml +104 -0
- package/templates/infra/nfr.yaml +46 -0
- package/templates/infra/review.yaml +65 -0
- package/templates/infra/structure.yaml +25 -0
- package/templates/library/claude-md.yaml +36 -0
- package/templates/library/review.yaml +56 -0
- package/templates/library/structure.yaml +19 -0
- package/templates/ml/claude-md.yaml +42 -0
- package/templates/ml/nfr.yaml +39 -0
- package/templates/ml/structure.yaml +25 -0
- package/templates/mobile/claude-md.yaml +44 -0
- package/templates/mobile/nfr.yaml +49 -0
- package/templates/mobile/structure.yaml +27 -0
- package/templates/realtime/claude-md.yaml +42 -0
- package/templates/social/claude-md.yaml +43 -0
- package/templates/state-machine/claude-md.yaml +42 -0
- package/templates/universal/claude-md.yaml +477 -0
- package/templates/universal/hooks.yaml +196 -0
- package/templates/universal/nfr.yaml +197 -0
- package/templates/universal/review.yaml +164 -0
- package/templates/universal/structure.yaml +52 -0
- package/templates/web-react/claude-md.yaml +110 -0
- package/templates/web-react/hooks.yaml +44 -0
- package/templates/web-react/nfr.yaml +27 -0
- package/templates/web-react/review.yaml +94 -0
- package/templates/web-react/structure.yaml +46 -0
- package/templates/web-static/claude-md.yaml +73 -0
- package/templates/web3/claude-md.yaml +44 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template composer.
|
|
3
|
+
*
|
|
4
|
+
* Given a set of active tags, composes CLAUDE.md blocks, folder structures,
|
|
5
|
+
* hooks, and NFRs from all matching templates into unified outputs.
|
|
6
|
+
* Handles merge, deduplication, ordering, and tier-based filtering.
|
|
7
|
+
*/
|
|
8
|
+
import { createLogger } from "../shared/logger/index.js";
|
|
9
|
+
const logger = createLogger("registry/composer");
|
|
10
|
+
/**
|
|
11
|
+
* Tier inclusion hierarchy.
|
|
12
|
+
* "core" → includes only core blocks.
|
|
13
|
+
* "recommended" → includes core + recommended.
|
|
14
|
+
* "optional" → includes core + recommended + optional.
|
|
15
|
+
* Blocks without a tier field are treated as "core" (always included).
|
|
16
|
+
*/
|
|
17
|
+
const TIER_HIERARCHY = {
|
|
18
|
+
core: ["core"],
|
|
19
|
+
recommended: ["core", "recommended"],
|
|
20
|
+
optional: ["core", "recommended", "optional"],
|
|
21
|
+
};
|
|
22
|
+
/** Default tier when none is specified in config. */
|
|
23
|
+
const DEFAULT_TIER = "recommended";
|
|
24
|
+
/**
|
|
25
|
+
* Check if a block should be included based on the tier filter.
|
|
26
|
+
* Blocks without a tier are treated as "core" (always included).
|
|
27
|
+
*
|
|
28
|
+
* @param blockTier - The tier of the block (undefined = core)
|
|
29
|
+
* @param allowedTiers - The set of allowed tiers
|
|
30
|
+
* @returns true if the block should be included
|
|
31
|
+
*/
|
|
32
|
+
function isTierAllowed(blockTier, allowedTiers) {
|
|
33
|
+
const effective = blockTier ?? "core";
|
|
34
|
+
return allowedTiers.has(effective);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Check if a block ID is included/excluded by the config lists.
|
|
38
|
+
*
|
|
39
|
+
* @param blockId - The block identifier
|
|
40
|
+
* @param include - Explicit include list (if set, only these are included)
|
|
41
|
+
* @param exclude - Explicit exclude list (always excluded)
|
|
42
|
+
* @returns true if the block should be included
|
|
43
|
+
*/
|
|
44
|
+
function isBlockAllowed(blockId, include, exclude) {
|
|
45
|
+
if (exclude?.includes(blockId)) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
if (include && include.length > 0) {
|
|
49
|
+
return include.includes(blockId);
|
|
50
|
+
}
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Compose templates for a given set of active tags.
|
|
55
|
+
* UNIVERSAL is always included first regardless of whether it's in the tags list.
|
|
56
|
+
*
|
|
57
|
+
* @param activeTags - Tags to compose for
|
|
58
|
+
* @param allTemplates - Full template map from the loader
|
|
59
|
+
* @param options - Optional composition config (tier filtering, include/exclude)
|
|
60
|
+
* @returns Composed and filtered templates
|
|
61
|
+
*/
|
|
62
|
+
export function composeTemplates(activeTags, allTemplates, options) {
|
|
63
|
+
const config = options?.config;
|
|
64
|
+
const tierLevel = config?.tier ?? DEFAULT_TIER;
|
|
65
|
+
const allowedTiers = new Set(TIER_HIERARCHY[tierLevel]);
|
|
66
|
+
const includeList = config?.include;
|
|
67
|
+
const excludeList = config?.exclude;
|
|
68
|
+
// Ensure UNIVERSAL is first and present
|
|
69
|
+
const orderedTags = normalizeTagOrder(activeTags);
|
|
70
|
+
const claudeMdBlocks = [];
|
|
71
|
+
const structureEntries = [];
|
|
72
|
+
const nfrBlocks = [];
|
|
73
|
+
const hooks = [];
|
|
74
|
+
const reviewBlocks = [];
|
|
75
|
+
const seenBlockIds = new Set();
|
|
76
|
+
const seenPaths = new Set();
|
|
77
|
+
const seenHookNames = new Set();
|
|
78
|
+
const seenNfrIds = new Set();
|
|
79
|
+
const seenReviewIds = new Set();
|
|
80
|
+
for (const tag of orderedTags) {
|
|
81
|
+
const templateSet = allTemplates.get(tag);
|
|
82
|
+
if (!templateSet) {
|
|
83
|
+
logger.warn("No templates found for tag", { tag });
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
// Compose CLAUDE.md blocks (deduplicate by id, filter by tier)
|
|
87
|
+
if (templateSet.claudeMd?.blocks) {
|
|
88
|
+
for (const block of templateSet.claudeMd.blocks) {
|
|
89
|
+
if (!seenBlockIds.has(block.id) &&
|
|
90
|
+
isTierAllowed(block.tier, allowedTiers) &&
|
|
91
|
+
isBlockAllowed(block.id, includeList, excludeList)) {
|
|
92
|
+
seenBlockIds.add(block.id);
|
|
93
|
+
claudeMdBlocks.push(block);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Compose structure entries (deduplicate by path — not tier-filtered)
|
|
98
|
+
if (templateSet.structure?.entries) {
|
|
99
|
+
for (const entry of templateSet.structure.entries) {
|
|
100
|
+
if (!seenPaths.has(entry.path)) {
|
|
101
|
+
seenPaths.add(entry.path);
|
|
102
|
+
structureEntries.push(entry);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Compose NFR blocks (deduplicate by id, filter by tier)
|
|
107
|
+
if (templateSet.nfr?.blocks) {
|
|
108
|
+
for (const block of templateSet.nfr.blocks) {
|
|
109
|
+
if (!seenNfrIds.has(block.id) &&
|
|
110
|
+
isTierAllowed(block.tier, allowedTiers) &&
|
|
111
|
+
isBlockAllowed(block.id, includeList, excludeList)) {
|
|
112
|
+
seenNfrIds.add(block.id);
|
|
113
|
+
nfrBlocks.push(block);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// Compose hooks (deduplicate by name — not tier-filtered)
|
|
118
|
+
if (templateSet.hooks) {
|
|
119
|
+
for (const hook of templateSet.hooks) {
|
|
120
|
+
if (!seenHookNames.has(hook.name)) {
|
|
121
|
+
seenHookNames.add(hook.name);
|
|
122
|
+
hooks.push(hook);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// Compose review blocks (deduplicate by id, filter by tier)
|
|
127
|
+
if (templateSet.review?.blocks) {
|
|
128
|
+
for (const block of templateSet.review.blocks) {
|
|
129
|
+
if (!seenReviewIds.has(block.id) &&
|
|
130
|
+
isTierAllowed(block.tier, allowedTiers) &&
|
|
131
|
+
isBlockAllowed(block.id, includeList, excludeList)) {
|
|
132
|
+
seenReviewIds.add(block.id);
|
|
133
|
+
reviewBlocks.push(block);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
logger.info("Templates composed", {
|
|
139
|
+
tags: orderedTags,
|
|
140
|
+
tier: tierLevel,
|
|
141
|
+
claudeMdBlocks: claudeMdBlocks.length,
|
|
142
|
+
structureEntries: structureEntries.length,
|
|
143
|
+
nfrBlocks: nfrBlocks.length,
|
|
144
|
+
hooks: hooks.length,
|
|
145
|
+
reviewBlocks: reviewBlocks.length,
|
|
146
|
+
});
|
|
147
|
+
return { claudeMdBlocks, structureEntries, nfrBlocks, hooks, reviewBlocks };
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Ensure UNIVERSAL is always first in the tag list.
|
|
151
|
+
* Remove duplicates. Preserve user order for other tags.
|
|
152
|
+
*/
|
|
153
|
+
function normalizeTagOrder(tags) {
|
|
154
|
+
const seen = new Set();
|
|
155
|
+
const result = [];
|
|
156
|
+
// UNIVERSAL always first
|
|
157
|
+
if (!tags.includes("UNIVERSAL")) {
|
|
158
|
+
result.push("UNIVERSAL");
|
|
159
|
+
seen.add("UNIVERSAL");
|
|
160
|
+
}
|
|
161
|
+
for (const tag of tags) {
|
|
162
|
+
if (!seen.has(tag)) {
|
|
163
|
+
seen.add(tag);
|
|
164
|
+
result.push(tag);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return result;
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=composer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"composer.js","sourceRoot":"","sources":["../../src/registry/composer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template registry loader.
|
|
3
|
+
*
|
|
4
|
+
* Loads YAML template files from the templates/ directory (shipped with the package)
|
|
5
|
+
* and merges with any user overrides from .forgecraft.json.
|
|
6
|
+
*/
|
|
7
|
+
import type { Tag, TagTemplateSet, ForgeCraftConfig } from "../shared/types.js";
|
|
8
|
+
/**
|
|
9
|
+
* Resolve the templates directory path.
|
|
10
|
+
* Uses FORGECRAFT_TEMPLATE_DIR env var if set, otherwise the package's built-in templates.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveTemplatesDir(): string;
|
|
13
|
+
/**
|
|
14
|
+
* Load all template sets from the templates directory.
|
|
15
|
+
* Returns a map of tag → TagTemplateSet.
|
|
16
|
+
*/
|
|
17
|
+
export declare function loadAllTemplates(templatesDir?: string): Map<Tag, TagTemplateSet>;
|
|
18
|
+
/**
|
|
19
|
+
* Convert a Tag to its directory name.
|
|
20
|
+
*/
|
|
21
|
+
export declare function tagToDirName(tag: Tag): string;
|
|
22
|
+
/**
|
|
23
|
+
* Load user overrides from forgecraft.yaml or .forgecraft.json in the project directory.
|
|
24
|
+
* Prefers forgecraft.yaml over .forgecraft.json.
|
|
25
|
+
* Returns null if no config file exists.
|
|
26
|
+
*/
|
|
27
|
+
export declare function loadUserOverrides(projectDir: string): ForgeCraftConfig | null;
|
|
28
|
+
/**
|
|
29
|
+
* Load templates from multiple directories and merge them.
|
|
30
|
+
* Later directories override earlier ones (community/local override built-in).
|
|
31
|
+
*
|
|
32
|
+
* @param builtInDir - The built-in templates directory
|
|
33
|
+
* @param extraDirs - Additional template directories from config
|
|
34
|
+
* @returns Merged map of tag → TagTemplateSet
|
|
35
|
+
*/
|
|
36
|
+
export declare function loadAllTemplatesWithExtras(builtInDir?: string, extraDirs?: string[]): Map<Tag, TagTemplateSet>;
|
|
37
|
+
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/registry/loader.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,OAAO,KAAK,EACV,GAAG,EACH,cAAc,EAMd,gBAAgB,EACjB,MAAM,oBAAoB,CAAC;AAW5B;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAuB5C;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,YAAY,CAAC,EAAE,MAAM,GACpB,GAAG,CAAC,GAAG,EAAE,cAAc,CAAC,CA0B1B;AA8FD;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAE7C;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,GACjB,gBAAgB,GAAG,IAAI,CA4BzB;AAED;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACxC,UAAU,CAAC,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,EAAE,GACnB,GAAG,CAAC,GAAG,EAAE,cAAc,CAAC,CAuC1B"}
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template registry loader.
|
|
3
|
+
*
|
|
4
|
+
* Loads YAML template files from the templates/ directory (shipped with the package)
|
|
5
|
+
* and merges with any user overrides from .forgecraft.json.
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync, readdirSync, existsSync } from "node:fs";
|
|
8
|
+
import { join, resolve } from "node:path";
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
10
|
+
import yaml from "js-yaml";
|
|
11
|
+
import { createLogger } from "../shared/logger/index.js";
|
|
12
|
+
import { TemplateNotFoundError, TemplateParseError } from "../shared/errors/index.js";
|
|
13
|
+
const logger = createLogger("registry/loader");
|
|
14
|
+
/**
|
|
15
|
+
* Resolve the templates directory path.
|
|
16
|
+
* Uses FORGECRAFT_TEMPLATE_DIR env var if set, otherwise the package's built-in templates.
|
|
17
|
+
*/
|
|
18
|
+
export function resolveTemplatesDir() {
|
|
19
|
+
const envDir = process.env["FORGECRAFT_TEMPLATE_DIR"];
|
|
20
|
+
if (envDir && existsSync(envDir)) {
|
|
21
|
+
return resolve(envDir);
|
|
22
|
+
}
|
|
23
|
+
// Resolve relative to this file's location in the package
|
|
24
|
+
const thisDir = fileURLToPath(new URL(".", import.meta.url));
|
|
25
|
+
// In dist/registry/loader.js → go up 2 levels to package root, then templates/
|
|
26
|
+
const packageRoot = resolve(thisDir, "..", "..");
|
|
27
|
+
const templatesDir = join(packageRoot, "templates");
|
|
28
|
+
if (existsSync(templatesDir)) {
|
|
29
|
+
return templatesDir;
|
|
30
|
+
}
|
|
31
|
+
// Fallback: maybe we're running from src/ during development
|
|
32
|
+
const devTemplatesDir = join(packageRoot, "..", "templates");
|
|
33
|
+
if (existsSync(devTemplatesDir)) {
|
|
34
|
+
return devTemplatesDir;
|
|
35
|
+
}
|
|
36
|
+
throw new TemplateNotFoundError("templates", "Could not locate templates directory");
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Load all template sets from the templates directory.
|
|
40
|
+
* Returns a map of tag → TagTemplateSet.
|
|
41
|
+
*/
|
|
42
|
+
export function loadAllTemplates(templatesDir) {
|
|
43
|
+
const dir = templatesDir ?? resolveTemplatesDir();
|
|
44
|
+
const result = new Map();
|
|
45
|
+
const tagDirs = readdirSync(dir, { withFileTypes: true })
|
|
46
|
+
.filter((entry) => entry.isDirectory())
|
|
47
|
+
.map((entry) => entry.name);
|
|
48
|
+
for (const tagDirName of tagDirs) {
|
|
49
|
+
const tag = tagDirNameToTag(tagDirName);
|
|
50
|
+
if (!tag) {
|
|
51
|
+
logger.warn("Unknown tag directory, skipping", { dir: tagDirName });
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
const tagDir = join(dir, tagDirName);
|
|
55
|
+
const templateSet = loadTagTemplateSet(tag, tagDir);
|
|
56
|
+
result.set(tag, templateSet);
|
|
57
|
+
}
|
|
58
|
+
logger.info("Templates loaded", {
|
|
59
|
+
tagCount: result.size,
|
|
60
|
+
tags: Array.from(result.keys()),
|
|
61
|
+
});
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Load a single tag's template set from its directory.
|
|
66
|
+
*/
|
|
67
|
+
function loadTagTemplateSet(tag, tagDir) {
|
|
68
|
+
let claudeMd;
|
|
69
|
+
let nfr;
|
|
70
|
+
let structure;
|
|
71
|
+
let hooks;
|
|
72
|
+
let review;
|
|
73
|
+
// Load claude-md.yaml
|
|
74
|
+
const claudeMdPath = join(tagDir, "claude-md.yaml");
|
|
75
|
+
if (existsSync(claudeMdPath)) {
|
|
76
|
+
claudeMd = loadYamlFile(claudeMdPath);
|
|
77
|
+
}
|
|
78
|
+
// Load nfr.yaml
|
|
79
|
+
const nfrPath = join(tagDir, "nfr.yaml");
|
|
80
|
+
if (existsSync(nfrPath)) {
|
|
81
|
+
nfr = loadYamlFile(nfrPath);
|
|
82
|
+
}
|
|
83
|
+
// Load structure.yaml
|
|
84
|
+
const structurePath = join(tagDir, "structure.yaml");
|
|
85
|
+
if (existsSync(structurePath)) {
|
|
86
|
+
structure = loadYamlFile(structurePath);
|
|
87
|
+
}
|
|
88
|
+
// Load hooks.yaml
|
|
89
|
+
const hooksPath = join(tagDir, "hooks.yaml");
|
|
90
|
+
if (existsSync(hooksPath)) {
|
|
91
|
+
const hooksFile = loadYamlFile(hooksPath);
|
|
92
|
+
hooks = hooksFile.hooks;
|
|
93
|
+
}
|
|
94
|
+
// Load review.yaml
|
|
95
|
+
const reviewPath = join(tagDir, "review.yaml");
|
|
96
|
+
if (existsSync(reviewPath)) {
|
|
97
|
+
review = loadYamlFile(reviewPath);
|
|
98
|
+
}
|
|
99
|
+
return { tag, claudeMd, nfr, structure, hooks, review };
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Load and parse a single YAML template file.
|
|
103
|
+
*/
|
|
104
|
+
function loadYamlFile(filePath) {
|
|
105
|
+
try {
|
|
106
|
+
const content = readFileSync(filePath, "utf-8");
|
|
107
|
+
const parsed = yaml.load(content);
|
|
108
|
+
if (!parsed) {
|
|
109
|
+
throw new TemplateParseError(filePath, "YAML parsed to null/undefined");
|
|
110
|
+
}
|
|
111
|
+
return parsed;
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
if (error instanceof TemplateParseError) {
|
|
115
|
+
throw error;
|
|
116
|
+
}
|
|
117
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
118
|
+
throw new TemplateParseError(filePath, message);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Convert a directory name to a Tag enum value.
|
|
123
|
+
* Directory names use lowercase-kebab (e.g., "web-react"), tags use UPPER-KEBAB.
|
|
124
|
+
*/
|
|
125
|
+
function tagDirNameToTag(dirName) {
|
|
126
|
+
const mapping = {
|
|
127
|
+
universal: "UNIVERSAL",
|
|
128
|
+
"web-react": "WEB-REACT",
|
|
129
|
+
"web-static": "WEB-STATIC",
|
|
130
|
+
api: "API",
|
|
131
|
+
"data-pipeline": "DATA-PIPELINE",
|
|
132
|
+
ml: "ML",
|
|
133
|
+
healthcare: "HEALTHCARE",
|
|
134
|
+
fintech: "FINTECH",
|
|
135
|
+
web3: "WEB3",
|
|
136
|
+
realtime: "REALTIME",
|
|
137
|
+
"state-machine": "STATE-MACHINE",
|
|
138
|
+
game: "GAME",
|
|
139
|
+
social: "SOCIAL",
|
|
140
|
+
cli: "CLI",
|
|
141
|
+
library: "LIBRARY",
|
|
142
|
+
infra: "INFRA",
|
|
143
|
+
mobile: "MOBILE",
|
|
144
|
+
analytics: "ANALYTICS",
|
|
145
|
+
};
|
|
146
|
+
return mapping[dirName] ?? null;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Convert a Tag to its directory name.
|
|
150
|
+
*/
|
|
151
|
+
export function tagToDirName(tag) {
|
|
152
|
+
return tag.toLowerCase();
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Load user overrides from forgecraft.yaml or .forgecraft.json in the project directory.
|
|
156
|
+
* Prefers forgecraft.yaml over .forgecraft.json.
|
|
157
|
+
* Returns null if no config file exists.
|
|
158
|
+
*/
|
|
159
|
+
export function loadUserOverrides(projectDir) {
|
|
160
|
+
// Prefer YAML config
|
|
161
|
+
const yamlPath = join(projectDir, "forgecraft.yaml");
|
|
162
|
+
if (existsSync(yamlPath)) {
|
|
163
|
+
try {
|
|
164
|
+
const content = readFileSync(yamlPath, "utf-8");
|
|
165
|
+
return yaml.load(content);
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
169
|
+
logger.warn("Failed to parse forgecraft.yaml", { error: message });
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// Fallback to JSON config
|
|
174
|
+
const configPath = join(projectDir, ".forgecraft.json");
|
|
175
|
+
if (!existsSync(configPath)) {
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
try {
|
|
179
|
+
const content = readFileSync(configPath, "utf-8");
|
|
180
|
+
return JSON.parse(content);
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
184
|
+
logger.warn("Failed to parse .forgecraft.json", { error: message });
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Load templates from multiple directories and merge them.
|
|
190
|
+
* Later directories override earlier ones (community/local override built-in).
|
|
191
|
+
*
|
|
192
|
+
* @param builtInDir - The built-in templates directory
|
|
193
|
+
* @param extraDirs - Additional template directories from config
|
|
194
|
+
* @returns Merged map of tag → TagTemplateSet
|
|
195
|
+
*/
|
|
196
|
+
export function loadAllTemplatesWithExtras(builtInDir, extraDirs) {
|
|
197
|
+
const base = loadAllTemplates(builtInDir);
|
|
198
|
+
if (!extraDirs || extraDirs.length === 0) {
|
|
199
|
+
return base;
|
|
200
|
+
}
|
|
201
|
+
for (const dir of extraDirs) {
|
|
202
|
+
const resolvedDir = resolve(dir);
|
|
203
|
+
if (!existsSync(resolvedDir)) {
|
|
204
|
+
logger.warn("Community template directory not found, skipping", { dir: resolvedDir });
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
logger.info("Loading community templates", { dir: resolvedDir });
|
|
208
|
+
const extra = loadAllTemplates(resolvedDir);
|
|
209
|
+
// Merge: extra templates extend base templates (additive for blocks)
|
|
210
|
+
for (const [tag, extraSet] of extra) {
|
|
211
|
+
const baseSet = base.get(tag);
|
|
212
|
+
if (!baseSet) {
|
|
213
|
+
base.set(tag, extraSet);
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
// Merge each template section additively
|
|
217
|
+
const merged = {
|
|
218
|
+
tag,
|
|
219
|
+
claudeMd: mergeClaudeMdTemplates(baseSet.claudeMd, extraSet.claudeMd),
|
|
220
|
+
nfr: mergeNfrTemplates(baseSet.nfr, extraSet.nfr),
|
|
221
|
+
structure: extraSet.structure ?? baseSet.structure,
|
|
222
|
+
hooks: mergeHookTemplates(baseSet.hooks, extraSet.hooks),
|
|
223
|
+
review: mergeReviewTemplates(baseSet.review, extraSet.review),
|
|
224
|
+
};
|
|
225
|
+
base.set(tag, merged);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return base;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Merge two ClaudeMdTemplates, appending non-duplicate blocks from the extra template.
|
|
232
|
+
*/
|
|
233
|
+
function mergeClaudeMdTemplates(base, extra) {
|
|
234
|
+
if (!extra)
|
|
235
|
+
return base;
|
|
236
|
+
if (!base)
|
|
237
|
+
return extra;
|
|
238
|
+
const seenIds = new Set(base.blocks.map((b) => b.id));
|
|
239
|
+
const newBlocks = extra.blocks.filter((b) => !seenIds.has(b.id));
|
|
240
|
+
return { ...base, blocks: [...base.blocks, ...newBlocks] };
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Merge two NfrTemplates, appending non-duplicate blocks.
|
|
244
|
+
*/
|
|
245
|
+
function mergeNfrTemplates(base, extra) {
|
|
246
|
+
if (!extra)
|
|
247
|
+
return base;
|
|
248
|
+
if (!base)
|
|
249
|
+
return extra;
|
|
250
|
+
const seenIds = new Set(base.blocks.map((b) => b.id));
|
|
251
|
+
const newBlocks = extra.blocks.filter((b) => !seenIds.has(b.id));
|
|
252
|
+
return { ...base, blocks: [...base.blocks, ...newBlocks] };
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Merge two hook template arrays, appending non-duplicate hooks.
|
|
256
|
+
*/
|
|
257
|
+
function mergeHookTemplates(base, extra) {
|
|
258
|
+
if (!extra)
|
|
259
|
+
return base;
|
|
260
|
+
if (!base)
|
|
261
|
+
return extra;
|
|
262
|
+
const seenNames = new Set(base.map((h) => h.name));
|
|
263
|
+
const newHooks = extra.filter((h) => !seenNames.has(h.name));
|
|
264
|
+
return [...base, ...newHooks];
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Merge two ReviewTemplates, appending non-duplicate blocks.
|
|
268
|
+
*/
|
|
269
|
+
function mergeReviewTemplates(base, extra) {
|
|
270
|
+
if (!extra)
|
|
271
|
+
return base;
|
|
272
|
+
if (!base)
|
|
273
|
+
return extra;
|
|
274
|
+
const seenIds = new Set(base.blocks.map((b) => b.id));
|
|
275
|
+
const newBlocks = extra.blocks.filter((b) => !seenIds.has(b.id));
|
|
276
|
+
return { ...base, blocks: [...base.blocks, ...newBlocks] };
|
|
277
|
+
}
|
|
278
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/registry/loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template renderer.
|
|
3
|
+
*
|
|
4
|
+
* Renders composed template content with project-specific variable substitution.
|
|
5
|
+
* Handles {{variable}} and {{variable | default: value}} syntax.
|
|
6
|
+
*/
|
|
7
|
+
import type { ClaudeMdBlock, NfrBlock, ReviewBlock, Tag } from "../shared/types.js";
|
|
8
|
+
/** Variables available for template rendering. */
|
|
9
|
+
export interface RenderContext {
|
|
10
|
+
readonly projectName: string;
|
|
11
|
+
readonly language: string;
|
|
12
|
+
readonly framework?: string;
|
|
13
|
+
readonly domain?: string;
|
|
14
|
+
readonly repoUrl?: string;
|
|
15
|
+
readonly sensitiveData?: string;
|
|
16
|
+
readonly tags: Tag[];
|
|
17
|
+
readonly [key: string]: unknown;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Render a CLAUDE.md from composed blocks and project context.
|
|
21
|
+
* Returns the full CLAUDE.md content as a string.
|
|
22
|
+
*/
|
|
23
|
+
export declare function renderClaudeMd(blocks: ClaudeMdBlock[], context: RenderContext): string;
|
|
24
|
+
/**
|
|
25
|
+
* Render NFR sections from composed blocks.
|
|
26
|
+
*/
|
|
27
|
+
export declare function renderNfrs(blocks: NfrBlock[], context: RenderContext): string;
|
|
28
|
+
/**
|
|
29
|
+
* Render review checklist blocks grouped by dimension.
|
|
30
|
+
*
|
|
31
|
+
* @param blocks - Composed review blocks from all active tags.
|
|
32
|
+
* @param scope - "comprehensive" renders all items; "focused" limits to critical items.
|
|
33
|
+
* @returns Formatted markdown review checklist.
|
|
34
|
+
*/
|
|
35
|
+
export declare function renderReviewChecklist(blocks: ReviewBlock[], scope: "comprehensive" | "focused"): string;
|
|
36
|
+
/**
|
|
37
|
+
* Render a Status.md skeleton with project info.
|
|
38
|
+
*/
|
|
39
|
+
export declare function renderStatusMd(context: RenderContext): string;
|
|
40
|
+
/**
|
|
41
|
+
* Render a PRD skeleton.
|
|
42
|
+
*/
|
|
43
|
+
export declare function renderPrdSkeleton(context: RenderContext): string;
|
|
44
|
+
/**
|
|
45
|
+
* Render a Tech Spec skeleton.
|
|
46
|
+
*/
|
|
47
|
+
export declare function renderTechSpecSkeleton(context: RenderContext): string;
|
|
48
|
+
/**
|
|
49
|
+
* Render a template string by substituting {{variable}} placeholders.
|
|
50
|
+
* Supports {{variable | default: value}} syntax.
|
|
51
|
+
*/
|
|
52
|
+
export declare function renderTemplate(template: string, context: RenderContext): string;
|
|
53
|
+
//# sourceMappingURL=renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/registry/renderer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,EAAmB,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAIrG,kDAAkD;AAClD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC;IACrB,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,aAAa,EAAE,EACvB,OAAO,EAAE,aAAa,GACrB,MAAM,CAUR;AA0BD;;GAEG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,QAAQ,EAAE,EAClB,OAAO,EAAE,aAAa,GACrB,MAAM,CAQR;AAkBD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,WAAW,EAAE,EACrB,KAAK,EAAE,eAAe,GAAG,SAAS,GACjC,MAAM,CAuDR;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAsC7D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CA6BhE;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CA+BrE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,aAAa,GACrB,MAAM,CA2BR"}
|