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.
Files changed (147) hide show
  1. package/README.md +251 -0
  2. package/dist/analyzers/anti-pattern.d.ts +21 -0
  3. package/dist/analyzers/anti-pattern.d.ts.map +1 -0
  4. package/dist/analyzers/anti-pattern.js +130 -0
  5. package/dist/analyzers/anti-pattern.js.map +1 -0
  6. package/dist/analyzers/completeness.d.ts +15 -0
  7. package/dist/analyzers/completeness.d.ts.map +1 -0
  8. package/dist/analyzers/completeness.js +207 -0
  9. package/dist/analyzers/completeness.js.map +1 -0
  10. package/dist/analyzers/folder-structure.d.ts +35 -0
  11. package/dist/analyzers/folder-structure.d.ts.map +1 -0
  12. package/dist/analyzers/folder-structure.js +151 -0
  13. package/dist/analyzers/folder-structure.js.map +1 -0
  14. package/dist/analyzers/package-json.d.ts +22 -0
  15. package/dist/analyzers/package-json.d.ts.map +1 -0
  16. package/dist/analyzers/package-json.js +229 -0
  17. package/dist/analyzers/package-json.js.map +1 -0
  18. package/dist/index.d.ts +9 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +59 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/registry/composer.d.ts +32 -0
  23. package/dist/registry/composer.d.ts.map +1 -0
  24. package/dist/registry/composer.js +169 -0
  25. package/dist/registry/composer.js.map +1 -0
  26. package/dist/registry/loader.d.ts +37 -0
  27. package/dist/registry/loader.d.ts.map +1 -0
  28. package/dist/registry/loader.js +278 -0
  29. package/dist/registry/loader.js.map +1 -0
  30. package/dist/registry/renderer.d.ts +53 -0
  31. package/dist/registry/renderer.d.ts.map +1 -0
  32. package/dist/registry/renderer.js +275 -0
  33. package/dist/registry/renderer.js.map +1 -0
  34. package/dist/shared/config/index.d.ts +15 -0
  35. package/dist/shared/config/index.d.ts.map +1 -0
  36. package/dist/shared/config/index.js +16 -0
  37. package/dist/shared/config/index.js.map +1 -0
  38. package/dist/shared/errors/index.d.ts +30 -0
  39. package/dist/shared/errors/index.d.ts.map +1 -0
  40. package/dist/shared/errors/index.js +44 -0
  41. package/dist/shared/errors/index.js.map +1 -0
  42. package/dist/shared/logger/index.d.ts +27 -0
  43. package/dist/shared/logger/index.d.ts.map +1 -0
  44. package/dist/shared/logger/index.js +59 -0
  45. package/dist/shared/logger/index.js.map +1 -0
  46. package/dist/shared/types.d.ts +212 -0
  47. package/dist/shared/types.d.ts.map +1 -0
  48. package/dist/shared/types.js +30 -0
  49. package/dist/shared/types.js.map +1 -0
  50. package/dist/tools/add-hook.d.ts +26 -0
  51. package/dist/tools/add-hook.d.ts.map +1 -0
  52. package/dist/tools/add-hook.js +82 -0
  53. package/dist/tools/add-hook.js.map +1 -0
  54. package/dist/tools/add-module.d.ts +29 -0
  55. package/dist/tools/add-module.d.ts.map +1 -0
  56. package/dist/tools/add-module.js +244 -0
  57. package/dist/tools/add-module.js.map +1 -0
  58. package/dist/tools/audit.d.ts +26 -0
  59. package/dist/tools/audit.d.ts.map +1 -0
  60. package/dist/tools/audit.js +111 -0
  61. package/dist/tools/audit.js.map +1 -0
  62. package/dist/tools/classify.d.ts +23 -0
  63. package/dist/tools/classify.d.ts.map +1 -0
  64. package/dist/tools/classify.js +73 -0
  65. package/dist/tools/classify.js.map +1 -0
  66. package/dist/tools/configure-mcp.d.ts +49 -0
  67. package/dist/tools/configure-mcp.d.ts.map +1 -0
  68. package/dist/tools/configure-mcp.js +127 -0
  69. package/dist/tools/configure-mcp.js.map +1 -0
  70. package/dist/tools/convert.d.ts +27 -0
  71. package/dist/tools/convert.d.ts.map +1 -0
  72. package/dist/tools/convert.js +154 -0
  73. package/dist/tools/convert.js.map +1 -0
  74. package/dist/tools/generate-claude-md.d.ts +29 -0
  75. package/dist/tools/generate-claude-md.d.ts.map +1 -0
  76. package/dist/tools/generate-claude-md.js +116 -0
  77. package/dist/tools/generate-claude-md.js.map +1 -0
  78. package/dist/tools/get-nfr.d.ts +20 -0
  79. package/dist/tools/get-nfr.d.ts.map +1 -0
  80. package/dist/tools/get-nfr.js +53 -0
  81. package/dist/tools/get-nfr.js.map +1 -0
  82. package/dist/tools/list.d.ts +33 -0
  83. package/dist/tools/list.d.ts.map +1 -0
  84. package/dist/tools/list.js +155 -0
  85. package/dist/tools/list.js.map +1 -0
  86. package/dist/tools/refresh-project.d.ts +34 -0
  87. package/dist/tools/refresh-project.d.ts.map +1 -0
  88. package/dist/tools/refresh-project.js +257 -0
  89. package/dist/tools/refresh-project.js.map +1 -0
  90. package/dist/tools/review.d.ts +31 -0
  91. package/dist/tools/review.d.ts.map +1 -0
  92. package/dist/tools/review.js +62 -0
  93. package/dist/tools/review.js.map +1 -0
  94. package/dist/tools/scaffold.d.ts +32 -0
  95. package/dist/tools/scaffold.d.ts.map +1 -0
  96. package/dist/tools/scaffold.js +160 -0
  97. package/dist/tools/scaffold.js.map +1 -0
  98. package/dist/tools/setup-project.d.ts +37 -0
  99. package/dist/tools/setup-project.d.ts.map +1 -0
  100. package/dist/tools/setup-project.js +270 -0
  101. package/dist/tools/setup-project.js.map +1 -0
  102. package/package.json +69 -0
  103. package/templates/analytics/claude-md.yaml +37 -0
  104. package/templates/analytics/structure.yaml +25 -0
  105. package/templates/api/claude-md.yaml +85 -0
  106. package/templates/api/nfr.yaml +23 -0
  107. package/templates/api/review.yaml +103 -0
  108. package/templates/api/structure.yaml +34 -0
  109. package/templates/cli/claude-md.yaml +31 -0
  110. package/templates/cli/review.yaml +53 -0
  111. package/templates/cli/structure.yaml +16 -0
  112. package/templates/data-pipeline/claude-md.yaml +42 -0
  113. package/templates/data-pipeline/nfr.yaml +39 -0
  114. package/templates/data-pipeline/structure.yaml +23 -0
  115. package/templates/fintech/claude-md.yaml +42 -0
  116. package/templates/fintech/nfr.yaml +46 -0
  117. package/templates/game/claude-md.yaml +42 -0
  118. package/templates/healthcare/claude-md.yaml +42 -0
  119. package/templates/healthcare/nfr.yaml +47 -0
  120. package/templates/infra/claude-md.yaml +104 -0
  121. package/templates/infra/nfr.yaml +46 -0
  122. package/templates/infra/review.yaml +65 -0
  123. package/templates/infra/structure.yaml +25 -0
  124. package/templates/library/claude-md.yaml +36 -0
  125. package/templates/library/review.yaml +56 -0
  126. package/templates/library/structure.yaml +19 -0
  127. package/templates/ml/claude-md.yaml +42 -0
  128. package/templates/ml/nfr.yaml +39 -0
  129. package/templates/ml/structure.yaml +25 -0
  130. package/templates/mobile/claude-md.yaml +44 -0
  131. package/templates/mobile/nfr.yaml +49 -0
  132. package/templates/mobile/structure.yaml +27 -0
  133. package/templates/realtime/claude-md.yaml +42 -0
  134. package/templates/social/claude-md.yaml +43 -0
  135. package/templates/state-machine/claude-md.yaml +42 -0
  136. package/templates/universal/claude-md.yaml +477 -0
  137. package/templates/universal/hooks.yaml +196 -0
  138. package/templates/universal/nfr.yaml +197 -0
  139. package/templates/universal/review.yaml +164 -0
  140. package/templates/universal/structure.yaml +52 -0
  141. package/templates/web-react/claude-md.yaml +110 -0
  142. package/templates/web-react/hooks.yaml +44 -0
  143. package/templates/web-react/nfr.yaml +27 -0
  144. package/templates/web-react/review.yaml +94 -0
  145. package/templates/web-react/structure.yaml +46 -0
  146. package/templates/web-static/claude-md.yaml +73 -0
  147. 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"}