forgecraft 1.0.0 → 1.1.0

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.
@@ -220,11 +220,68 @@ requirements.txt # Python dependencies
220
220
  `.trim()
221
221
  };
222
222
 
223
+ // src/core/adapters/generic.ts
224
+ var genericAdapter = {
225
+ id: "generic",
226
+ name: "Custom Stack",
227
+ language: "typescript",
228
+ // default, but prompts tell the agent to auto-detect
229
+ scaffoldCommands: [],
230
+ buildCommand: "AUTO_DETECT",
231
+ lintCommand: "AUTO_DETECT",
232
+ typecheckCommand: "AUTO_DETECT",
233
+ devCommand: "npm run dev",
234
+ devPort: 3e3,
235
+ designSupport: false,
236
+ packageManager: "npm",
237
+ requiredFiles: [],
238
+ buildPromptAdditions: `
239
+ CUSTOM TECH STACK \u2014 IMPORTANT:
240
+ This project uses a tech stack chosen by the user. You MUST auto-detect everything.
241
+
242
+ STEP 1 \u2014 DETECT THE STACK:
243
+ Before writing ANY code, read these files (whichever exist):
244
+ - package.json (Node.js/JS/TS projects)
245
+ - requirements.txt / pyproject.toml / Pipfile (Python projects)
246
+ - go.mod (Go projects)
247
+ - Cargo.toml (Rust projects)
248
+ - pom.xml / build.gradle (Java/Kotlin projects)
249
+ - pubspec.yaml (Flutter/Dart projects)
250
+ - Gemfile (Ruby projects)
251
+ - composer.json (PHP projects)
252
+ - Any existing source files to understand patterns
253
+
254
+ STEP 2 \u2014 FOLLOW EXISTING CONVENTIONS:
255
+ - If the project already has code, match its style exactly (naming, file structure, patterns)
256
+ - If starting from scratch, use the standard project structure for the detected tech stack
257
+ - Use the package manager the project already uses (npm, yarn, pnpm, pip, poetry, cargo, go, etc.)
258
+
259
+ STEP 3 \u2014 BUILD VERIFICATION:
260
+ - Detect the correct build/lint/test commands from the project config
261
+ - For Node.js: check package.json "scripts" for build, lint, typecheck commands
262
+ - For Python: use pytest, flake8/ruff, mypy if configured
263
+ - For Go: use go build, go vet, go test
264
+ - For Rust: use cargo build, cargo clippy, cargo test
265
+ - If no build script exists, skip the build step \u2014 do NOT fail
266
+ - If a command does not exist or is not configured, skip it gracefully
267
+
268
+ STEP 4 \u2014 SCAFFOLDING:
269
+ - If the project directory is empty, scaffold the project using the standard tooling for the stack
270
+ (e.g., npm init, cargo init, go mod init, django-admin startproject, etc.)
271
+ - Install dependencies after scaffolding
272
+ `.trim(),
273
+ designPromptAdditions: "",
274
+ fileStructure: `
275
+ (auto-detected \u2014 read the project's existing files to determine structure)
276
+ `.trim()
277
+ };
278
+
223
279
  // src/core/adapters/index.ts
224
280
  var adapters = {
225
281
  nextjs: nextjsAdapter,
226
282
  react: reactViteAdapter,
227
- django: djangoAdapter
283
+ django: djangoAdapter,
284
+ generic: genericAdapter
228
285
  };
229
286
  function getAdapter(framework) {
230
287
  const adapter = adapters[framework];
@@ -362,12 +419,14 @@ var Orchestrator = class {
362
419
  // ── Plan Generation ───────────────────────────────────────
363
420
  async generatePlan(description) {
364
421
  const adapter = getAdapter(this.config.framework);
422
+ const isGeneric = adapter.id === "generic";
423
+ const frameworkHint = isGeneric ? `Tech stack: Detect from the user's description below. The user may specify their own framework, language, and tools.` : `Framework: ${adapter.name} (${this.config.framework})
424
+ Language: ${adapter.language}`;
365
425
  const prompt = `
366
426
  The user wants to build the following application:
367
427
  "${description}"
368
428
 
369
- Framework: ${adapter.name} (${this.config.framework})
370
- Language: ${adapter.language}
429
+ ${frameworkHint}
371
430
  Design support: ${adapter.designSupport ? "yes (Storybook)" : "no"}
372
431
 
373
432
  Break this down into epics and stories. Each story should be:
@@ -522,11 +581,31 @@ var Orchestrator = class {
522
581
  `;
523
582
  }
524
583
  craftBuildPrompt(story, context, adapter) {
584
+ const isGeneric = adapter.id === "generic";
525
585
  const designRef = context.designMeta ? `
526
586
  Approved design: Follow the design in stories/${story.id}.stories.tsx exactly.` : "";
527
587
  const existingRef = context.existingFiles?.length ? `
528
588
  Existing files to reference for patterns:
529
589
  ${context.existingFiles.map((f) => ` - ${f}`).join("\n")}` : "";
590
+ const verifySteps = isGeneric ? `
591
+ After writing code:
592
+ 1. Detect the project's build/lint/typecheck commands from its config files (package.json scripts, Makefile, pyproject.toml, etc.)
593
+ 2. Run whichever commands exist \u2014 skip any that aren't configured
594
+ 3. Fix any errors before finishing
595
+ ` : `
596
+ After writing code:
597
+ 1. Run: ${adapter.buildCommand} (fix any errors)
598
+ 2. Run: ${adapter.lintCommand} (fix any warnings)
599
+ 3. Run: ${adapter.typecheckCommand} (fix any type errors)
600
+ `;
601
+ const structureRef = isGeneric ? `
602
+ Project structure:
603
+ Read the existing project files to understand the structure.
604
+ If starting from scratch, use the standard conventions for this tech stack.
605
+ ` : `
606
+ Expected project structure:
607
+ ${adapter.fileStructure}
608
+ `;
530
609
  return `
531
610
  Implement: "${story.title}"
532
611
 
@@ -535,8 +614,7 @@ ${context.existingFiles.map((f) => ` - ${f}`).join("\n")}` : "";
535
614
  ${designRef}
536
615
  ${existingRef}
537
616
 
538
- Expected project structure:
539
- ${adapter.fileStructure}
617
+ ${structureRef}
540
618
 
541
619
  Technical requirements:
542
620
  - Follow existing code patterns in the project
@@ -544,16 +622,18 @@ ${context.existingFiles.map((f) => ` - ${f}`).join("\n")}` : "";
544
622
  - Proper error handling
545
623
  - Responsive design (mobile-first)
546
624
 
547
- After writing code:
548
- 1. Run: ${adapter.buildCommand} (fix any errors)
549
- 2. Run: ${adapter.lintCommand} (fix any warnings)
550
- 3. Run: ${adapter.typecheckCommand} (fix any type errors)
625
+ ${verifySteps}
551
626
 
552
627
  If any command fails, read the error, fix it, and re-run.
553
628
  Do NOT leave broken code.
554
629
  `;
555
630
  }
556
631
  craftReviewPrompt(story, context, adapter) {
632
+ const isGeneric = adapter.id === "generic";
633
+ const runCmds = isGeneric ? `Run the project's build/lint/test commands (detect from config files). Skip any that aren't configured.` : `Run:
634
+ - ${adapter.buildCommand}
635
+ - ${adapter.lintCommand}
636
+ - ${adapter.typecheckCommand}`;
557
637
  return `
558
638
  Review the code for: "${story.title}"
559
639
 
@@ -568,10 +648,7 @@ ${context.existingFiles.map((f) => ` - ${f}`).join("\n")}` : "";
568
648
  6. Accessibility \u2014 semantic HTML, ARIA labels
569
649
  7. No debug logs, no commented-out code, no TODOs
570
650
 
571
- Run:
572
- - ${adapter.buildCommand}
573
- - ${adapter.lintCommand}
574
- - ${adapter.typecheckCommand}
651
+ ${runCmds}
575
652
 
576
653
  If you find issues:
577
654
  - Minor (formatting, missing type): fix them directly
@@ -581,12 +658,14 @@ ${context.existingFiles.map((f) => ` - ${f}`).join("\n")}` : "";
581
658
  `;
582
659
  }
583
660
  craftFixPrompt(story, context, adapter) {
661
+ const isGeneric = adapter.id === "generic";
662
+ const verifyCmds = isGeneric ? "After fixing, run the project's build/test commands to verify (detect from config files)." : `After fixing, run ${adapter.buildCommand} and ${adapter.typecheckCommand} to verify.`;
584
663
  return `
585
664
  Fix an issue in: "${story.title}"
586
665
  Framework: ${adapter.name}
587
666
 
588
667
  Make the smallest possible change. Do not refactor.
589
- After fixing, run ${adapter.buildCommand} and ${adapter.typecheckCommand} to verify.
668
+ ${verifyCmds}
590
669
  `;
591
670
  }
592
671
  // ── SDK Query Helper ──────────────────────────────────────
@@ -699,9 +778,20 @@ ${additions}
699
778
  function getBuildPrompt(framework) {
700
779
  const adapter = framework ? getAdapter(framework) : null;
701
780
  const additions = adapter?.buildPromptAdditions || "";
702
- const buildCmd = adapter?.buildCommand || "npm run build";
703
- const lintCmd = adapter?.lintCommand || "npm run lint";
704
- const typecheckCmd = adapter?.typecheckCommand || "npx tsc --noEmit";
781
+ const isGeneric = adapter?.id === "generic";
782
+ const verifyBlock = isGeneric ? `
783
+ AFTER WRITING CODE:
784
+ 1. Detect the project's build/lint/typecheck/test commands from its config files
785
+ (package.json scripts, Makefile, pyproject.toml, Cargo.toml, etc.)
786
+ 2. Run whichever commands exist \u2014 skip any that aren't configured
787
+ 3. Fix ALL errors before proceeding
788
+ 4. If no build system is configured, verify the code is syntactically valid
789
+ ` : `
790
+ AFTER WRITING CODE:
791
+ 1. Run: ${adapter?.buildCommand || "npm run build"} \u2014 fix ALL errors before proceeding
792
+ 2. Run: ${adapter?.lintCommand || "npm run lint"} \u2014 fix warnings
793
+ 3. Run: ${adapter?.typecheckCommand || "npx tsc --noEmit"} \u2014 fix type errors
794
+ `;
705
795
  return `
706
796
  You are a senior fullstack developer working within the Forge development framework.
707
797
  Your job is to implement features based on approved designs and story requirements.
@@ -715,10 +805,7 @@ CODING STANDARDS:
715
805
 
716
806
  ${additions}
717
807
 
718
- AFTER WRITING CODE:
719
- 1. Run: ${buildCmd} \u2014 fix ALL errors before proceeding
720
- 2. Run: ${lintCmd} \u2014 fix warnings
721
- 3. Run: ${typecheckCmd} \u2014 fix type errors
808
+ ${verifyBlock}
722
809
 
723
810
  If any command fails:
724
811
  - Read the full error output
@@ -736,10 +823,21 @@ GIT:
736
823
  }
737
824
  function getReviewPrompt(framework) {
738
825
  const adapter = framework ? getAdapter(framework) : null;
739
- const buildCmd = adapter?.buildCommand || "npm run build";
740
- const lintCmd = adapter?.lintCommand || "npm run lint";
741
- const typecheckCmd = adapter?.typecheckCommand || "npx tsc --noEmit";
826
+ const isGeneric = adapter?.id === "generic";
742
827
  const lang = adapter?.language || "typescript";
828
+ const langCheck = isGeneric ? "3. Code quality \u2014 follows the language's best practices and idioms" : lang === "typescript" ? "3. TypeScript strict compliance (no any, no ts-ignore, no ts-expect-error)" : "3. Python code quality (no bare except, proper type hints where used)";
829
+ const runBlock = isGeneric ? `
830
+ RUN THESE COMMANDS:
831
+ - Detect build/lint/test commands from the project's config files (package.json, Makefile, pyproject.toml, Cargo.toml, etc.)
832
+ - Run whichever exist \u2014 skip any that aren't configured
833
+ - Run tests if a test runner is configured
834
+ ` : `
835
+ RUN THESE COMMANDS:
836
+ - ${adapter?.buildCommand || "npm run build"}
837
+ - ${adapter?.lintCommand || "npm run lint"}
838
+ - ${adapter?.typecheckCommand || "npx tsc --noEmit"}
839
+ - npm run test (if tests exist)
840
+ `;
743
841
  return `
744
842
  You are a QA engineer reviewing code within the Forge development framework.
745
843
  Your job is to catch issues before code is merged to main.
@@ -747,7 +845,7 @@ Your job is to catch issues before code is merged to main.
747
845
  REVIEW CHECKLIST:
748
846
  1. Implementation matches the story description
749
847
  2. If design was approved \u2014 implementation matches the design
750
- ${lang === "typescript" ? "3. TypeScript strict compliance (no any, no ts-ignore, no ts-expect-error)" : "3. Python code quality (no bare except, proper type hints where used)"}
848
+ ${langCheck}
751
849
  4. Responsive design works at 375px, 768px, 1440px
752
850
  5. Error handling \u2014 what happens when things fail?
753
851
  6. Loading states \u2014 what does the user see while waiting?
@@ -758,11 +856,7 @@ ${lang === "typescript" ? "3. TypeScript strict compliance (no any, no ts-ignore
758
856
  11. No TODO/FIXME/HACK comments left behind
759
857
  12. No hardcoded values that should be configurable
760
858
 
761
- RUN THESE COMMANDS:
762
- - ${buildCmd}
763
- - ${lintCmd}
764
- - ${typecheckCmd}
765
- - npm run test (if tests exist)
859
+ ${runBlock}
766
860
 
767
861
  ISSUE CLASSIFICATION:
768
862
  - MINOR: formatting, missing type annotation, unused import
@@ -781,8 +875,18 @@ Provide a structured review summary:
781
875
  }
782
876
  function getFixPrompt(framework) {
783
877
  const adapter = framework ? getAdapter(framework) : null;
784
- const buildCmd = adapter?.buildCommand || "npm run build";
785
- const typecheckCmd = adapter?.typecheckCommand || "npx tsc --noEmit";
878
+ const isGeneric = adapter?.id === "generic";
879
+ const verifyBlock = isGeneric ? `
880
+ AFTER EVERY FIX:
881
+ 1. Detect the project's build/test commands from its config files
882
+ 2. Run whichever exist to verify nothing is broken
883
+ 3. Verify the fix works
884
+ ` : `
885
+ AFTER EVERY FIX:
886
+ 1. Run: ${adapter?.buildCommand || "npm run build"}
887
+ 2. Run: ${adapter?.typecheckCommand || "npx tsc --noEmit"}
888
+ 3. Verify the fix works
889
+ `;
786
890
  return `
787
891
  You are a debugger and problem solver within the Forge development framework.
788
892
  Your job is to make targeted fixes without breaking anything else.
@@ -805,10 +909,7 @@ FOR BUG FIXES:
805
909
  - Check if the same bug pattern exists elsewhere
806
910
  - Verify the fix by running the relevant command
807
911
 
808
- AFTER EVERY FIX:
809
- 1. Run: ${buildCmd}
810
- 2. Run: ${typecheckCmd}
811
- 3. Verify the fix works
912
+ ${verifyBlock}
812
913
 
813
914
  If your fix introduces new errors, undo it and try a different approach.
814
915
  `.trim();
@@ -911,6 +1012,9 @@ var Worker = class {
911
1012
  cwd: workingDir,
912
1013
  maxTurns: MODE_MAX_TURNS[mode]
913
1014
  };
1015
+ if (this.sandboxOpts.yes && !this.sandboxOpts.sandbox) {
1016
+ sdkOptions.permissionMode = "bypassPermissions";
1017
+ }
914
1018
  if (this.sandboxOpts.sandbox) {
915
1019
  sdkOptions.permissionMode = "bypassPermissions";
916
1020
  sdkOptions.sandbox = {
@@ -1927,6 +2031,7 @@ var AutoPipeline = class {
1927
2031
  config,
1928
2032
  {
1929
2033
  sandbox: options.sandbox ?? true,
2034
+ yes: options.yes ?? false,
1930
2035
  workingDir: options.workingDir,
1931
2036
  allowedDomains: options.allowedDomains
1932
2037
  },
@@ -2027,7 +2132,11 @@ var AutoPipeline = class {
2027
2132
  const errors = [];
2028
2133
  this.startTime = Date.now();
2029
2134
  console.log(chalk4.bold("\n forge") + chalk4.dim(" auto"));
2030
- console.log(chalk4.dim(` sandbox ${this.options.sandbox !== false ? "on" : "off"} \xB7 type a message anytime to queue feedback
2135
+ const flags = [
2136
+ `sandbox ${this.options.sandbox !== false ? "on" : "off"}`,
2137
+ ...this.options.yes ? ["auto-approve on"] : []
2138
+ ].join(" \xB7 ");
2139
+ console.log(chalk4.dim(` ${flags} \xB7 type a message anytime to queue feedback
2031
2140
  `));
2032
2141
  this.startChatListener();
2033
2142
  await this.git.ensureRepo();
@@ -2415,6 +2524,7 @@ var AutoPipeline = class {
2415
2524
  }
2416
2525
  // ── Review Gate ───────────────────────────────────────────
2417
2526
  async reviewGate() {
2527
+ if (this.options.yes) return "continue";
2418
2528
  if (!process.stdout.isTTY) return "continue";
2419
2529
  if (!this.options.mute) {
2420
2530
  playSound();
@@ -2805,4 +2915,4 @@ export {
2805
2915
  validateConfig,
2806
2916
  loadAndValidateConfig
2807
2917
  };
2808
- //# sourceMappingURL=chunk-2HFEPXBV.js.map
2918
+ //# sourceMappingURL=chunk-WXVO3XYN.js.map