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.
Files changed (51) hide show
  1. package/dist/context/store.d.ts.map +1 -1
  2. package/dist/context/store.js +1 -0
  3. package/dist/context/store.js.map +1 -1
  4. package/dist/generators/claude.d.ts.map +1 -1
  5. package/dist/generators/claude.js +10 -27
  6. package/dist/generators/claude.js.map +1 -1
  7. package/dist/generators/codex.d.ts.map +1 -1
  8. package/dist/generators/codex.js +12 -34
  9. package/dist/generators/codex.js.map +1 -1
  10. package/dist/generators/copilot.d.ts.map +1 -1
  11. package/dist/generators/copilot.js +12 -27
  12. package/dist/generators/copilot.js.map +1 -1
  13. package/dist/generators/cursor.d.ts.map +1 -1
  14. package/dist/generators/cursor.js +11 -33
  15. package/dist/generators/cursor.js.map +1 -1
  16. package/dist/generators/gemini.d.ts.map +1 -1
  17. package/dist/generators/gemini.js +11 -26
  18. package/dist/generators/gemini.js.map +1 -1
  19. package/dist/generators/index.d.ts.map +1 -1
  20. package/dist/generators/index.js +97 -0
  21. package/dist/generators/index.js.map +1 -1
  22. package/dist/generators/template.d.ts +10 -9
  23. package/dist/generators/template.d.ts.map +1 -1
  24. package/dist/generators/template.js +252 -226
  25. package/dist/generators/template.js.map +1 -1
  26. package/dist/generators/trae.d.ts.map +1 -1
  27. package/dist/generators/trae.js +11 -28
  28. package/dist/generators/trae.js.map +1 -1
  29. package/dist/generators/windsurf.d.ts.map +1 -1
  30. package/dist/generators/windsurf.js +11 -26
  31. package/dist/generators/windsurf.js.map +1 -1
  32. package/dist/scanner/business.js +99 -6
  33. package/dist/scanner/business.js.map +1 -1
  34. package/dist/scanner/database.js +31 -1
  35. package/dist/scanner/database.js.map +1 -1
  36. package/dist/scanner/index.d.ts.map +1 -1
  37. package/dist/scanner/index.js +4 -1
  38. package/dist/scanner/index.js.map +1 -1
  39. package/dist/scanner/patterns.d.ts +23 -0
  40. package/dist/scanner/patterns.d.ts.map +1 -1
  41. package/dist/scanner/patterns.js +263 -92
  42. package/dist/scanner/patterns.js.map +1 -1
  43. package/dist/scanner/routes.js +16 -2
  44. package/dist/scanner/routes.js.map +1 -1
  45. package/dist/scanner/rules.d.ts +3 -0
  46. package/dist/scanner/rules.d.ts.map +1 -0
  47. package/dist/scanner/rules.js +177 -0
  48. package/dist/scanner/rules.js.map +1 -0
  49. package/dist/types.d.ts +22 -0
  50. package/dist/types.d.ts.map +1 -1
  51. 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
- // Tech stack summary
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
- for (const [category, fws] of Object.entries(categories)) {
19
- const label = capitalize(category);
20
- const names = fws.map((f) => `${f.name} (${f.version})`).join(", ");
21
- lines.push(`- **${label}:** ${names}`);
22
- }
23
- // Only add conventions that aren't already covered by frameworks
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(`- **Styling:** ${ctx.conventions.styling}`);
28
+ lines.push(`Styling: ${ctx.conventions.styling}`);
26
29
  }
27
30
  if (ctx.conventions.stateManagement !== "None detected" && !coveredCategories.has("state")) {
28
- lines.push(`- **State:** ${ctx.conventions.stateManagement}`);
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 buildStructureSection(ctx) {
36
+ export function buildRulesSection(ctx) {
37
+ if (!ctx.rules?.length)
38
+ return "";
40
39
  const lines = [];
41
- lines.push("## Project Structure");
40
+ lines.push("## Critical Rules");
42
41
  lines.push("");
43
- lines.push("```");
44
- // Group by top-level directory
45
- const topLevel = ctx.structure.filter((d) => !d.path.includes("/"));
46
- const nested = ctx.structure.filter((d) => d.path.includes("/"));
47
- for (const dir of topLevel) {
48
- lines.push(`${dir.path}/ — ${dir.description} (${dir.fileCount} files)`);
49
- const children = nested.filter((d) => d.path.startsWith(dir.path + "/") && d.path.split("/").length === 2);
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 buildKeyFilesSection(ctx) {
53
+ export function buildPatternsSection(ctx) {
54
+ if (!ctx.patterns)
55
+ return "";
56
+ const p = ctx.patterns;
60
57
  const lines = [];
61
- if (ctx.keyFiles.length > 0) {
62
- lines.push("## Key Files");
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
- for (const kf of ctx.keyFiles) {
65
- lines.push(`- \`${kf.path}\` — ${kf.role}`);
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
- return lines.join("\n");
70
- }
71
- export function buildEntryPointsSection(ctx) {
72
- const lines = [];
73
- if (ctx.entryPoints.length > 0) {
74
- lines.push("## Entry Points");
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
- for (const ep of ctx.entryPoints) {
77
- lines.push(`- \`${ep}\``);
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
- return lines.join("\n");
82
- }
83
- export function buildScriptsSection(ctx) {
84
- const lines = [];
85
- if (Object.keys(ctx.scripts).length > 0) {
86
- lines.push("## Available Scripts");
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
- for (const [name, cmd] of Object.entries(ctx.scripts)) {
89
- lines.push(`- \`${ctx.dependencies.packageManager} run ${name}\` — \`${cmd}\``);
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
- return lines.join("\n");
94
- }
95
- export function buildDependenciesSection(ctx) {
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
- for (const dep of importantDeps) {
102
- lines.push(`- **${dep.name}** (${dep.version}) — ${dep.purpose}`);
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
- return lines.join("\n");
107
- }
108
- export function buildArchitectureSection(ctx) {
109
- const lines = [];
110
- lines.push("## Architecture");
111
- lines.push("");
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
- lines.push("| Method | Path | File | Auth |");
126
- lines.push("|--------|------|------|------|");
127
- const routes = ctx.routes.slice(0, 30);
128
- for (const r of routes) {
129
- lines.push(`| ${r.method} | ${r.path} | \`${r.file}\` | ${r.auth ? "Yes" : "No"} |`);
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 models = ctx.database.slice(0, 15);
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 field of model.fields) {
204
+ for (const f of model.fields) {
148
205
  const tags = [];
149
- if (field.primary)
150
- tags.push("primary");
151
- if (field.unique)
206
+ if (f.primary)
207
+ tags.push("PK");
208
+ if (f.unique)
152
209
  tags.push("unique");
153
- if (field.required === false)
210
+ if (f.required === false)
154
211
  tags.push("optional");
155
- const tagStr = tags.length ? ` (${tags.join(", ")})` : "";
156
- lines.push(`- **${field.name}** — ${field.type}${tagStr}`);
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 rel of model.relations) {
159
- lines.push(`- **${rel.name}** → ${rel.target} (${rel.type})`);
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 buildServicesSection(ctx) {
200
- if (!ctx.services?.length)
236
+ export function buildModulesSection(ctx) {
237
+ if (!ctx.modules?.length)
201
238
  return "";
202
239
  const lines = [];
203
- lines.push("## External Services");
240
+ lines.push("## Modules");
204
241
  lines.push("");
205
- for (const svc of ctx.services) {
206
- lines.push(`- **${svc.name}** ${svc.type} (${svc.source})`);
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 buildModulesSection(ctx) {
212
- if (!ctx.modules?.length)
213
- return "";
249
+ export function buildEnvServicesSection(ctx) {
214
250
  const lines = [];
215
- lines.push("## Modules");
216
- lines.push("");
217
- for (const mod of ctx.modules) {
218
- const deps = mod.dependsOn.length > 0
219
- ? `depends on: ${mod.dependsOn.join(", ")}`
220
- : "no dependencies";
221
- lines.push(`- **${mod.name}** (${mod.files} files) → ${deps}`);
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.push("## Business Context");
232
- lines.push("");
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("### Features");
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("### Skills / Plugins");
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
- lines.push(`- **${skill.name}** \`${skill.file}\``);
263
- }
264
- lines.push("");
265
- }
266
- if (biz.documentation.length > 0) {
267
- lines.push("### Documentation");
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("### Validation Rules");
326
+ lines.push("## Validation");
276
327
  lines.push("");
277
- for (const rule of biz.validationRules) {
278
- const fields = rule.fields.length > 0 ? ` — ${rule.fields.join(", ")}` : "";
279
- lines.push(`- \`${rule.schema}\` (${rule.library})${fields}`);
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("### Auth & Permissions");
336
+ lines.push("## Auth & Permissions");
285
337
  lines.push("");
286
- for (const pattern of biz.authPatterns) {
287
- lines.push(`- ${pattern}`);
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("### Domain Entities");
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 buildPatternsSection(ctx) {
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("## Code Patterns & Conventions");
354
+ lines.push("## Documentation Index");
355
+ lines.push("Read these files for detailed context:");
305
356
  lines.push("");
306
- if (p.di) {
307
- lines.push(`**Dependency Injection:** ${p.di}`);
308
- lines.push("");
309
- }
310
- if (p.imports.length > 0) {
311
- lines.push("**Import Conventions:**");
312
- for (const imp of p.imports) {
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 (p.ideCommands.length > 0) {
349
- lines.push("**IDE Commands:**");
350
- for (const cmd of p.ideCommands) {
351
- lines.push(`- \`/${cmd.name}\` — ${cmd.description} (\`${cmd.file}\`)`);
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) {