@codexa/cli 9.0.8 → 9.0.9

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.
@@ -11,6 +11,7 @@ import type { ContextSection } from "./assembly";
11
11
  function makeSections(): ContextSection[] {
12
12
  return [
13
13
  { name: "STANDARDS", content: "...", priority: 1 },
14
+ { name: "REFERENCIAS", content: "...", priority: 2 },
14
15
  { name: "ALERTAS", content: "...", priority: 2 },
15
16
  { name: "ARQUITETURA", content: "...", priority: 3 },
16
17
  { name: "DECISOES", content: "...", priority: 4 },
@@ -119,7 +120,7 @@ describe("adjustSectionPriorities", () => {
119
120
  it("null domain passes all sections through unchanged", () => {
120
121
  const sections = makeSections();
121
122
  const result = adjustSectionPriorities(sections, null);
122
- expect(result).toHaveLength(12);
123
+ expect(result).toHaveLength(13);
123
124
  expect(result).toEqual(sections);
124
125
  });
125
126
 
@@ -127,8 +128,9 @@ describe("adjustSectionPriorities", () => {
127
128
  const result = adjustSectionPriorities(makeSections(), "explore");
128
129
  const names = result.map(s => s.name);
129
130
 
130
- // explore profile: 7 sections have relevance 0
131
+ // explore profile: 8 sections have relevance 0
131
132
  expect(names).not.toContain("STANDARDS");
133
+ expect(names).not.toContain("REFERENCIAS");
132
134
  expect(names).not.toContain("CONTEXTO DE TASKS ANTERIORES");
133
135
  expect(names).not.toContain("GRAPH");
134
136
  expect(names).not.toContain("PRODUTO");
@@ -189,7 +191,7 @@ describe("adjustSectionPriorities", () => {
189
191
  const result = adjustSectionPriorities(makeSections(), "testing");
190
192
  const names = result.map(s => s.name);
191
193
  expect(names).not.toContain("PRODUTO");
192
- expect(result).toHaveLength(11);
194
+ expect(result).toHaveLength(12);
193
195
  });
194
196
 
195
197
  it("testing domain boosts CONTEXTO DE TASKS ANTERIORES (relevance=3)", () => {
@@ -212,10 +214,30 @@ describe("adjustSectionPriorities", () => {
212
214
  expect(produto?.priority).toBe(5);
213
215
  });
214
216
 
215
- it("security domain excludes PRODUTO (relevance=0)", () => {
217
+ it("backend domain boosts REFERENCIAS (relevance=3)", () => {
218
+ const result = adjustSectionPriorities(makeSections(), "backend");
219
+ const refs = result.find(s => s.name === "REFERENCIAS");
220
+ // backend: REFERENCIAS=3 (base 2 + offset -2 = 0 → floor 1)
221
+ expect(refs?.priority).toBe(1);
222
+ });
223
+
224
+ it("explore domain excludes REFERENCIAS (relevance=0)", () => {
225
+ const result = adjustSectionPriorities(makeSections(), "explore");
226
+ const names = result.map(s => s.name);
227
+ expect(names).not.toContain("REFERENCIAS");
228
+ });
229
+
230
+ it("architecture domain excludes REFERENCIAS (relevance=0)", () => {
231
+ const result = adjustSectionPriorities(makeSections(), "architecture");
232
+ const names = result.map(s => s.name);
233
+ expect(names).not.toContain("REFERENCIAS");
234
+ });
235
+
236
+ it("security domain excludes PRODUTO and REFERENCIAS (relevance=0)", () => {
216
237
  const result = adjustSectionPriorities(makeSections(), "security");
217
238
  const names = result.map(s => s.name);
218
239
  expect(names).not.toContain("PRODUTO");
240
+ expect(names).not.toContain("REFERENCIAS");
219
241
  expect(result).toHaveLength(11);
220
242
  });
221
243
 
@@ -235,12 +257,12 @@ describe("adjustSectionPriorities", () => {
235
257
 
236
258
  describe("DOMAIN_PROFILES completeness", () => {
237
259
  const allSectionNames = [
238
- "STANDARDS", "ALERTAS", "ARQUITETURA", "DECISOES",
260
+ "STANDARDS", "REFERENCIAS", "ALERTAS", "ARQUITETURA", "DECISOES",
239
261
  "CONTEXTO DE TASKS ANTERIORES", "GRAPH", "PRODUTO",
240
262
  "DISCOVERIES", "UTILITIES", "PATTERNS", "HINTS", "STACK",
241
263
  ];
242
264
 
243
- it("every domain profile covers all 12 sections", () => {
265
+ it("every domain profile covers all 13 sections", () => {
244
266
  for (const [domain, profile] of Object.entries(DOMAIN_PROFILES)) {
245
267
  for (const section of allSectionNames) {
246
268
  expect(profile[section as keyof typeof profile]).toBeDefined();
@@ -19,6 +19,7 @@ export type Relevance = 0 | 1 | 2 | 3;
19
19
 
20
20
  export type SectionName =
21
21
  | "STANDARDS"
22
+ | "REFERENCIAS"
22
23
  | "ALERTAS"
23
24
  | "ARQUITETURA"
24
25
  | "DECISOES"
@@ -58,42 +59,42 @@ export const AGENT_DOMAIN: Record<string, AgentDomain> = {
58
59
 
59
60
  export const DOMAIN_PROFILES: Record<AgentDomain, DomainProfile> = {
60
61
  backend: {
61
- "STANDARDS": 3, "ALERTAS": 3, "ARQUITETURA": 2, "DECISOES": 3,
62
+ "STANDARDS": 3, "REFERENCIAS": 3, "ALERTAS": 3, "ARQUITETURA": 2, "DECISOES": 3,
62
63
  "CONTEXTO DE TASKS ANTERIORES": 2, "GRAPH": 2, "PRODUTO": 1,
63
64
  "DISCOVERIES": 2, "UTILITIES": 3, "PATTERNS": 2, "HINTS": 2, "STACK": 2,
64
65
  },
65
66
  frontend: {
66
- "STANDARDS": 3, "ALERTAS": 3, "ARQUITETURA": 2, "DECISOES": 3,
67
+ "STANDARDS": 3, "REFERENCIAS": 3, "ALERTAS": 3, "ARQUITETURA": 2, "DECISOES": 3,
67
68
  "CONTEXTO DE TASKS ANTERIORES": 2, "GRAPH": 2, "PRODUTO": 3,
68
69
  "DISCOVERIES": 2, "UTILITIES": 3, "PATTERNS": 3, "HINTS": 2, "STACK": 2,
69
70
  },
70
71
  database: {
71
- "STANDARDS": 3, "ALERTAS": 3, "ARQUITETURA": 3, "DECISOES": 3,
72
+ "STANDARDS": 3, "REFERENCIAS": 3, "ALERTAS": 3, "ARQUITETURA": 3, "DECISOES": 3,
72
73
  "CONTEXTO DE TASKS ANTERIORES": 2, "GRAPH": 2, "PRODUTO": 0,
73
74
  "DISCOVERIES": 2, "UTILITIES": 1, "PATTERNS": 2, "HINTS": 2, "STACK": 3,
74
75
  },
75
76
  testing: {
76
- "STANDARDS": 3, "ALERTAS": 3, "ARQUITETURA": 1, "DECISOES": 2,
77
+ "STANDARDS": 3, "REFERENCIAS": 3, "ALERTAS": 3, "ARQUITETURA": 1, "DECISOES": 2,
77
78
  "CONTEXTO DE TASKS ANTERIORES": 3, "GRAPH": 1, "PRODUTO": 0,
78
79
  "DISCOVERIES": 2, "UTILITIES": 3, "PATTERNS": 3, "HINTS": 2, "STACK": 1,
79
80
  },
80
81
  review: {
81
- "STANDARDS": 3, "ALERTAS": 3, "ARQUITETURA": 3, "DECISOES": 3,
82
+ "STANDARDS": 3, "REFERENCIAS": 1, "ALERTAS": 3, "ARQUITETURA": 3, "DECISOES": 3,
82
83
  "CONTEXTO DE TASKS ANTERIORES": 2, "GRAPH": 2, "PRODUTO": 1,
83
84
  "DISCOVERIES": 2, "UTILITIES": 3, "PATTERNS": 2, "HINTS": 3, "STACK": 2,
84
85
  },
85
86
  security: {
86
- "STANDARDS": 3, "ALERTAS": 3, "ARQUITETURA": 2, "DECISOES": 2,
87
+ "STANDARDS": 3, "REFERENCIAS": 0, "ALERTAS": 3, "ARQUITETURA": 2, "DECISOES": 2,
87
88
  "CONTEXTO DE TASKS ANTERIORES": 1, "GRAPH": 1, "PRODUTO": 0,
88
89
  "DISCOVERIES": 2, "UTILITIES": 1, "PATTERNS": 1, "HINTS": 2, "STACK": 3,
89
90
  },
90
91
  explore: {
91
- "STANDARDS": 0, "ALERTAS": 1, "ARQUITETURA": 3, "DECISOES": 1,
92
+ "STANDARDS": 0, "REFERENCIAS": 0, "ALERTAS": 1, "ARQUITETURA": 3, "DECISOES": 1,
92
93
  "CONTEXTO DE TASKS ANTERIORES": 0, "GRAPH": 0, "PRODUTO": 0,
93
94
  "DISCOVERIES": 1, "UTILITIES": 0, "PATTERNS": 0, "HINTS": 0, "STACK": 3,
94
95
  },
95
96
  architecture: {
96
- "STANDARDS": 2, "ALERTAS": 2, "ARQUITETURA": 3, "DECISOES": 3,
97
+ "STANDARDS": 2, "REFERENCIAS": 0, "ALERTAS": 2, "ARQUITETURA": 3, "DECISOES": 3,
97
98
  "CONTEXTO DE TASKS ANTERIORES": 2, "GRAPH": 2, "PRODUTO": 3,
98
99
  "DISCOVERIES": 2, "UTILITIES": 1, "PATTERNS": 2, "HINTS": 1, "STACK": 3,
99
100
  },
@@ -18,6 +18,7 @@ import {
18
18
  buildGraphSection,
19
19
  buildStackSection,
20
20
  buildHintsSection,
21
+ buildReferencesSection,
21
22
  } from "./sections";
22
23
 
23
24
  // v9.0: Contexto minimo para subagent (max ~2KB)
@@ -253,6 +254,7 @@ export function getContextForSubagent(taskId: number): string {
253
254
  buildProductSection(data),
254
255
  buildArchitectureSection(data),
255
256
  buildStandardsSection(data),
257
+ buildReferencesSection(data),
256
258
  buildDecisionsSection(data),
257
259
  buildReasoningSection(data),
258
260
  buildAlertsSection(data),
package/context/index.ts CHANGED
@@ -18,4 +18,7 @@ export {
18
18
  buildGraphSection,
19
19
  buildStackSection,
20
20
  buildHintsSection,
21
+ buildReferencesSection,
21
22
  } from "./sections";
23
+ export { findReferenceFiles } from "./references";
24
+ export type { ReferenceFile } from "./references";
@@ -0,0 +1,159 @@
1
+ import { describe, it, expect, beforeAll, afterAll } from "bun:test";
2
+ import { join } from "path";
3
+ import { mkdirSync, rmSync, writeFileSync } from "fs";
4
+ import { findReferenceFiles } from "./references";
5
+
6
+ // ── Test fixtures ────────────────────────────────────────────
7
+
8
+ const TMP_DIR = join(import.meta.dir, "__test_refs__");
9
+
10
+ function ensureDir(dir: string) {
11
+ mkdirSync(dir, { recursive: true });
12
+ }
13
+
14
+ function writeTmpFile(relativePath: string, content: string): string {
15
+ const full = join(TMP_DIR, relativePath);
16
+ ensureDir(join(full, ".."));
17
+ writeFileSync(full, content);
18
+ return relativePath;
19
+ }
20
+
21
+ beforeAll(() => {
22
+ ensureDir(TMP_DIR);
23
+
24
+ // src/routes/ — 3 route files of different sizes
25
+ writeTmpFile("src/routes/users.ts", "export function getUsers() { return []; }\nexport function createUser() { return {}; }\n// more code here to make it larger\n".repeat(5));
26
+ writeTmpFile("src/routes/products.ts", "export function getProducts() { return []; }\n");
27
+ writeTmpFile("src/routes/orders.ts", "export function getOrders() { return []; }\nexport function createOrder() { return {}; }\n");
28
+
29
+ // src/services/ — 2 service files
30
+ writeTmpFile("src/services/auth.service.ts", "export class AuthService { login() {} logout() {} verify() {} }\n".repeat(3));
31
+ writeTmpFile("src/services/user.service.ts", "export class UserService { getById() {} }\n");
32
+
33
+ // src/components/ — React components
34
+ writeTmpFile("src/components/Button.tsx", "export function Button() { return <button/>; }\n");
35
+ writeTmpFile("src/components/Card.tsx", "export function Card() { return <div/>; }\nexport function CardHeader() { return <div/>; }\n".repeat(3));
36
+
37
+ // src/modules/users/ and src/modules/payments/ — parallel structure
38
+ writeTmpFile("src/modules/users/route.ts", "export function usersRoute() { return {}; }\n".repeat(4));
39
+ writeTmpFile("src/modules/users/service.ts", "export function usersService() {}\n");
40
+ writeTmpFile("src/modules/payments/service.ts", "export function paymentsService() {}\n");
41
+
42
+ // tests/ — test files
43
+ writeTmpFile("tests/routes/users.test.ts", "describe('users', () => { it('works', () => {}); });\n".repeat(2));
44
+
45
+ // node_modules/ — should be ignored
46
+ writeTmpFile("node_modules/pkg/index.ts", "export const x = 1;\n");
47
+
48
+ // Non-code file
49
+ writeTmpFile("docs/readme.md", "# Readme\n");
50
+ });
51
+
52
+ afterAll(() => {
53
+ rmSync(TMP_DIR, { recursive: true, force: true });
54
+ });
55
+
56
+ // ── Tests ────────────────────────────────────────────────────
57
+
58
+ describe("findReferenceFiles", () => {
59
+ it("finds siblings in the same directory", () => {
60
+ // Target: new file in src/routes/ — should find existing routes
61
+ const refs = findReferenceFiles(["src/routes/payments.ts"], TMP_DIR);
62
+
63
+ expect(refs.length).toBeGreaterThanOrEqual(1);
64
+ expect(refs[0].reason).toBe("mesmo diretorio");
65
+ // Should pick the largest sibling (users.ts has the most content)
66
+ expect(refs[0].path).toBe("src/routes/users.ts");
67
+ });
68
+
69
+ it("prioritizes largest file as reference", () => {
70
+ const refs = findReferenceFiles(["src/components/Modal.tsx"], TMP_DIR);
71
+
72
+ expect(refs.length).toBe(1);
73
+ // Card.tsx is larger than Button.tsx
74
+ expect(refs[0].path).toBe("src/components/Card.tsx");
75
+ });
76
+
77
+ it("finds namesakes when no siblings exist", () => {
78
+ // Target: src/modules/payments/route.ts — no siblings, but src/modules/users/route.ts exists
79
+ const refs = findReferenceFiles(["src/modules/payments/route.ts"], TMP_DIR);
80
+
81
+ expect(refs.length).toBeGreaterThanOrEqual(1);
82
+ const paths = refs.map(r => r.path);
83
+ // Should find the namesake route.ts or a sibling service.ts
84
+ expect(
85
+ paths.some(p => p.includes("route.ts") || p.includes("service.ts"))
86
+ ).toBe(true);
87
+ });
88
+
89
+ it("returns empty for non-code files", () => {
90
+ const refs = findReferenceFiles(["docs/notes.md"], TMP_DIR);
91
+ expect(refs).toEqual([]);
92
+ });
93
+
94
+ it("returns empty for empty task files", () => {
95
+ expect(findReferenceFiles([], TMP_DIR)).toEqual([]);
96
+ });
97
+
98
+ it("returns empty for null/undefined", () => {
99
+ expect(findReferenceFiles(null as any, TMP_DIR)).toEqual([]);
100
+ expect(findReferenceFiles(undefined as any, TMP_DIR)).toEqual([]);
101
+ });
102
+
103
+ it("ignores node_modules", () => {
104
+ const refs = findReferenceFiles(["node_modules/pkg/new.ts"], TMP_DIR);
105
+ // Even if node_modules has .ts files, targets in ignored dirs get no refs
106
+ // (the target itself is filtered by extension check, not by ignored dir)
107
+ // But results should never point INTO node_modules
108
+ for (const ref of refs) {
109
+ expect(ref.path).not.toContain("node_modules");
110
+ }
111
+ });
112
+
113
+ it("limits to 3 references max", () => {
114
+ const refs = findReferenceFiles([
115
+ "src/routes/payments.ts",
116
+ "src/services/payment.service.ts",
117
+ "src/components/Modal.tsx",
118
+ "tests/routes/products.test.ts",
119
+ ], TMP_DIR);
120
+
121
+ expect(refs.length).toBeLessThanOrEqual(3);
122
+ });
123
+
124
+ it("deduplicates references", () => {
125
+ const refs = findReferenceFiles([
126
+ "src/routes/payments.ts",
127
+ "src/routes/invoices.ts",
128
+ ], TMP_DIR);
129
+
130
+ const paths = refs.map(r => r.path);
131
+ const unique = new Set(paths);
132
+ expect(paths.length).toBe(unique.size);
133
+ });
134
+
135
+ it("handles Windows-style backslash paths", () => {
136
+ const refs = findReferenceFiles(["src\\routes\\payments.ts"], TMP_DIR);
137
+ expect(refs.length).toBeGreaterThanOrEqual(1);
138
+ // All returned paths should use forward slashes
139
+ for (const ref of refs) {
140
+ expect(ref.path).not.toContain("\\");
141
+ }
142
+ });
143
+
144
+ it("finds reference for test files", () => {
145
+ const refs = findReferenceFiles(["tests/routes/products.test.ts"], TMP_DIR);
146
+ expect(refs.length).toBeGreaterThanOrEqual(1);
147
+ expect(refs[0].path).toContain("users.test.ts");
148
+ });
149
+
150
+ it("uses parent directory as fallback", () => {
151
+ // Target in a new subdirectory with no siblings or namesakes
152
+ writeTmpFile("src/features/billing/handler.ts", "export function handle() {}\n");
153
+ const refs = findReferenceFiles(["src/features/billing/processor.ts"], TMP_DIR);
154
+ // Should find handler.ts as sibling
155
+ if (refs.length > 0) {
156
+ expect(refs[0].path).toContain("billing");
157
+ }
158
+ });
159
+ });
@@ -0,0 +1,159 @@
1
+ import { join, dirname, basename, extname, resolve, relative } from "path";
2
+ import { globSync } from "fs";
3
+
4
+ // ═══════════════════════════════════════════════════════════════
5
+ // REFERENCE FILES — Pattern by Example (v9.5)
6
+ //
7
+ // Finds existing files similar to task targets so subagents can
8
+ // read them and replicate the coding style exactly.
9
+ // ═══════════════════════════════════════════════════════════════
10
+
11
+ export interface ReferenceFile {
12
+ path: string;
13
+ reason: string;
14
+ }
15
+
16
+ const IGNORED_DIRS = new Set([
17
+ "node_modules", ".git", "dist", "build", ".next", ".codexa",
18
+ ".nuxt", ".output", "coverage", "__pycache__", ".venv", "vendor",
19
+ "target", "bin", "obj",
20
+ ]);
21
+
22
+ const CODE_EXTENSIONS = new Set([
23
+ ".ts", ".tsx", ".js", ".jsx", ".vue", ".svelte",
24
+ ".go", ".rs", ".py", ".cs", ".kt", ".java",
25
+ ".dart", ".php", ".rb", ".swift",
26
+ ]);
27
+
28
+ function normalizePath(p: string): string {
29
+ return p.replace(/\\/g, "/");
30
+ }
31
+
32
+ function isIgnored(filePath: string): boolean {
33
+ const parts = normalizePath(filePath).split("/");
34
+ return parts.some(part => IGNORED_DIRS.has(part));
35
+ }
36
+
37
+ function getFileSize(filePath: string): number {
38
+ try {
39
+ return Bun.file(filePath).size;
40
+ } catch {
41
+ return 0;
42
+ }
43
+ }
44
+
45
+ function fileExists(filePath: string): boolean {
46
+ try {
47
+ return Bun.file(filePath).size > 0;
48
+ } catch {
49
+ return false;
50
+ }
51
+ }
52
+
53
+ function globFiles(pattern: string, cwd: string): string[] {
54
+ try {
55
+ const glob = new Bun.Glob(pattern);
56
+ const results: string[] = [];
57
+ for (const match of glob.scanSync({ cwd, dot: false })) {
58
+ const full = join(cwd, match);
59
+ if (!isIgnored(full)) {
60
+ results.push(normalizePath(full));
61
+ }
62
+ }
63
+ return results;
64
+ } catch {
65
+ return [];
66
+ }
67
+ }
68
+
69
+ function pickLargest(files: string[]): string | null {
70
+ if (files.length === 0) return null;
71
+
72
+ let best = files[0];
73
+ let bestSize = getFileSize(files[0]);
74
+
75
+ for (let i = 1; i < files.length; i++) {
76
+ const size = getFileSize(files[i]);
77
+ if (size > bestSize) {
78
+ best = files[i];
79
+ bestSize = size;
80
+ }
81
+ }
82
+
83
+ return bestSize > 0 ? best : null;
84
+ }
85
+
86
+ /**
87
+ * Find reference files for a set of task target files.
88
+ *
89
+ * Strategy per target file:
90
+ * 1. Siblings — other files in the same directory with same extension
91
+ * 2. Namesakes — files with same basename in other directories
92
+ * 3. Parent — files with same extension in parent directory tree
93
+ *
94
+ * Returns max 3 deduplicated reference file paths.
95
+ */
96
+ export function findReferenceFiles(
97
+ taskFiles: string[],
98
+ projectRoot: string,
99
+ ): ReferenceFile[] {
100
+ if (!taskFiles || taskFiles.length === 0) return [];
101
+
102
+ const seen = new Set<string>();
103
+ const results: ReferenceFile[] = [];
104
+ const normalizedRoot = normalizePath(resolve(projectRoot));
105
+
106
+ for (const rawTarget of taskFiles) {
107
+ if (results.length >= 3) break;
108
+
109
+ const target = normalizePath(resolve(projectRoot, rawTarget));
110
+ const ext = extname(target);
111
+ const base = basename(target);
112
+ const dir = dirname(target);
113
+
114
+ if (!ext || !CODE_EXTENSIONS.has(ext)) continue;
115
+
116
+ // Strategy 1: Siblings (same directory, same extension)
117
+ const siblings = globFiles(`*${ext}`, dir)
118
+ .filter(f => f !== target && !seen.has(f) && fileExists(f));
119
+
120
+ const bestSibling = pickLargest(siblings);
121
+ if (bestSibling) {
122
+ const rel = normalizePath(relative(normalizedRoot, bestSibling));
123
+ seen.add(bestSibling);
124
+ results.push({ path: rel, reason: "mesmo diretorio" });
125
+ continue;
126
+ }
127
+
128
+ // Strategy 2: Namesakes (same filename in other directories)
129
+ const namesakes = globFiles(`**/${base}`, normalizedRoot)
130
+ .filter(f => f !== target && !seen.has(f) && fileExists(f));
131
+
132
+ if (namesakes.length > 0) {
133
+ // Pick the one closest by path depth similarity
134
+ const bestNamesake = pickLargest(namesakes);
135
+ if (bestNamesake) {
136
+ const rel = normalizePath(relative(normalizedRoot, bestNamesake));
137
+ seen.add(bestNamesake);
138
+ results.push({ path: rel, reason: "mesmo tipo de arquivo" });
139
+ continue;
140
+ }
141
+ }
142
+
143
+ // Strategy 3: Parent directory search (same extension, one level up)
144
+ const parentDir = dirname(dir);
145
+ if (parentDir !== dir) {
146
+ const parentFiles = globFiles(`**/*${ext}`, parentDir)
147
+ .filter(f => f !== target && !seen.has(f) && fileExists(f));
148
+
149
+ const bestParent = pickLargest(parentFiles);
150
+ if (bestParent) {
151
+ const rel = normalizePath(relative(normalizedRoot, bestParent));
152
+ seen.add(bestParent);
153
+ results.push({ path: rel, reason: "arquivo similar proximo" });
154
+ }
155
+ }
156
+ }
157
+
158
+ return results;
159
+ }
@@ -1,6 +1,7 @@
1
1
  import { getUtilitiesForContext, getAgentHints } from "../db/schema";
2
2
  import type { ContextSection, ContextData } from "./assembly";
3
3
  import { getAgentDomain, domainToScope } from "./domains";
4
+ import { findReferenceFiles } from "./references";
4
5
 
5
6
  // ── Section Builders ──────────────────────────────────────────
6
7
 
@@ -245,3 +246,18 @@ ${hints.map(h => `- ${h}`).join("\n")}
245
246
  `;
246
247
  return { name: "HINTS", content, priority: 10 };
247
248
  }
249
+
250
+ export function buildReferencesSection(data: ContextData): ContextSection | null {
251
+ if (data.taskFiles.length === 0) return null;
252
+
253
+ const projectRoot = process.cwd();
254
+ const refs = findReferenceFiles(data.taskFiles, projectRoot);
255
+ if (refs.length === 0) return null;
256
+
257
+ const content = `
258
+ ### REFERENCIA DE ESTILO (${refs.length})
259
+ **ANTES de criar/modificar arquivos, leia estas referencias e replique o mesmo estilo** (nomenclatura, estrutura, imports, error handling):
260
+ ${refs.map(r => `- \`${r.path}\` (${r.reason})`).join("\n")}
261
+ `;
262
+ return { name: "REFERENCIAS", content, priority: 2 };
263
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codexa/cli",
3
- "version": "9.0.8",
3
+ "version": "9.0.9",
4
4
  "description": "Orchestrated workflow system for Claude Code - manages feature development through parallel subagents with structured phases, gates, and quality enforcement.",
5
5
  "type": "module",
6
6
  "bin": {