project-context-ai 1.3.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/context/store.d.ts.map +1 -1
- package/dist/context/store.js +1 -0
- package/dist/context/store.js.map +1 -1
- package/dist/generators/claude.d.ts.map +1 -1
- package/dist/generators/claude.js +10 -27
- package/dist/generators/claude.js.map +1 -1
- package/dist/generators/codex.d.ts.map +1 -1
- package/dist/generators/codex.js +12 -34
- package/dist/generators/codex.js.map +1 -1
- package/dist/generators/copilot.d.ts.map +1 -1
- package/dist/generators/copilot.js +12 -27
- package/dist/generators/copilot.js.map +1 -1
- package/dist/generators/cursor.d.ts.map +1 -1
- package/dist/generators/cursor.js +11 -33
- package/dist/generators/cursor.js.map +1 -1
- package/dist/generators/gemini.d.ts.map +1 -1
- package/dist/generators/gemini.js +11 -26
- package/dist/generators/gemini.js.map +1 -1
- package/dist/generators/index.d.ts.map +1 -1
- package/dist/generators/index.js +97 -0
- package/dist/generators/index.js.map +1 -1
- package/dist/generators/template.d.ts +10 -9
- package/dist/generators/template.d.ts.map +1 -1
- package/dist/generators/template.js +252 -226
- package/dist/generators/template.js.map +1 -1
- package/dist/generators/trae.d.ts.map +1 -1
- package/dist/generators/trae.js +11 -28
- package/dist/generators/trae.js.map +1 -1
- package/dist/generators/windsurf.d.ts.map +1 -1
- package/dist/generators/windsurf.js +11 -26
- package/dist/generators/windsurf.js.map +1 -1
- package/dist/scanner/business.js +99 -6
- package/dist/scanner/business.js.map +1 -1
- package/dist/scanner/database.js +31 -1
- package/dist/scanner/database.js.map +1 -1
- package/dist/scanner/index.d.ts.map +1 -1
- package/dist/scanner/index.js +4 -1
- package/dist/scanner/index.js.map +1 -1
- package/dist/scanner/patterns.d.ts +23 -0
- package/dist/scanner/patterns.d.ts.map +1 -1
- package/dist/scanner/patterns.js +263 -92
- package/dist/scanner/patterns.js.map +1 -1
- package/dist/scanner/routes.js +16 -2
- package/dist/scanner/routes.js.map +1 -1
- package/dist/scanner/rules.d.ts +3 -0
- package/dist/scanner/rules.d.ts.map +1 -0
- package/dist/scanner/rules.js +177 -0
- package/dist/scanner/rules.js.map +1 -0
- package/dist/types.d.ts +22 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1,119 +1,169 @@
|
|
|
1
|
+
// ─── High-Signal Format: Rules → Stack → Patterns → Details → Pointers ───
|
|
1
2
|
export function buildProjectOverview(ctx) {
|
|
2
3
|
const lines = [];
|
|
3
4
|
lines.push(`# ${ctx.meta.name}`);
|
|
4
5
|
if (ctx.meta.description)
|
|
5
6
|
lines.push(`\n${ctx.meta.description}`);
|
|
6
7
|
lines.push("");
|
|
7
|
-
//
|
|
8
|
-
lines.push("## Tech Stack");
|
|
9
|
-
lines.push("");
|
|
10
|
-
lines.push(`- **Type:** ${ctx.meta.type}`);
|
|
11
|
-
lines.push(`- **Language(s):** ${ctx.meta.languages.join(", ")}`);
|
|
12
|
-
if (ctx.dependencies.packageManager !== "unknown") {
|
|
13
|
-
lines.push(`- **Package Manager:** ${ctx.dependencies.packageManager}`);
|
|
14
|
-
}
|
|
8
|
+
// Compact tech stack (one-liners)
|
|
15
9
|
const categories = groupFrameworksByCategory(ctx);
|
|
16
|
-
// Track which categories are already covered by frameworks
|
|
17
10
|
const coveredCategories = new Set(Object.keys(categories));
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
11
|
+
const stackParts = [];
|
|
12
|
+
stackParts.push(ctx.meta.languages.join(", "));
|
|
13
|
+
if (ctx.dependencies.packageManager !== "unknown")
|
|
14
|
+
stackParts.push(ctx.dependencies.packageManager);
|
|
15
|
+
const fwParts = [];
|
|
16
|
+
for (const [, fws] of Object.entries(categories)) {
|
|
17
|
+
for (const fw of fws)
|
|
18
|
+
fwParts.push(`${fw.name} ${fw.version.replace(/^\^/, "")}`);
|
|
19
|
+
}
|
|
20
|
+
if (fwParts.length > 0)
|
|
21
|
+
stackParts.push(fwParts.join(", "));
|
|
22
|
+
if (ctx.conventions.api)
|
|
23
|
+
stackParts.push(ctx.conventions.api);
|
|
24
|
+
lines.push(`## Tech Stack`);
|
|
25
|
+
lines.push(`${stackParts.join(" | ")}`);
|
|
26
|
+
// Extra lines only for non-covered info
|
|
24
27
|
if (ctx.conventions.styling !== "CSS" && !coveredCategories.has("styling")) {
|
|
25
|
-
lines.push(
|
|
28
|
+
lines.push(`Styling: ${ctx.conventions.styling}`);
|
|
26
29
|
}
|
|
27
30
|
if (ctx.conventions.stateManagement !== "None detected" && !coveredCategories.has("state")) {
|
|
28
|
-
lines.push(
|
|
29
|
-
}
|
|
30
|
-
if (ctx.conventions.api) {
|
|
31
|
-
lines.push(`- **API Pattern:** ${ctx.conventions.api}`);
|
|
32
|
-
}
|
|
33
|
-
if (ctx.conventions.testing !== "No testing framework detected" && !coveredCategories.has("testing")) {
|
|
34
|
-
lines.push(`- **Testing:** ${ctx.conventions.testing}`);
|
|
31
|
+
lines.push(`State: ${ctx.conventions.stateManagement}`);
|
|
35
32
|
}
|
|
36
33
|
lines.push("");
|
|
37
34
|
return lines.join("\n");
|
|
38
35
|
}
|
|
39
|
-
export function
|
|
36
|
+
export function buildRulesSection(ctx) {
|
|
37
|
+
if (!ctx.rules?.length)
|
|
38
|
+
return "";
|
|
40
39
|
const lines = [];
|
|
41
|
-
lines.push("##
|
|
40
|
+
lines.push("## Critical Rules");
|
|
42
41
|
lines.push("");
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
for (const child of children) {
|
|
51
|
-
const childName = child.path.split("/").pop();
|
|
52
|
-
lines.push(` ${childName}/ — ${child.description} (${child.fileCount} files)`);
|
|
53
|
-
}
|
|
42
|
+
const nevers = ctx.rules.filter((r) => r.type === "never");
|
|
43
|
+
const always = ctx.rules.filter((r) => r.type === "always");
|
|
44
|
+
for (const r of nevers) {
|
|
45
|
+
lines.push(`- ⛔ NEVER ${r.rule}`);
|
|
46
|
+
}
|
|
47
|
+
for (const r of always) {
|
|
48
|
+
lines.push(`- ✅ ALWAYS ${r.rule}`);
|
|
54
49
|
}
|
|
55
|
-
lines.push("```");
|
|
56
50
|
lines.push("");
|
|
57
51
|
return lines.join("\n");
|
|
58
52
|
}
|
|
59
|
-
export function
|
|
53
|
+
export function buildPatternsSection(ctx) {
|
|
54
|
+
if (!ctx.patterns)
|
|
55
|
+
return "";
|
|
56
|
+
const p = ctx.patterns;
|
|
60
57
|
const lines = [];
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
lines.push("## Code Patterns");
|
|
59
|
+
lines.push("");
|
|
60
|
+
// DI
|
|
61
|
+
if (p.di) {
|
|
62
|
+
lines.push(`**DI:** ${p.di}`);
|
|
63
|
+
const diEx = p.codeExamples.find((e) => e.category === "di");
|
|
64
|
+
if (diEx) {
|
|
65
|
+
lines.push("```typescript");
|
|
66
|
+
lines.push(diEx.code);
|
|
67
|
+
lines.push("```");
|
|
68
|
+
}
|
|
63
69
|
lines.push("");
|
|
64
|
-
|
|
65
|
-
|
|
70
|
+
}
|
|
71
|
+
// Imports
|
|
72
|
+
if (p.imports.length > 0) {
|
|
73
|
+
lines.push("**Imports:**");
|
|
74
|
+
for (const imp of p.imports) {
|
|
75
|
+
const icon = imp.toLowerCase().includes("no ") || imp.toLowerCase().includes("never") ? "❌" : "✅";
|
|
76
|
+
lines.push(`- ${icon} ${imp}`);
|
|
66
77
|
}
|
|
67
78
|
lines.push("");
|
|
68
79
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
80
|
+
// Error handling
|
|
81
|
+
if (p.errorHandling.length > 0) {
|
|
82
|
+
const bases = [...new Set(p.errorHandling.map((e) => e.extendsFrom))];
|
|
83
|
+
lines.push(`**Errors:** Custom classes extending ${bases.join(", ")}`);
|
|
84
|
+
for (const err of p.errorHandling.slice(0, 8)) {
|
|
85
|
+
lines.push(`- \`${err.className}\` → \`${err.file}\``);
|
|
86
|
+
}
|
|
87
|
+
const errEx = p.codeExamples.find((e) => e.category === "error-handling");
|
|
88
|
+
if (errEx) {
|
|
89
|
+
lines.push("```typescript");
|
|
90
|
+
lines.push(errEx.code);
|
|
91
|
+
lines.push("```");
|
|
92
|
+
}
|
|
75
93
|
lines.push("");
|
|
76
|
-
|
|
77
|
-
|
|
94
|
+
}
|
|
95
|
+
// Testing
|
|
96
|
+
if (p.testPatterns) {
|
|
97
|
+
const t = p.testPatterns;
|
|
98
|
+
const parts = [`**Testing:** ${t.framework}`];
|
|
99
|
+
if (t.coverageThreshold !== null)
|
|
100
|
+
parts.push(`${t.coverageThreshold}% coverage`);
|
|
101
|
+
parts.push(`\`${t.unitFilePattern}\``);
|
|
102
|
+
if (t.integrationFilePattern)
|
|
103
|
+
parts.push(`integration: \`${t.integrationFilePattern}\``);
|
|
104
|
+
if (t.assertionStyle)
|
|
105
|
+
parts.push(t.assertionStyle);
|
|
106
|
+
lines.push(parts.join(" | "));
|
|
107
|
+
lines.push("");
|
|
108
|
+
}
|
|
109
|
+
// Architecture rules
|
|
110
|
+
if (p.architecturalRules.length > 0) {
|
|
111
|
+
lines.push("**Architecture Rules:**");
|
|
112
|
+
for (const rule of p.architecturalRules) {
|
|
113
|
+
const icon = rule.toLowerCase().includes("not") || rule.toLowerCase().includes("forbidden") ? "❌" : "✅";
|
|
114
|
+
lines.push(`- ${icon} ${rule}`);
|
|
78
115
|
}
|
|
79
116
|
lines.push("");
|
|
80
117
|
}
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
118
|
+
// Naming (compact)
|
|
119
|
+
const namingParts = [`Files: ${p.naming.files}`, `Vars: ${p.naming.variables}`];
|
|
120
|
+
if (p.naming.dbColumns !== "unknown")
|
|
121
|
+
namingParts.push(`DB: ${p.naming.dbColumns}`);
|
|
122
|
+
lines.push(`**Naming:** ${namingParts.join(" | ")}`);
|
|
123
|
+
lines.push("");
|
|
124
|
+
// Code conventions
|
|
125
|
+
if (p.codeConventions.length > 0) {
|
|
126
|
+
for (const conv of p.codeConventions)
|
|
127
|
+
lines.push(`- ${conv}`);
|
|
87
128
|
lines.push("");
|
|
88
|
-
|
|
89
|
-
|
|
129
|
+
}
|
|
130
|
+
// Code examples (non-DI, non-error)
|
|
131
|
+
const otherExamples = p.codeExamples.filter((e) => !["di", "error-handling"].includes(e.category));
|
|
132
|
+
if (otherExamples.length > 0) {
|
|
133
|
+
lines.push("### Code Examples");
|
|
134
|
+
for (const ex of otherExamples) {
|
|
135
|
+
lines.push(`**${ex.label}** (\`${ex.file}\`):`);
|
|
136
|
+
lines.push("```typescript");
|
|
137
|
+
lines.push(ex.code);
|
|
138
|
+
lines.push("```");
|
|
139
|
+
lines.push("");
|
|
90
140
|
}
|
|
141
|
+
}
|
|
142
|
+
// Workflows
|
|
143
|
+
if (p.workflows.length > 0) {
|
|
144
|
+
lines.push("### Workflows");
|
|
145
|
+
for (const wf of p.workflows)
|
|
146
|
+
lines.push(`- ${wf}`);
|
|
91
147
|
lines.push("");
|
|
92
148
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const lines = [];
|
|
97
|
-
const importantDeps = ctx.dependencies.runtime.filter((d) => d.purpose);
|
|
98
|
-
if (importantDeps.length > 0) {
|
|
99
|
-
lines.push("## Key Dependencies");
|
|
149
|
+
// IDE Skills table
|
|
150
|
+
if (p.ideSkills.length > 0) {
|
|
151
|
+
lines.push("### IDE Skills");
|
|
100
152
|
lines.push("");
|
|
101
|
-
|
|
102
|
-
|
|
153
|
+
lines.push("| Skill | File | Activates On |");
|
|
154
|
+
lines.push("|-------|------|-------------|");
|
|
155
|
+
for (const s of p.ideSkills) {
|
|
156
|
+
lines.push(`| ${s.name} | \`${s.file}\` | ${s.activatesOn || "manual"} |`);
|
|
103
157
|
}
|
|
104
158
|
lines.push("");
|
|
105
159
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
lines.push(`- **Pattern:** ${ctx.conventions.architecture}`);
|
|
113
|
-
if (ctx.conventions.api) {
|
|
114
|
-
lines.push(`- **API:** ${ctx.conventions.api}`);
|
|
160
|
+
// IDE Commands
|
|
161
|
+
if (p.ideCommands.length > 0) {
|
|
162
|
+
lines.push("### IDE Commands");
|
|
163
|
+
for (const c of p.ideCommands)
|
|
164
|
+
lines.push(`- \`/${c.name}\` — ${c.description}`);
|
|
165
|
+
lines.push("");
|
|
115
166
|
}
|
|
116
|
-
lines.push("");
|
|
117
167
|
return lines.join("\n");
|
|
118
168
|
}
|
|
119
169
|
export function buildRoutesSection(ctx) {
|
|
@@ -122,15 +172,23 @@ export function buildRoutesSection(ctx) {
|
|
|
122
172
|
const lines = [];
|
|
123
173
|
lines.push("## API Routes");
|
|
124
174
|
lines.push("");
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
175
|
+
const hasHandlers = ctx.routes.some((r) => r.handler);
|
|
176
|
+
let header = "| Method | Path | File | Auth |";
|
|
177
|
+
let sep = "|--------|------|------|------|";
|
|
178
|
+
if (hasHandlers) {
|
|
179
|
+
header += " Handler |";
|
|
180
|
+
sep += "---------|";
|
|
181
|
+
}
|
|
182
|
+
lines.push(header);
|
|
183
|
+
lines.push(sep);
|
|
184
|
+
for (const r of ctx.routes.slice(0, 30)) {
|
|
185
|
+
let row = `| ${r.method} | ${r.path} | \`${r.file}\` | ${r.auth ? "✓" : "—"} |`;
|
|
186
|
+
if (hasHandlers)
|
|
187
|
+
row += ` ${r.handler || "—"} |`;
|
|
188
|
+
lines.push(row);
|
|
130
189
|
}
|
|
131
190
|
if (ctx.routes.length > 30) {
|
|
132
|
-
lines.push(
|
|
133
|
-
lines.push(`> ${ctx.routes.length} routes total (showing first 30)`);
|
|
191
|
+
lines.push(`\n> ${ctx.routes.length} routes total`);
|
|
134
192
|
}
|
|
135
193
|
lines.push("");
|
|
136
194
|
return lines.join("\n");
|
|
@@ -141,107 +199,102 @@ export function buildDatabaseSection(ctx) {
|
|
|
141
199
|
const lines = [];
|
|
142
200
|
lines.push("## Database Schema");
|
|
143
201
|
lines.push("");
|
|
144
|
-
const
|
|
145
|
-
for (const model of models) {
|
|
202
|
+
for (const model of ctx.database.slice(0, 15)) {
|
|
146
203
|
lines.push(`### ${model.name} (${model.source})`);
|
|
147
|
-
for (const
|
|
204
|
+
for (const f of model.fields) {
|
|
148
205
|
const tags = [];
|
|
149
|
-
if (
|
|
150
|
-
tags.push("
|
|
151
|
-
if (
|
|
206
|
+
if (f.primary)
|
|
207
|
+
tags.push("PK");
|
|
208
|
+
if (f.unique)
|
|
152
209
|
tags.push("unique");
|
|
153
|
-
if (
|
|
210
|
+
if (f.required === false)
|
|
154
211
|
tags.push("optional");
|
|
155
|
-
|
|
156
|
-
|
|
212
|
+
if (f.defaultValue)
|
|
213
|
+
tags.push(`default: ${f.defaultValue}`);
|
|
214
|
+
const t = tags.length ? ` (${tags.join(", ")})` : "";
|
|
215
|
+
lines.push(`- **${f.name}** ${f.type}${t}`);
|
|
157
216
|
}
|
|
158
|
-
for (const
|
|
159
|
-
lines.push(`- **${
|
|
217
|
+
for (const r of model.relations) {
|
|
218
|
+
lines.push(`- **${r.name}** → ${r.target} (${r.type})`);
|
|
219
|
+
}
|
|
220
|
+
if (model.indexes?.length) {
|
|
221
|
+
for (const idx of model.indexes) {
|
|
222
|
+
lines.push(`- 📇 ${idx.unique ? "unique" : "index"}(${idx.fields.join(", ")})`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
if (model.enums?.length) {
|
|
226
|
+
for (const en of model.enums) {
|
|
227
|
+
lines.push(`- 📋 \`${en.name}\`: ${en.values.join(" | ")}`);
|
|
228
|
+
}
|
|
160
229
|
}
|
|
161
230
|
lines.push("");
|
|
162
231
|
}
|
|
163
|
-
if (ctx.database.length > 15)
|
|
164
|
-
lines.push(`> ... and ${ctx.database.length - 15} more models`);
|
|
165
|
-
lines.push("");
|
|
166
|
-
}
|
|
167
|
-
return lines.join("\n");
|
|
168
|
-
}
|
|
169
|
-
export function buildEnvVarsSection(ctx) {
|
|
170
|
-
if (!ctx.envVars?.length)
|
|
171
|
-
return "";
|
|
172
|
-
const lines = [];
|
|
173
|
-
lines.push("## Environment Variables");
|
|
174
|
-
lines.push("");
|
|
175
|
-
// Group by category
|
|
176
|
-
const groups = new Map();
|
|
177
|
-
for (const v of ctx.envVars) {
|
|
178
|
-
if (!groups.has(v.category))
|
|
179
|
-
groups.set(v.category, []);
|
|
180
|
-
groups.get(v.category).push(v);
|
|
181
|
-
}
|
|
182
|
-
const categoryLabels = {
|
|
183
|
-
database: "Database",
|
|
184
|
-
auth: "Auth",
|
|
185
|
-
"api-key": "API Keys",
|
|
186
|
-
service: "Services",
|
|
187
|
-
"feature-flag": "Feature Flags",
|
|
188
|
-
config: "Config",
|
|
189
|
-
other: "Other",
|
|
190
|
-
};
|
|
191
|
-
for (const [category, vars] of groups) {
|
|
192
|
-
const label = categoryLabels[category] || capitalize(category);
|
|
193
|
-
const varList = vars.map((v) => `\`${v.name}\`${v.required ? " (required)" : ""}`).join(", ");
|
|
194
|
-
lines.push(`**${label}:** ${varList}`);
|
|
195
|
-
lines.push("");
|
|
196
|
-
}
|
|
232
|
+
if (ctx.database.length > 15)
|
|
233
|
+
lines.push(`> ... and ${ctx.database.length - 15} more models\n`);
|
|
197
234
|
return lines.join("\n");
|
|
198
235
|
}
|
|
199
|
-
export function
|
|
200
|
-
if (!ctx.
|
|
236
|
+
export function buildModulesSection(ctx) {
|
|
237
|
+
if (!ctx.modules?.length)
|
|
201
238
|
return "";
|
|
202
239
|
const lines = [];
|
|
203
|
-
lines.push("##
|
|
240
|
+
lines.push("## Modules");
|
|
204
241
|
lines.push("");
|
|
205
|
-
for (const
|
|
206
|
-
|
|
242
|
+
for (const m of ctx.modules) {
|
|
243
|
+
const deps = m.dependsOn.length > 0 ? `→ ${m.dependsOn.join(", ")}` : "(no deps)";
|
|
244
|
+
lines.push(`- **${m.name}** (${m.files} files) ${deps}`);
|
|
207
245
|
}
|
|
208
246
|
lines.push("");
|
|
209
247
|
return lines.join("\n");
|
|
210
248
|
}
|
|
211
|
-
export function
|
|
212
|
-
if (!ctx.modules?.length)
|
|
213
|
-
return "";
|
|
249
|
+
export function buildEnvServicesSection(ctx) {
|
|
214
250
|
const lines = [];
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
251
|
+
// Services (compact)
|
|
252
|
+
if (ctx.services?.length) {
|
|
253
|
+
lines.push("## External Services");
|
|
254
|
+
lines.push(ctx.services.map((s) => `**${s.name}** (${s.type})`).join(" · "));
|
|
255
|
+
lines.push("");
|
|
256
|
+
}
|
|
257
|
+
// Env vars (compact by category)
|
|
258
|
+
if (ctx.envVars?.length) {
|
|
259
|
+
lines.push("## Environment Variables");
|
|
260
|
+
lines.push("");
|
|
261
|
+
const groups = new Map();
|
|
262
|
+
for (const v of ctx.envVars) {
|
|
263
|
+
if (!groups.has(v.category))
|
|
264
|
+
groups.set(v.category, []);
|
|
265
|
+
groups.get(v.category).push(v);
|
|
266
|
+
}
|
|
267
|
+
const labels = {
|
|
268
|
+
database: "DB", auth: "Auth", "api-key": "API Keys",
|
|
269
|
+
service: "Services", "feature-flag": "Flags", config: "Config", other: "Other",
|
|
270
|
+
};
|
|
271
|
+
for (const [cat, vars] of groups) {
|
|
272
|
+
const label = labels[cat] || cat;
|
|
273
|
+
const required = vars.filter((v) => v.required).map((v) => `\`${v.name}\``);
|
|
274
|
+
const optional = vars.filter((v) => !v.required).map((v) => `\`${v.name}\``);
|
|
275
|
+
const parts = [];
|
|
276
|
+
if (required.length)
|
|
277
|
+
parts.push(required.join(", "));
|
|
278
|
+
if (optional.length)
|
|
279
|
+
parts.push(`optional: ${optional.join(", ")}`);
|
|
280
|
+
lines.push(`**${label}:** ${parts.join(" | ")}`);
|
|
281
|
+
}
|
|
282
|
+
lines.push("");
|
|
222
283
|
}
|
|
223
|
-
lines.push("");
|
|
224
284
|
return lines.join("\n");
|
|
225
285
|
}
|
|
226
286
|
export function buildBusinessSection(ctx) {
|
|
227
287
|
if (!ctx.business)
|
|
228
288
|
return "";
|
|
229
|
-
const lines = [];
|
|
230
289
|
const biz = ctx.business;
|
|
231
|
-
lines
|
|
232
|
-
|
|
233
|
-
if (biz.description) {
|
|
234
|
-
lines.push(biz.description);
|
|
235
|
-
lines.push("");
|
|
236
|
-
}
|
|
290
|
+
const lines = [];
|
|
291
|
+
// Features
|
|
237
292
|
if (biz.features.length > 0) {
|
|
238
|
-
lines.push("
|
|
293
|
+
lines.push("## Features");
|
|
239
294
|
lines.push("");
|
|
240
295
|
for (const f of biz.features) {
|
|
241
|
-
// Category markers from extractAllBullets start with [
|
|
242
296
|
if (f.startsWith("[") && f.endsWith("]")) {
|
|
243
|
-
lines.push(
|
|
244
|
-
lines.push(`**${f.slice(1, -1)}:**`);
|
|
297
|
+
lines.push(`\n**${f.slice(1, -1)}:**`);
|
|
245
298
|
}
|
|
246
299
|
else {
|
|
247
300
|
lines.push(`- ${f}`);
|
|
@@ -249,111 +302,84 @@ export function buildBusinessSection(ctx) {
|
|
|
249
302
|
}
|
|
250
303
|
lines.push("");
|
|
251
304
|
}
|
|
305
|
+
// Skills
|
|
252
306
|
if (biz.skills.length > 0) {
|
|
253
|
-
lines.push("
|
|
307
|
+
lines.push("## Skills / Plugins");
|
|
254
308
|
lines.push("");
|
|
255
|
-
// Group by interface if available
|
|
256
309
|
const interfaces = new Set(biz.skills.map((s) => s.interface).filter(Boolean));
|
|
257
310
|
if (interfaces.size === 1) {
|
|
258
311
|
lines.push(`> ${biz.skills.length} skills implementing \`${[...interfaces][0]}\``);
|
|
259
312
|
lines.push("");
|
|
260
313
|
}
|
|
261
314
|
for (const skill of biz.skills) {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
lines.push("");
|
|
269
|
-
for (const doc of biz.documentation) {
|
|
270
|
-
lines.push(`- **${doc.title}** (\`${doc.file}\`) — ${doc.summary}`);
|
|
315
|
+
const tools = skill.toolCount ? ` (${skill.toolCount} tools)` : "";
|
|
316
|
+
lines.push(`- **${skill.name}**${tools} — \`${skill.file}\``);
|
|
317
|
+
if (skill.methods?.length) {
|
|
318
|
+
for (const m of skill.methods.slice(0, 4))
|
|
319
|
+
lines.push(` - \`${m}\``);
|
|
320
|
+
}
|
|
271
321
|
}
|
|
272
322
|
lines.push("");
|
|
273
323
|
}
|
|
324
|
+
// Validation rules
|
|
274
325
|
if (biz.validationRules.length > 0) {
|
|
275
|
-
lines.push("
|
|
326
|
+
lines.push("## Validation");
|
|
276
327
|
lines.push("");
|
|
277
|
-
for (const
|
|
278
|
-
const fields =
|
|
279
|
-
lines.push(`- \`${
|
|
328
|
+
for (const r of biz.validationRules) {
|
|
329
|
+
const fields = r.fields.length > 0 ? ` — ${r.fields.join(", ")}` : "";
|
|
330
|
+
lines.push(`- \`${r.schema}\` (${r.library})${fields}`);
|
|
280
331
|
}
|
|
281
332
|
lines.push("");
|
|
282
333
|
}
|
|
334
|
+
// Auth
|
|
283
335
|
if (biz.authPatterns.length > 0) {
|
|
284
|
-
lines.push("
|
|
336
|
+
lines.push("## Auth & Permissions");
|
|
285
337
|
lines.push("");
|
|
286
|
-
for (const
|
|
287
|
-
lines.push(`- ${
|
|
288
|
-
}
|
|
338
|
+
for (const p of biz.authPatterns)
|
|
339
|
+
lines.push(`- ${p}`);
|
|
289
340
|
lines.push("");
|
|
290
341
|
}
|
|
342
|
+
// Domain entities
|
|
291
343
|
if (biz.domainEntities.length > 0) {
|
|
292
|
-
lines.push("
|
|
293
|
-
lines.push("");
|
|
344
|
+
lines.push("## Domain Entities");
|
|
294
345
|
lines.push(biz.domainEntities.join(", "));
|
|
295
346
|
lines.push("");
|
|
296
347
|
}
|
|
297
348
|
return lines.join("\n");
|
|
298
349
|
}
|
|
299
|
-
export function
|
|
300
|
-
if (!ctx.patterns)
|
|
350
|
+
export function buildDocIndexSection(ctx) {
|
|
351
|
+
if (!ctx.business?.documentation?.length && !ctx.patterns?.ideSkills?.length)
|
|
301
352
|
return "";
|
|
302
|
-
const p = ctx.patterns;
|
|
303
353
|
const lines = [];
|
|
304
|
-
lines.push("##
|
|
354
|
+
lines.push("## Documentation Index");
|
|
355
|
+
lines.push("Read these files for detailed context:");
|
|
305
356
|
lines.push("");
|
|
306
|
-
if (
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
lines.push(`- ${imp}`);
|
|
314
|
-
}
|
|
315
|
-
lines.push("");
|
|
316
|
-
}
|
|
317
|
-
lines.push("**Naming:**");
|
|
318
|
-
lines.push(`- Files: ${p.naming.files}`);
|
|
319
|
-
if (p.naming.dbColumns !== "unknown") {
|
|
320
|
-
lines.push(`- DB columns: ${p.naming.dbColumns}`);
|
|
321
|
-
}
|
|
322
|
-
lines.push("");
|
|
323
|
-
if (p.codeConventions.length > 0) {
|
|
324
|
-
lines.push("**Conventions:**");
|
|
325
|
-
for (const conv of p.codeConventions) {
|
|
326
|
-
lines.push(`- ${conv}`);
|
|
327
|
-
}
|
|
328
|
-
lines.push("");
|
|
329
|
-
}
|
|
330
|
-
if (p.workflows.length > 0) {
|
|
331
|
-
lines.push("**Workflows:**");
|
|
332
|
-
for (const wf of p.workflows) {
|
|
333
|
-
lines.push(`- ${wf}`);
|
|
334
|
-
}
|
|
335
|
-
lines.push("");
|
|
336
|
-
}
|
|
337
|
-
if (p.ideSkills.length > 0) {
|
|
338
|
-
lines.push("**IDE Skills:**");
|
|
339
|
-
lines.push("");
|
|
340
|
-
lines.push("| Skill | File | Activates On |");
|
|
341
|
-
lines.push("|-------|------|-------------|");
|
|
342
|
-
for (const skill of p.ideSkills) {
|
|
343
|
-
const activates = skill.activatesOn || "manual";
|
|
344
|
-
lines.push(`| ${skill.name} | \`${skill.file}\` | ${activates} |`);
|
|
357
|
+
if (ctx.business?.documentation) {
|
|
358
|
+
for (const doc of ctx.business.documentation) {
|
|
359
|
+
lines.push(`- \`${doc.file}\` — ${doc.title}`);
|
|
360
|
+
if (doc.keyRules?.length) {
|
|
361
|
+
for (const rule of doc.keyRules)
|
|
362
|
+
lines.push(` - ⚠️ ${rule}`);
|
|
363
|
+
}
|
|
345
364
|
}
|
|
346
|
-
lines.push("");
|
|
347
365
|
}
|
|
348
|
-
if (
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
lines.push(`-
|
|
366
|
+
if (ctx.patterns?.ideSkills?.length) {
|
|
367
|
+
for (const skill of ctx.patterns.ideSkills) {
|
|
368
|
+
const when = skill.activatesOn ? ` (read when editing ${skill.activatesOn})` : "";
|
|
369
|
+
lines.push(`- \`${skill.file}\` — ${skill.description || skill.name}${when}`);
|
|
352
370
|
}
|
|
353
|
-
lines.push("");
|
|
354
371
|
}
|
|
372
|
+
lines.push("");
|
|
355
373
|
return lines.join("\n");
|
|
356
374
|
}
|
|
375
|
+
// ─── Legacy exports (kept for backward compat but now unused by generators) ───
|
|
376
|
+
export function buildStructureSection(_ctx) { return ""; }
|
|
377
|
+
export function buildKeyFilesSection(_ctx) { return ""; }
|
|
378
|
+
export function buildEntryPointsSection(_ctx) { return ""; }
|
|
379
|
+
export function buildScriptsSection(_ctx) { return ""; }
|
|
380
|
+
export function buildDependenciesSection(_ctx) { return ""; }
|
|
381
|
+
export function buildArchitectureSection(_ctx) { return ""; }
|
|
382
|
+
// ─── Helpers ──────────────────────────────────────────────
|
|
357
383
|
function groupFrameworksByCategory(ctx) {
|
|
358
384
|
const groups = {};
|
|
359
385
|
for (const fw of ctx.frameworks) {
|