@brainforge/core 3.1.12 → 3.1.13
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/index.d.ts +12 -2
- package/dist/index.js +114 -31
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { EventEmitter } from 'events';
|
|
|
3
3
|
type ProjectType = 'student' | 'junior' | 'solo' | 'personal' | 'pro';
|
|
4
4
|
type StudentLevel = 'beginner' | 'intermediate' | 'advanced' | 'professional';
|
|
5
5
|
type Language = 'typescript' | 'javascript' | 'python' | 'java' | 'go' | 'php' | 'rust' | 'csharp' | 'ruby';
|
|
6
|
-
type PhaseStatus = 'pending' | 'active' | 'completed' | 'blocked' | 'draft' | 'discussed' | 'planned' | 'checked' | 'executing' | 'executed' | 'verified' | 'failed' | 'fixed' | 'shipped';
|
|
6
|
+
type PhaseStatus = 'pending' | 'active' | 'completed' | 'blocked' | 'draft' | 'discussed' | 'planned' | 'checked' | 'executing' | 'executed' | 'verified' | 'failed' | 'fixed' | 'shipped' | 'needs-manual-verification';
|
|
7
7
|
type TaskStatus = 'todo' | 'in-progress' | 'done' | 'skipped';
|
|
8
8
|
type TaskPriority = 'low' | 'medium' | 'high' | 'critical';
|
|
9
9
|
type TaskType = 'backend' | 'frontend' | 'database' | 'devops' | 'security' | 'test' | 'docs' | 'general';
|
|
@@ -750,6 +750,14 @@ interface BugEntry {
|
|
|
750
750
|
taskId?: string;
|
|
751
751
|
description?: string;
|
|
752
752
|
}
|
|
753
|
+
interface CommandResult {
|
|
754
|
+
command: string;
|
|
755
|
+
status: 'passed' | 'failed';
|
|
756
|
+
exitCode: number;
|
|
757
|
+
stdout: string;
|
|
758
|
+
stderr: string;
|
|
759
|
+
duration: number;
|
|
760
|
+
}
|
|
753
761
|
interface VerifyResult {
|
|
754
762
|
phaseId: string;
|
|
755
763
|
phaseName: string;
|
|
@@ -758,11 +766,13 @@ interface VerifyResult {
|
|
|
758
766
|
passed: number;
|
|
759
767
|
bugs: BugEntry[];
|
|
760
768
|
blocked: boolean;
|
|
769
|
+
commandResults?: CommandResult[];
|
|
761
770
|
}
|
|
762
771
|
declare class VerificationEngine {
|
|
763
772
|
detectAvailableCommands(cwd: string): Promise<string[]>;
|
|
773
|
+
runCommands(commands: string[], cwd: string): Promise<CommandResult[]>;
|
|
764
774
|
buildVerifyPrompt(phase: Phase, stack?: StackInfo, detectedCommands?: string[]): string;
|
|
765
|
-
buildVerifyMd(phase: Phase, bugs?: BugEntry[]): string;
|
|
775
|
+
buildVerifyMd(phase: Phase, commandResults?: CommandResult[], bugs?: BugEntry[]): string;
|
|
766
776
|
buildBugsMd(bugs: BugEntry[]): string;
|
|
767
777
|
}
|
|
768
778
|
|
package/dist/index.js
CHANGED
|
@@ -604,16 +604,20 @@ Identify:
|
|
|
604
604
|
Ensure every acceptance criterion is covered.`,
|
|
605
605
|
fix_phase: `You are BrainForge AI. Generate a fix plan for phase "{{phase.name}}".
|
|
606
606
|
|
|
607
|
-
|
|
608
|
-
|
|
607
|
+
# Verification Results
|
|
608
|
+
{{failures}}
|
|
609
609
|
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
- Files to inspect
|
|
613
|
-
- Proposed correction steps
|
|
614
|
-
- Commands to re-run
|
|
610
|
+
# Original Plan Context
|
|
611
|
+
{{plan}}
|
|
615
612
|
|
|
616
|
-
|
|
613
|
+
# Analysis Requirements
|
|
614
|
+
1. Identify the failed commands and their error outputs.
|
|
615
|
+
2. Formulate root cause hypotheses for each failure.
|
|
616
|
+
3. List specific files to inspect and potential logical bugs.
|
|
617
|
+
4. Propose step-by-step correction instructions for an AI agent.
|
|
618
|
+
5. Identify the exact verification commands to re-run after fixes.
|
|
619
|
+
|
|
620
|
+
Produce a FIX_PLAN.md that is honest: it guides the fix, it doesn't pretend to have fixed it automatically.`,
|
|
617
621
|
ship_phase: `You are BrainForge AI. Generate a final ship report for phase "{{phase.name}}".
|
|
618
622
|
|
|
619
623
|
Completed Tasks: {{tasks}}
|
|
@@ -7362,6 +7366,9 @@ ${cmd}
|
|
|
7362
7366
|
// src/workflow/verification-engine.ts
|
|
7363
7367
|
import fs23 from "fs/promises";
|
|
7364
7368
|
import path25 from "path";
|
|
7369
|
+
import { exec as exec2 } from "child_process";
|
|
7370
|
+
import { promisify as promisify2 } from "util";
|
|
7371
|
+
var execAsync2 = promisify2(exec2);
|
|
7365
7372
|
var VerificationEngine = class {
|
|
7366
7373
|
async detectAvailableCommands(cwd) {
|
|
7367
7374
|
const commands = [];
|
|
@@ -7370,10 +7377,15 @@ var VerificationEngine = class {
|
|
|
7370
7377
|
const raw = await fs23.readFile(pkgPath, "utf-8");
|
|
7371
7378
|
const pkg = JSON.parse(raw);
|
|
7372
7379
|
const scripts = pkg.scripts || {};
|
|
7373
|
-
|
|
7374
|
-
|
|
7375
|
-
|
|
7376
|
-
|
|
7380
|
+
const hasYarn = await fs23.access(path25.join(cwd, "yarn.lock")).then(() => true).catch(() => false);
|
|
7381
|
+
const hasPnpm = await fs23.access(path25.join(cwd, "pnpm-lock.yaml")).then(() => true).catch(() => false);
|
|
7382
|
+
const hasBun = await fs23.access(path25.join(cwd, "bun.lockb")).then(() => true).catch(() => false);
|
|
7383
|
+
const manager = hasBun ? "bun" : hasPnpm ? "pnpm" : hasYarn ? "yarn" : "npm";
|
|
7384
|
+
const run = manager === "npm" || manager === "bun" ? `${manager} run` : manager;
|
|
7385
|
+
if (scripts.build) commands.push(`${run} build`);
|
|
7386
|
+
if (scripts.test) commands.push(`${manager} test`);
|
|
7387
|
+
if (scripts.lint) commands.push(`${run} lint`);
|
|
7388
|
+
if (scripts.typecheck) commands.push(`${run} typecheck`);
|
|
7377
7389
|
} catch {
|
|
7378
7390
|
}
|
|
7379
7391
|
try {
|
|
@@ -7393,11 +7405,48 @@ var VerificationEngine = class {
|
|
|
7393
7405
|
}
|
|
7394
7406
|
try {
|
|
7395
7407
|
await fs23.access(path25.join(cwd, "build.gradle"));
|
|
7396
|
-
commands.push("
|
|
7408
|
+
commands.push("./gradlew test");
|
|
7409
|
+
} catch {
|
|
7410
|
+
}
|
|
7411
|
+
try {
|
|
7412
|
+
await fs23.access(path25.join(cwd, "go.mod"));
|
|
7413
|
+
commands.push("go test ./...");
|
|
7414
|
+
} catch {
|
|
7415
|
+
}
|
|
7416
|
+
try {
|
|
7417
|
+
await fs23.access(path25.join(cwd, "Cargo.toml"));
|
|
7418
|
+
commands.push("cargo test");
|
|
7397
7419
|
} catch {
|
|
7398
7420
|
}
|
|
7399
7421
|
return commands;
|
|
7400
7422
|
}
|
|
7423
|
+
async runCommands(commands, cwd) {
|
|
7424
|
+
const results = [];
|
|
7425
|
+
for (const command of commands) {
|
|
7426
|
+
const start = Date.now();
|
|
7427
|
+
try {
|
|
7428
|
+
const { stdout, stderr } = await execAsync2(command, { cwd });
|
|
7429
|
+
results.push({
|
|
7430
|
+
command,
|
|
7431
|
+
status: "passed",
|
|
7432
|
+
exitCode: 0,
|
|
7433
|
+
stdout,
|
|
7434
|
+
stderr,
|
|
7435
|
+
duration: Date.now() - start
|
|
7436
|
+
});
|
|
7437
|
+
} catch (err) {
|
|
7438
|
+
results.push({
|
|
7439
|
+
command,
|
|
7440
|
+
status: "failed",
|
|
7441
|
+
exitCode: err.code || 1,
|
|
7442
|
+
stdout: err.stdout || "",
|
|
7443
|
+
stderr: err.stderr || err.message,
|
|
7444
|
+
duration: Date.now() - start
|
|
7445
|
+
});
|
|
7446
|
+
}
|
|
7447
|
+
}
|
|
7448
|
+
return results;
|
|
7449
|
+
}
|
|
7401
7450
|
buildVerifyPrompt(phase, stack, detectedCommands = []) {
|
|
7402
7451
|
const allCriteria = [];
|
|
7403
7452
|
for (const t of phase.tasks) {
|
|
@@ -7447,23 +7496,53 @@ ${cmd}
|
|
|
7447
7496
|
lines.push("*Generated by BrainForge AI \u2014 paste into your AI tool to verify the phase.*");
|
|
7448
7497
|
return lines.join("\n");
|
|
7449
7498
|
}
|
|
7450
|
-
buildVerifyMd(phase, bugs = []) {
|
|
7499
|
+
buildVerifyMd(phase, commandResults = [], bugs = []) {
|
|
7451
7500
|
const now = (/* @__PURE__ */ new Date()).toISOString().slice(0, 16).replace("T", " ");
|
|
7452
|
-
|
|
7453
|
-
|
|
7501
|
+
let status = "passed";
|
|
7502
|
+
if (commandResults.length === 0) {
|
|
7503
|
+
status = "manual-required";
|
|
7504
|
+
} else if (commandResults.some((r) => r.status === "failed") || bugs.some((b) => b.severity === "critical")) {
|
|
7505
|
+
status = "failed";
|
|
7506
|
+
}
|
|
7507
|
+
const passedCount = commandResults.filter((r) => r.status === "passed").length;
|
|
7508
|
+
const totalDuration = commandResults.reduce((acc, r) => acc + r.duration, 0);
|
|
7454
7509
|
const lines = [
|
|
7455
|
-
`#
|
|
7456
|
-
|
|
7457
|
-
|
|
7510
|
+
`# Verify Report: ${phase.name}`,
|
|
7511
|
+
"",
|
|
7512
|
+
"## Summary",
|
|
7513
|
+
"",
|
|
7514
|
+
`- **Status:** ${status.toUpperCase()}`,
|
|
7515
|
+
`- **Date:** ${now} UTC`,
|
|
7516
|
+
`- **Duration:** ${(totalDuration / 1e3).toFixed(2)}s`,
|
|
7517
|
+
`- **Commands run:** ${commandResults.length}`,
|
|
7518
|
+
`- **Commands passed:** ${passedCount}`,
|
|
7519
|
+
`- **Commands failed:** ${commandResults.length - passedCount}`,
|
|
7458
7520
|
"",
|
|
7459
|
-
"##
|
|
7521
|
+
"## Commands",
|
|
7522
|
+
""
|
|
7460
7523
|
];
|
|
7461
|
-
for (const
|
|
7462
|
-
|
|
7463
|
-
|
|
7524
|
+
for (const r of commandResults) {
|
|
7525
|
+
lines.push(
|
|
7526
|
+
`### \`${r.command}\``,
|
|
7527
|
+
"",
|
|
7528
|
+
`- **Status:** ${r.status === "passed" ? "\u{1F7E2} PASSED" : "\u{1F534} FAILED"}`,
|
|
7529
|
+
`- **Exit code:** ${r.exitCode}`,
|
|
7530
|
+
`- **Duration:** ${(r.duration / 1e3).toFixed(2)}s`,
|
|
7531
|
+
"",
|
|
7532
|
+
"#### stdout",
|
|
7533
|
+
"```txt",
|
|
7534
|
+
r.stdout || "(empty)",
|
|
7535
|
+
"```",
|
|
7536
|
+
"",
|
|
7537
|
+
"#### stderr",
|
|
7538
|
+
"```txt",
|
|
7539
|
+
r.stderr || "(empty)",
|
|
7540
|
+
"```",
|
|
7541
|
+
""
|
|
7542
|
+
);
|
|
7464
7543
|
}
|
|
7465
7544
|
if (bugs.length > 0) {
|
|
7466
|
-
lines.push("", "
|
|
7545
|
+
lines.push("## Findings", "");
|
|
7467
7546
|
for (const bug of bugs) {
|
|
7468
7547
|
lines.push(`### ${bug.id}: ${bug.title}`);
|
|
7469
7548
|
lines.push(`**Severity:** ${bug.severity}`);
|
|
@@ -7472,13 +7551,17 @@ ${cmd}
|
|
|
7472
7551
|
lines.push("");
|
|
7473
7552
|
}
|
|
7474
7553
|
}
|
|
7475
|
-
|
|
7476
|
-
|
|
7477
|
-
|
|
7478
|
-
|
|
7479
|
-
|
|
7480
|
-
|
|
7481
|
-
|
|
7554
|
+
lines.push(
|
|
7555
|
+
"## Diagnosis",
|
|
7556
|
+
"",
|
|
7557
|
+
status === "passed" ? "* All automated checks passed. Ready to ship." : status === "manual-required" ? "* No automated commands detected. Manual verification is required." : "* Automated checks failed. Review stderr above for root causes.",
|
|
7558
|
+
"* Files likely involved: " + (phase.tasks.flatMap((t) => t.files || []).join(", ") || "N/A"),
|
|
7559
|
+
"",
|
|
7560
|
+
"## Final decision",
|
|
7561
|
+
"",
|
|
7562
|
+
`Phase status changed to: **${status === "passed" ? "verified" : status === "failed" ? "failed" : "needs-manual-verification"}**`,
|
|
7563
|
+
""
|
|
7564
|
+
);
|
|
7482
7565
|
return lines.join("\n");
|
|
7483
7566
|
}
|
|
7484
7567
|
buildBugsMd(bugs) {
|