@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 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
- Bugs/Failures: {{failures}}
608
- Original Plan: {{plan}}
607
+ # Verification Results
608
+ {{failures}}
609
609
 
610
- Analyze:
611
- - Root cause hypotheses
612
- - Files to inspect
613
- - Proposed correction steps
614
- - Commands to re-run
610
+ # Original Plan Context
611
+ {{plan}}
615
612
 
616
- Produce a FIX_PLAN.md.`,
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
- if (scripts.build) commands.push("npm run build");
7374
- if (scripts.test) commands.push("npm test");
7375
- if (scripts.lint) commands.push("npm run lint");
7376
- if (scripts.typecheck) commands.push("npm run typecheck");
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("gradle test");
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
- const criticalBugs = bugs.filter((b) => b.severity === "critical");
7453
- const blocked = criticalBugs.length > 0;
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
- `# Verification Report \u2014 ${phase.name}`,
7456
- `> Generated: ${now} UTC`,
7457
- `> Status: ${blocked ? "\u{1F534} BLOCKED" : bugs.length > 0 ? "\u{1F7E1} ISSUES FOUND" : "\u{1F7E2} VERIFIED"}`,
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
- "## Tasks"
7521
+ "## Commands",
7522
+ ""
7460
7523
  ];
7461
- for (const t of phase.tasks) {
7462
- const icon = t.status === "done" ? "\u2713" : "\u25CB";
7463
- lines.push(`- [${icon}] ${t.title}`);
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("", "## Bugs Found");
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
- if (!blocked) {
7476
- lines.push("", "## Next step");
7477
- lines.push("Run `brg ship` to close this phase and update project memory.");
7478
- } else {
7479
- lines.push("", "## Next step");
7480
- lines.push("Fix critical bugs then re-run `brg verify` before shipping.");
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) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainforge/core",
3
- "version": "3.1.12",
3
+ "version": "3.1.13",
4
4
  "description": "Core engine for BrainForge AI — state management, AST mapper, skills, and AI adapters",
5
5
  "type": "module",
6
6
  "license": "MIT",