@codexa/cli 9.0.9 → 9.0.11
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/commands/discover.ts +38 -11
- package/commands/patterns.ts +29 -2
- package/commands/sync.ts +12 -1
- package/commands/team.test.ts +253 -0
- package/commands/team.ts +703 -0
- package/db/schema.ts +7 -0
- package/detectors/go.ts +55 -1
- package/detectors/node.ts +39 -1
- package/gates/standards-validator.ts +3 -2
- package/package.json +1 -1
- package/workflow.ts +43 -0
package/db/schema.ts
CHANGED
|
@@ -480,6 +480,13 @@ const MIGRATIONS: Migration[] = [
|
|
|
480
480
|
db.exec(`ALTER TABLE project ADD COLUMN typecheck_command TEXT`);
|
|
481
481
|
},
|
|
482
482
|
},
|
|
483
|
+
{
|
|
484
|
+
version: "9.8.0",
|
|
485
|
+
description: "Adicionar grepai_workspace na tabela project para suporte a workspace cross-project",
|
|
486
|
+
up: (db) => {
|
|
487
|
+
db.exec(`ALTER TABLE project ADD COLUMN grepai_workspace TEXT`);
|
|
488
|
+
},
|
|
489
|
+
},
|
|
483
490
|
];
|
|
484
491
|
|
|
485
492
|
export function runMigrations(): void {
|
package/detectors/go.ts
CHANGED
|
@@ -55,6 +55,37 @@ function parseGoMod(content: string): GoMod {
|
|
|
55
55
|
return result;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
interface GoWork {
|
|
59
|
+
goVersion?: string;
|
|
60
|
+
uses: string[];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function parseGoWork(content: string): GoWork {
|
|
64
|
+
const result: GoWork = { uses: [] };
|
|
65
|
+
|
|
66
|
+
const goMatch = content.match(/^go\s+(\d+\.\d+(?:\.\d+)?)$/m);
|
|
67
|
+
if (goMatch) result.goVersion = goMatch[1];
|
|
68
|
+
|
|
69
|
+
// Parse use block: use ( ./path1 \n ./path2 )
|
|
70
|
+
const useBlockMatch = content.match(/use\s*\(([\s\S]*?)\)/);
|
|
71
|
+
if (useBlockMatch) {
|
|
72
|
+
for (const line of useBlockMatch[1].split("\n")) {
|
|
73
|
+
const trimmed = line.trim();
|
|
74
|
+
if (trimmed && !trimmed.startsWith("//")) {
|
|
75
|
+
result.uses.push(trimmed);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Parse single-line: use ./path
|
|
81
|
+
const singleUses = content.matchAll(/^use\s+(\S+)\s*$/gm);
|
|
82
|
+
for (const match of singleUses) {
|
|
83
|
+
result.uses.push(match[1].trim());
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
|
|
58
89
|
const goDetector: Detector = {
|
|
59
90
|
name: "go",
|
|
60
91
|
ecosystem: "go",
|
|
@@ -117,12 +148,35 @@ const goDetector: Detector = {
|
|
|
117
148
|
category: "runtime",
|
|
118
149
|
});
|
|
119
150
|
|
|
120
|
-
// Create dependency lookup
|
|
151
|
+
// Create dependency lookup from root go.mod
|
|
121
152
|
const deps = new Map<string, string>();
|
|
122
153
|
for (const req of goMod.require) {
|
|
123
154
|
deps.set(req.path, req.version);
|
|
124
155
|
}
|
|
125
156
|
|
|
157
|
+
// Merge workspace module dependencies from go.work
|
|
158
|
+
const goWorkPath = join(cwd, "go.work");
|
|
159
|
+
if (fileExists(goWorkPath)) {
|
|
160
|
+
const goWorkContent = readText(goWorkPath);
|
|
161
|
+
if (goWorkContent) {
|
|
162
|
+
const goWork = parseGoWork(goWorkContent);
|
|
163
|
+
for (const usePath of goWork.uses) {
|
|
164
|
+
const wsModPath = join(cwd, usePath, "go.mod");
|
|
165
|
+
if (fileExists(wsModPath)) {
|
|
166
|
+
const wsContent = readText(wsModPath);
|
|
167
|
+
if (wsContent) {
|
|
168
|
+
const wsMod = parseGoMod(wsContent);
|
|
169
|
+
for (const req of wsMod.require) {
|
|
170
|
+
if (!deps.has(req.path)) {
|
|
171
|
+
deps.set(req.path, req.version);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
126
180
|
// Web Framework Detection
|
|
127
181
|
const webFrameworks = [
|
|
128
182
|
{ paths: ["github.com/gin-gonic/gin"], name: "Gin", confidence: 1.0 },
|
package/detectors/node.ts
CHANGED
|
@@ -22,6 +22,32 @@ import {
|
|
|
22
22
|
readText,
|
|
23
23
|
} from "./index";
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Resolve workspace glob patterns from package.json workspaces or pnpm-workspace.yaml.
|
|
27
|
+
* Returns array of glob patterns (e.g. ["apps/*", "packages/*"]).
|
|
28
|
+
*/
|
|
29
|
+
function resolveWorkspacePatterns(cwd: string, pkg: PackageJson): string[] {
|
|
30
|
+
// npm/yarn: workspaces as array or { packages: [] }
|
|
31
|
+
if (pkg.workspaces) {
|
|
32
|
+
if (Array.isArray(pkg.workspaces)) return pkg.workspaces;
|
|
33
|
+
if (pkg.workspaces.packages) return pkg.workspaces.packages;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// pnpm: pnpm-workspace.yaml
|
|
37
|
+
const pnpmPath = join(cwd, "pnpm-workspace.yaml");
|
|
38
|
+
const content = readText(pnpmPath);
|
|
39
|
+
if (content) {
|
|
40
|
+
const patterns: string[] = [];
|
|
41
|
+
for (const line of content.split("\n")) {
|
|
42
|
+
const match = line.match(/^\s*-\s*['"]?([^'"#]+)['"]?\s*$/);
|
|
43
|
+
if (match) patterns.push(match[1].trim());
|
|
44
|
+
}
|
|
45
|
+
return patterns;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
|
|
25
51
|
interface PackageJson {
|
|
26
52
|
name?: string;
|
|
27
53
|
version?: string;
|
|
@@ -93,12 +119,24 @@ const nodeDetector: Detector = {
|
|
|
93
119
|
const pkg: PackageJson | null = readJson(pkgPath);
|
|
94
120
|
if (!pkg) return null;
|
|
95
121
|
|
|
96
|
-
const allDeps = {
|
|
122
|
+
const allDeps: Record<string, string> = {
|
|
97
123
|
...pkg.dependencies,
|
|
98
124
|
...pkg.devDependencies,
|
|
99
125
|
...pkg.peerDependencies,
|
|
100
126
|
};
|
|
101
127
|
|
|
128
|
+
// Merge workspace package dependencies
|
|
129
|
+
const workspacePatterns = resolveWorkspacePatterns(cwd, pkg);
|
|
130
|
+
for (const pattern of workspacePatterns) {
|
|
131
|
+
const pkgFiles = findFiles(cwd, `${pattern}/package.json`);
|
|
132
|
+
for (const relPath of pkgFiles) {
|
|
133
|
+
const wsPkg: PackageJson | null = readJson(join(cwd, relPath));
|
|
134
|
+
if (wsPkg) {
|
|
135
|
+
Object.assign(allDeps, wsPkg.dependencies, wsPkg.devDependencies);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
102
140
|
// Detect package manager from lock files
|
|
103
141
|
if (fileExists(join(cwd, "bun.lockb"))) {
|
|
104
142
|
technologies.push({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getDb } from "../db/connection";
|
|
2
2
|
import { existsSync, readFileSync } from "fs";
|
|
3
3
|
import { basename, resolve } from "path";
|
|
4
|
-
import { isGrepaiAvailable, searchWithGrepai, type GrepaiResult } from "../commands/patterns";
|
|
4
|
+
import { isGrepaiAvailable, searchWithGrepai, getGrepaiWorkspace, type GrepaiResult } from "../commands/patterns";
|
|
5
5
|
|
|
6
6
|
// ═══════════════════════════════════════════════════════════════
|
|
7
7
|
// INTERFACES
|
|
@@ -119,10 +119,11 @@ function validateSemantic(
|
|
|
119
119
|
violations: Violation[],
|
|
120
120
|
warnings: Violation[]
|
|
121
121
|
): void {
|
|
122
|
+
const workspace = getGrepaiWorkspace() ?? undefined;
|
|
122
123
|
for (const std of standards) {
|
|
123
124
|
if (!std.semantic_query) continue;
|
|
124
125
|
|
|
125
|
-
const results = searchWithGrepai(std.semantic_query, 20);
|
|
126
|
+
const results = searchWithGrepai(std.semantic_query, 20, workspace);
|
|
126
127
|
|
|
127
128
|
// Filtrar: apenas arquivos sendo validados + score acima do threshold
|
|
128
129
|
const matchingFiles = results.filter(r => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codexa/cli",
|
|
3
|
-
"version": "9.0.
|
|
3
|
+
"version": "9.0.11",
|
|
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": {
|
package/workflow.ts
CHANGED
|
@@ -23,7 +23,9 @@ import {
|
|
|
23
23
|
discoverRefreshPatterns,
|
|
24
24
|
discoverExportPatterns,
|
|
25
25
|
discoverIncremental,
|
|
26
|
+
ensureDeepExploreAgent,
|
|
26
27
|
} from "./commands/discover";
|
|
28
|
+
import { isValidWorkspaceName } from "./commands/patterns";
|
|
27
29
|
import { clearTasks, clearShow } from "./commands/clear";
|
|
28
30
|
import { standardsList, standardsAdd, standardsEdit, standardsRemove, standardsExport } from "./commands/standards";
|
|
29
31
|
import { productImport, productSet, productConfirm, productShow, productReset } from "./commands/product";
|
|
@@ -38,6 +40,7 @@ import {
|
|
|
38
40
|
architectExport,
|
|
39
41
|
architectCancel,
|
|
40
42
|
} from "./commands/architect";
|
|
43
|
+
import { teamSuggest } from "./commands/team";
|
|
41
44
|
import { initSchema } from "./db/schema";
|
|
42
45
|
import { getDb, closeDb } from "./db/connection";
|
|
43
46
|
import { execSync } from "child_process";
|
|
@@ -553,6 +556,7 @@ discoverCmd
|
|
|
553
556
|
.option("--auth <value>", "Auth (supabase, next-auth, clerk)")
|
|
554
557
|
.option("--testing <value>", "Testing (vitest, jest, playwright)")
|
|
555
558
|
.option("--typecheck-command <cmd>", "Comando custom de typecheck (ex: 'mypy --strict', 'go vet ./...'). Vazio para usar preset automatico.")
|
|
559
|
+
.option("--grepai-workspace <name>", "Nome do workspace grepai para busca semantica cross-project. Vazio para remover.")
|
|
556
560
|
.action((options) => {
|
|
557
561
|
// Tratar typecheck-command separadamente
|
|
558
562
|
if (options.typecheckCommand !== undefined) {
|
|
@@ -569,9 +573,32 @@ discoverCmd
|
|
|
569
573
|
}
|
|
570
574
|
console.log(" Sera usado no gate 4.5 (typecheck-pass) em cada task done.\n");
|
|
571
575
|
}
|
|
576
|
+
// Tratar grepai-workspace separadamente
|
|
577
|
+
if (options.grepaiWorkspace !== undefined) {
|
|
578
|
+
const { initSchema } = require("./db/schema");
|
|
579
|
+
const { getDb } = require("./db/connection");
|
|
580
|
+
initSchema();
|
|
581
|
+
const db = getDb();
|
|
582
|
+
const value = options.grepaiWorkspace === "" ? null : options.grepaiWorkspace;
|
|
583
|
+
if (value && !isValidWorkspaceName(value)) {
|
|
584
|
+
console.error(`\n[erro] Nome de workspace invalido: "${value}"`);
|
|
585
|
+
console.error(" Use apenas letras, numeros, hifens e underscores (ex: meu-workspace, dotnet_ws)\n");
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
db.run("UPDATE project SET grepai_workspace = ? WHERE id = 'default'", [value]);
|
|
589
|
+
if (value) {
|
|
590
|
+
console.log(`\n✓ Grepai workspace configurado: ${value}`);
|
|
591
|
+
console.log(" Sera usado em: semantic search (standards), deep-explore agent, grepai trace");
|
|
592
|
+
} else {
|
|
593
|
+
console.log(`\n✓ Grepai workspace removido (usando index local .grepai/)`);
|
|
594
|
+
}
|
|
595
|
+
// Auto-regenerate deep-explore agent with new workspace config
|
|
596
|
+
ensureDeepExploreAgent();
|
|
597
|
+
}
|
|
572
598
|
// Tratar stack options normalmente
|
|
573
599
|
const stackOptions = { ...options };
|
|
574
600
|
delete stackOptions.typecheckCommand;
|
|
601
|
+
delete stackOptions.grepaiWorkspace;
|
|
575
602
|
if (Object.keys(stackOptions).length > 0) {
|
|
576
603
|
discoverSetStack(stackOptions);
|
|
577
604
|
}
|
|
@@ -961,6 +988,22 @@ architectCmd
|
|
|
961
988
|
architectCancel(options);
|
|
962
989
|
});
|
|
963
990
|
|
|
991
|
+
// ═══════════════════════════════════════════════════════════════
|
|
992
|
+
// AGENT TEAMS (Experimental)
|
|
993
|
+
// ═══════════════════════════════════════════════════════════════
|
|
994
|
+
|
|
995
|
+
const teamCmd = program.command("team").description("Comandos de Agent Teams (experimental)");
|
|
996
|
+
|
|
997
|
+
teamCmd
|
|
998
|
+
.command("suggest")
|
|
999
|
+
.description("Sugere modo de execucao (team vs subagent) para a fase atual")
|
|
1000
|
+
.option("--json", "Saida em JSON")
|
|
1001
|
+
.option("--phase <phase>", "Fase especifica (imp, rev, architect)")
|
|
1002
|
+
.option("--spec <id>", "ID do spec (padrao: mais recente)")
|
|
1003
|
+
.action(wrapAction((options) => {
|
|
1004
|
+
teamSuggest(options);
|
|
1005
|
+
}));
|
|
1006
|
+
|
|
964
1007
|
// ═══════════════════════════════════════════════════════════════
|
|
965
1008
|
// PLUGIN
|
|
966
1009
|
// ═══════════════════════════════════════════════════════════════
|