@codexa/cli 9.0.31 → 9.0.32
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/architect.ts +52 -87
- package/commands/check.ts +22 -23
- package/commands/clear.ts +42 -48
- package/commands/decide.ts +46 -44
- package/commands/discover.ts +81 -94
- package/commands/integration.test.ts +262 -313
- package/commands/knowledge.test.ts +56 -61
- package/commands/knowledge.ts +126 -131
- package/commands/patterns.ts +28 -43
- package/commands/plan.ts +50 -48
- package/commands/product.ts +57 -59
- package/commands/research.ts +64 -77
- package/commands/review.ts +100 -86
- package/commands/simplify.ts +24 -35
- package/commands/spec-resolver.test.ts +52 -48
- package/commands/spec-resolver.ts +21 -23
- package/commands/standards.ts +20 -27
- package/commands/sync.ts +2 -8
- package/commands/task.ts +106 -97
- package/commands/team.test.ts +22 -83
- package/commands/team.ts +62 -50
- package/commands/utils.ts +83 -81
- package/context/assembly.ts +0 -1
- package/context/generator.ts +66 -79
- package/context/sections.ts +8 -14
- package/db/connection.ts +195 -19
- package/db/schema.test.ts +288 -299
- package/db/schema.ts +297 -394
- package/db/test-helpers.ts +18 -29
- package/gates/standards-validator.test.ts +83 -86
- package/gates/standards-validator.ts +9 -41
- package/gates/validator.test.ts +13 -22
- package/gates/validator.ts +69 -107
- package/package.json +2 -1
- package/protocol/process-return.ts +41 -57
- package/simplify/prompt-builder.test.ts +44 -42
- package/simplify/prompt-builder.ts +12 -14
- package/workflow.ts +159 -174
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { initSchema } from "../db/schema";
|
|
1
|
+
import { dbGet, dbAll } from "../db/connection";
|
|
3
2
|
import { CodexaError } from "../errors";
|
|
4
3
|
|
|
5
4
|
export interface ResolvedSpec {
|
|
@@ -18,15 +17,14 @@ export interface ResolvedSpec {
|
|
|
18
17
|
* - Se nao fornecido: busca o mais recente ativo (ORDER BY created_at DESC LIMIT 1)
|
|
19
18
|
* - Se requiredPhases: valida que spec.phase esta na lista
|
|
20
19
|
*/
|
|
21
|
-
export function resolveSpec(specId?: string, requiredPhases?: string[]): ResolvedSpec {
|
|
22
|
-
const db = getDb();
|
|
23
|
-
|
|
20
|
+
export async function resolveSpec(specId?: string, requiredPhases?: string[]): Promise<ResolvedSpec> {
|
|
24
21
|
let spec: any;
|
|
25
22
|
|
|
26
23
|
if (specId) {
|
|
27
|
-
spec =
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
spec = await dbGet<any>(
|
|
25
|
+
"SELECT * FROM specs WHERE id = ?",
|
|
26
|
+
[specId]
|
|
27
|
+
);
|
|
30
28
|
|
|
31
29
|
if (!spec) {
|
|
32
30
|
throw new CodexaError(`Spec '${specId}' nao encontrado.`);
|
|
@@ -36,9 +34,10 @@ export function resolveSpec(specId?: string, requiredPhases?: string[]): Resolve
|
|
|
36
34
|
throw new CodexaError(`Spec '${specId}' ja esta ${spec.phase}.`);
|
|
37
35
|
}
|
|
38
36
|
} else {
|
|
39
|
-
spec =
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
spec = await dbGet<any>(
|
|
38
|
+
"SELECT * FROM specs WHERE phase NOT IN ('completed', 'cancelled') ORDER BY created_at DESC LIMIT 1",
|
|
39
|
+
[]
|
|
40
|
+
);
|
|
42
41
|
|
|
43
42
|
if (!spec) {
|
|
44
43
|
throw new CodexaError("Nenhuma feature ativa.");
|
|
@@ -58,19 +57,18 @@ export function resolveSpec(specId?: string, requiredPhases?: string[]): Resolve
|
|
|
58
57
|
* Versao silenciosa de resolveSpec que retorna null em vez de process.exit(1).
|
|
59
58
|
* Util para comandos que tem tratamento especial (ex: json output, throw customizado).
|
|
60
59
|
*/
|
|
61
|
-
export function resolveSpecOrNull(specId?: string, requiredPhases?: string[]): ResolvedSpec | null {
|
|
62
|
-
const db = getDb();
|
|
63
|
-
|
|
60
|
+
export async function resolveSpecOrNull(specId?: string, requiredPhases?: string[]): Promise<ResolvedSpec | null> {
|
|
64
61
|
let spec: any;
|
|
65
62
|
|
|
66
63
|
if (specId) {
|
|
67
|
-
spec =
|
|
64
|
+
spec = await dbGet<any>("SELECT * FROM specs WHERE id = ?", [specId]);
|
|
68
65
|
if (!spec) return null;
|
|
69
66
|
if (spec.phase === "completed" || spec.phase === "cancelled") return null;
|
|
70
67
|
} else {
|
|
71
|
-
spec =
|
|
72
|
-
|
|
73
|
-
|
|
68
|
+
spec = await dbGet<any>(
|
|
69
|
+
"SELECT * FROM specs WHERE phase NOT IN ('completed', 'cancelled') ORDER BY created_at DESC LIMIT 1",
|
|
70
|
+
[]
|
|
71
|
+
);
|
|
74
72
|
if (!spec) return null;
|
|
75
73
|
}
|
|
76
74
|
|
|
@@ -82,9 +80,9 @@ export function resolveSpecOrNull(specId?: string, requiredPhases?: string[]): R
|
|
|
82
80
|
/**
|
|
83
81
|
* Retorna todos os specs ativos (nao completed/cancelled).
|
|
84
82
|
*/
|
|
85
|
-
export function getAllActiveSpecs(): ResolvedSpec[] {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
83
|
+
export async function getAllActiveSpecs(): Promise<ResolvedSpec[]> {
|
|
84
|
+
return await dbAll<ResolvedSpec>(
|
|
85
|
+
"SELECT * FROM specs WHERE phase NOT IN ('completed', 'cancelled') ORDER BY created_at DESC",
|
|
86
|
+
[]
|
|
87
|
+
);
|
|
90
88
|
}
|
package/commands/standards.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { dbGet, dbAll, dbRun } from "../db/connection";
|
|
2
2
|
import { initSchema } from "../db/schema";
|
|
3
3
|
import { generateStandardsMarkdown } from "./discover";
|
|
4
4
|
import { CodexaError, ValidationError } from "../errors";
|
|
5
5
|
|
|
6
|
-
export function standardsList(options: { category?: string; scope?: string; json?: boolean }): void {
|
|
7
|
-
initSchema();
|
|
8
|
-
const db = getDb();
|
|
6
|
+
export async function standardsList(options: { category?: string; scope?: string; json?: boolean }): Promise<void> {
|
|
7
|
+
await initSchema();
|
|
9
8
|
|
|
10
9
|
let query = "SELECT * FROM standards WHERE 1=1";
|
|
11
10
|
const params: any[] = [];
|
|
@@ -22,7 +21,7 @@ export function standardsList(options: { category?: string; scope?: string; json
|
|
|
22
21
|
|
|
23
22
|
query += " ORDER BY category, scope";
|
|
24
23
|
|
|
25
|
-
const standards =
|
|
24
|
+
const standards = await dbAll<any>(query, params);
|
|
26
25
|
|
|
27
26
|
if (options.json) {
|
|
28
27
|
console.log(JSON.stringify({ standards }, null, 2));
|
|
@@ -57,7 +56,7 @@ export function standardsList(options: { category?: string; scope?: string; json
|
|
|
57
56
|
console.log("Legenda: [REQ] = Obrigatorio [REC] = Recomendado\n");
|
|
58
57
|
}
|
|
59
58
|
|
|
60
|
-
export function standardsAdd(options: {
|
|
59
|
+
export async function standardsAdd(options: {
|
|
61
60
|
category: string;
|
|
62
61
|
scope: string;
|
|
63
62
|
rule: string;
|
|
@@ -66,9 +65,8 @@ export function standardsAdd(options: {
|
|
|
66
65
|
enforcement?: string;
|
|
67
66
|
semanticQuery?: string;
|
|
68
67
|
expect?: string;
|
|
69
|
-
}): void {
|
|
70
|
-
initSchema();
|
|
71
|
-
const db = getDb();
|
|
68
|
+
}): Promise<void> {
|
|
69
|
+
await initSchema();
|
|
72
70
|
|
|
73
71
|
const validCategories = ["stack", "structure", "naming", "code", "library", "practice"];
|
|
74
72
|
const validScopes = ["all", "database", "backend", "frontend", "testing"];
|
|
@@ -104,13 +102,12 @@ export function standardsAdd(options: {
|
|
|
104
102
|
antiExamples = JSON.stringify(options.antiExamples.split(",").map((s) => s.trim()));
|
|
105
103
|
}
|
|
106
104
|
|
|
107
|
-
const result =
|
|
105
|
+
const result = await dbRun(
|
|
108
106
|
`INSERT INTO standards (category, scope, rule, examples, anti_examples, enforcement, semantic_query, expect, source, created_at)
|
|
109
107
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'user', datetime('now'))`,
|
|
110
108
|
[options.category, options.scope, options.rule, examples, antiExamples, enforcement, options.semanticQuery || null, expectVal]
|
|
111
109
|
);
|
|
112
110
|
|
|
113
|
-
// Regenerar markdown
|
|
114
111
|
generateStandardsMarkdown();
|
|
115
112
|
|
|
116
113
|
console.log(`\nStandard #${result.lastInsertRowid} adicionado:`);
|
|
@@ -124,7 +121,7 @@ export function standardsAdd(options: {
|
|
|
124
121
|
console.log("\nArquivo atualizado: .codexa/standards.md\n");
|
|
125
122
|
}
|
|
126
123
|
|
|
127
|
-
export function standardsEdit(
|
|
124
|
+
export async function standardsEdit(
|
|
128
125
|
id: string,
|
|
129
126
|
options: {
|
|
130
127
|
rule?: string;
|
|
@@ -134,12 +131,11 @@ export function standardsEdit(
|
|
|
134
131
|
semanticQuery?: string;
|
|
135
132
|
expect?: string;
|
|
136
133
|
}
|
|
137
|
-
): void {
|
|
138
|
-
initSchema();
|
|
139
|
-
const db = getDb();
|
|
134
|
+
): Promise<void> {
|
|
135
|
+
await initSchema();
|
|
140
136
|
|
|
141
137
|
const standardId = parseInt(id);
|
|
142
|
-
const existing =
|
|
138
|
+
const existing = await dbGet<any>("SELECT * FROM standards WHERE id = ?", [standardId]);
|
|
143
139
|
|
|
144
140
|
if (!existing) {
|
|
145
141
|
throw new CodexaError(`Standard #${id} nao encontrado.`);
|
|
@@ -187,37 +183,34 @@ export function standardsEdit(
|
|
|
187
183
|
}
|
|
188
184
|
|
|
189
185
|
params.push(standardId);
|
|
190
|
-
|
|
186
|
+
await dbRun(`UPDATE standards SET ${updates.join(", ")} WHERE id = ?`, params);
|
|
191
187
|
|
|
192
|
-
// Regenerar markdown
|
|
193
188
|
generateStandardsMarkdown();
|
|
194
189
|
|
|
195
190
|
console.log(`\nStandard #${id} atualizado.`);
|
|
196
191
|
console.log("Arquivo atualizado: .codexa/standards.md\n");
|
|
197
192
|
}
|
|
198
193
|
|
|
199
|
-
export function standardsRemove(id: string): void {
|
|
200
|
-
initSchema();
|
|
201
|
-
const db = getDb();
|
|
194
|
+
export async function standardsRemove(id: string): Promise<void> {
|
|
195
|
+
await initSchema();
|
|
202
196
|
|
|
203
197
|
const standardId = parseInt(id);
|
|
204
|
-
const existing =
|
|
198
|
+
const existing = await dbGet<any>("SELECT * FROM standards WHERE id = ?", [standardId]);
|
|
205
199
|
|
|
206
200
|
if (!existing) {
|
|
207
201
|
throw new CodexaError(`Standard #${id} nao encontrado.`);
|
|
208
202
|
}
|
|
209
203
|
|
|
210
|
-
|
|
204
|
+
await dbRun("DELETE FROM standards WHERE id = ?", [standardId]);
|
|
211
205
|
|
|
212
|
-
// Regenerar markdown
|
|
213
206
|
generateStandardsMarkdown();
|
|
214
207
|
|
|
215
208
|
console.log(`\nStandard #${id} removido: ${existing.rule}`);
|
|
216
209
|
console.log("Arquivo atualizado: .codexa/standards.md\n");
|
|
217
210
|
}
|
|
218
211
|
|
|
219
|
-
export function standardsExport(): void {
|
|
220
|
-
initSchema();
|
|
212
|
+
export async function standardsExport(): Promise<void> {
|
|
213
|
+
await initSchema();
|
|
221
214
|
generateStandardsMarkdown();
|
|
222
215
|
console.log("\nArquivo gerado: .codexa/standards.md\n");
|
|
223
|
-
}
|
|
216
|
+
}
|
package/commands/sync.ts
CHANGED
|
@@ -4,14 +4,12 @@ import { join } from "path";
|
|
|
4
4
|
import { CodexaError } from "../errors";
|
|
5
5
|
import { getGrepaiWorkspace } from "./patterns";
|
|
6
6
|
|
|
7
|
-
// Agents que sao referencias (nao spawnables como subagent_type)
|
|
8
7
|
const REFERENCE_FILES = new Set([
|
|
9
8
|
"common-directives.md",
|
|
10
9
|
"subagent-return-protocol.md",
|
|
11
10
|
]);
|
|
12
11
|
|
|
13
12
|
function findPluginAgentsDir(): string | null {
|
|
14
|
-
// 1. Dev repo: git root + plugins/codexa-workflow/agents/
|
|
15
13
|
try {
|
|
16
14
|
const gitRoot = execSync("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim();
|
|
17
15
|
const pluginDir = join(gitRoot, "plugins", "codexa-workflow", "agents");
|
|
@@ -20,17 +18,14 @@ function findPluginAgentsDir(): string | null {
|
|
|
20
18
|
// Not in git repo
|
|
21
19
|
}
|
|
22
20
|
|
|
23
|
-
// 2. Global install: resolve from @codexa/cli package location
|
|
24
21
|
try {
|
|
25
22
|
const cliPath = execSync("bun pm ls -g 2>/dev/null || npm list -g @codexa/cli --parseable 2>/dev/null", {
|
|
26
23
|
encoding: "utf-8",
|
|
27
24
|
}).trim();
|
|
28
25
|
if (cliPath) {
|
|
29
|
-
// Navigate from cli package to sibling plugin
|
|
30
26
|
const lines = cliPath.split("\n").filter(l => l.includes("codexa"));
|
|
31
27
|
for (const line of lines) {
|
|
32
28
|
const trimmed = line.trim();
|
|
33
|
-
// Try parent paths to find the monorepo root
|
|
34
29
|
const parts = trimmed.split(/[/\\]/);
|
|
35
30
|
for (let i = parts.length - 1; i >= 0; i--) {
|
|
36
31
|
const candidate = join(parts.slice(0, i + 1).join("/"), "plugins", "codexa-workflow", "agents");
|
|
@@ -45,7 +40,7 @@ function findPluginAgentsDir(): string | null {
|
|
|
45
40
|
return null;
|
|
46
41
|
}
|
|
47
42
|
|
|
48
|
-
export function syncAgents(options: { force?: boolean } = {}): void {
|
|
43
|
+
export async function syncAgents(options: { force?: boolean } = {}): Promise<void> {
|
|
49
44
|
const pluginDir = findPluginAgentsDir();
|
|
50
45
|
|
|
51
46
|
if (!pluginDir) {
|
|
@@ -73,9 +68,8 @@ export function syncAgents(options: { force?: boolean } = {}): void {
|
|
|
73
68
|
|
|
74
69
|
copyFileSync(src, dst);
|
|
75
70
|
|
|
76
|
-
// Inject workspace flag in deep-explore if configured
|
|
77
71
|
if (file === "deep-explore.md") {
|
|
78
|
-
const workspace = getGrepaiWorkspace();
|
|
72
|
+
const workspace = await getGrepaiWorkspace();
|
|
79
73
|
const wsFlag = workspace ? ` --workspace ${workspace}` : "";
|
|
80
74
|
let agentContent = readFileSync(dst, "utf-8");
|
|
81
75
|
agentContent = agentContent.replace(/\{\{GREPAI_WS_FLAG\}\}/g, wsFlag);
|