forgehive 0.7.8 → 0.7.9

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.
Files changed (3) hide show
  1. package/README.md +2 -2
  2. package/dist/cli.js +101 -41
  3. package/package.json +2 -1
package/README.md CHANGED
@@ -16,7 +16,7 @@
16
16
  <img src="https://img.shields.io/badge/typescript-5.8-blue" alt="TypeScript">
17
17
  <img src="https://img.shields.io/badge/tests-273%20passing-success" alt="273 tests">
18
18
  <img src="https://img.shields.io/badge/bundle-259KB-lightgrey" alt="259KB bundle">
19
- <img src="https://img.shields.io/badge/license-MIT-green" alt="MIT">
19
+ <img src="https://img.shields.io/badge/license-Elastic%202.0-orange" alt="Elastic License 2.0">
20
20
  </p>
21
21
 
22
22
  ---
@@ -903,4 +903,4 @@ npm test # node --import tsx/esm --test test/*.test.ts
903
903
 
904
904
  ## License
905
905
 
906
- MIT
906
+ Elastic License 2.0 (ELv2) — kostenlos selbst hosten für den eigenen Betrieb. Weiterverkauf als Managed Service nicht erlaubt.
package/dist/cli.js CHANGED
@@ -2753,6 +2753,8 @@ var init_harness = __esm({
2753
2753
  init_js_yaml();
2754
2754
  import fs31 from "node:fs";
2755
2755
  import path32 from "node:path";
2756
+ import { spawnSync as spawnSync12 } from "node:child_process";
2757
+ import { createInterface } from "node:readline";
2756
2758
 
2757
2759
  // src/scanner.ts
2758
2760
  import fs from "node:fs";
@@ -6682,7 +6684,7 @@ USAGE
6682
6684
  fh <command> [subcommand] [options]
6683
6685
 
6684
6686
  SETUP
6685
- fh init Set up forgehive in the current project
6687
+ fh init [--yes] Set up forgehive in the current project
6686
6688
  fh confirm Activate capabilities (draft \u2192 confirmed)
6687
6689
  fh rollback Remove forgehive from the project
6688
6690
  fh status Show current project state
@@ -6759,41 +6761,77 @@ function loadClaudeMdBlock() {
6759
6761
  if (!fs31.existsSync(templatePath)) return "## forgehive\n\nSee .forgehive/ for configuration.";
6760
6762
  return fs31.readFileSync(templatePath, "utf8");
6761
6763
  }
6762
- if (command === "init") {
6763
- const forgehiveDirExists = fs31.existsSync(forgehiveDir);
6764
- if (forgehiveDirExists && !rest.includes("--force")) {
6765
- console.log(`\u26A0 .forgehive/ existiert bereits in diesem Projekt.`);
6766
- console.log(` Nutze 'fh init --force' um neu zu initialisieren (\xFCberschreibt capabilities.yaml).`);
6767
- console.log(` Nutze 'fh scan --update' um nur den Scan zu aktualisieren.`);
6768
- process.exit(0);
6764
+ async function promptConfirm(question) {
6765
+ if (!process.stdin.isTTY) return false;
6766
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
6767
+ return new Promise((resolve) => {
6768
+ rl.question(question, (answer) => {
6769
+ rl.close();
6770
+ const a = answer.trim().toLowerCase();
6771
+ resolve(a === "y" || a === "yes" || a === "");
6772
+ });
6773
+ });
6774
+ }
6775
+ function buildCapabilitySummary(ids) {
6776
+ if (ids.length === 0) return " Erkannt: (keine Capabilities)";
6777
+ const lines = [];
6778
+ for (let i = 0; i < ids.length && lines.length < 4; i += 4) {
6779
+ lines.push(" \u2022 " + ids.slice(i, i + 4).join(" \xB7 "));
6769
6780
  }
6770
- console.log("\u{1F50D} Analysiere Projekt...\n");
6771
- const scanResult = scan(projectRoot);
6772
- const tierCount = [1, 2, 3].map((t) => scanResult.signals.filter((s) => s.tier === t).length);
6773
- console.log(` \u2713 ${tierCount[0]} Technologie-Signale erkannt`);
6774
- console.log(` \u2713 ${tierCount[1]} Infrastruktur-Signale erkannt`);
6775
- console.log(` \u2713 ${tierCount[2]} Kontext-Signale erkannt`);
6776
- console.log();
6777
- const capMap = mapSignalsToCapabilities(scanResult);
6778
- const block = loadClaudeMdBlock();
6779
- writeForgehiveDir(projectRoot, scanResult, capMap, block);
6780
- const hash = computeHash(projectRoot);
6781
- fs31.writeFileSync(path32.join(forgehiveDir, ".scan-hash"), hash, "utf8");
6782
- const runtimeDir = path32.join(
6783
- path32.dirname(new URL(import.meta.url).pathname),
6784
- "..",
6785
- "forgehive"
6786
- );
6787
- initForgehiveRuntime(forgehiveDir, runtimeDir);
6788
- console.log("\u2713 .forgehive/ eingerichtet");
6789
- console.log("\u2713 CLAUDE.md aktualisiert\n");
6790
- console.log("Erkannte Capabilities:");
6791
- for (const cap of capMap.confirmed) {
6792
- console.log(` + ${cap.id} (aus ${cap.source})`);
6793
- }
6794
- console.log("\nN\xE4chster Schritt:");
6795
- console.log(" Pr\xFCfe .forgehive/capabilities.yaml und f\xFChre dann aus:");
6796
- console.log(" fh confirm\n");
6781
+ return " Erkannt:\n" + lines.join("\n");
6782
+ }
6783
+ if (command === "init") {
6784
+ (async () => {
6785
+ const gitCheck = spawnSync12("git", ["--version"], { stdio: "ignore" });
6786
+ if (gitCheck.error || gitCheck.status !== 0) {
6787
+ console.error("Fehler: git nicht gefunden.");
6788
+ console.error(" Installation: https://git-scm.com");
6789
+ process.exit(1);
6790
+ }
6791
+ const forgehiveDirExists = fs31.existsSync(forgehiveDir);
6792
+ if (forgehiveDirExists && !rest.includes("--force")) {
6793
+ console.log(`\u26A0 .forgehive/ existiert bereits in diesem Projekt.`);
6794
+ console.log(` Nutze 'fh init --force' um neu zu initialisieren (\xFCberschreibt capabilities.yaml).`);
6795
+ console.log(` Nutze 'fh scan --update' um nur den Scan zu aktualisieren.`);
6796
+ process.exit(0);
6797
+ }
6798
+ console.log("\u{1F50D} Analysiere Projekt...\n");
6799
+ const scanResult = scan(projectRoot);
6800
+ const tierCount = [1, 2, 3].map((t) => scanResult.signals.filter((s) => s.tier === t).length);
6801
+ console.log(` \u2713 ${tierCount[0]} Technologie-Signale erkannt`);
6802
+ console.log(` \u2713 ${tierCount[1]} Infrastruktur-Signale erkannt`);
6803
+ console.log(` \u2713 ${tierCount[2]} Kontext-Signale erkannt`);
6804
+ console.log();
6805
+ const capMap = mapSignalsToCapabilities(scanResult);
6806
+ const block = loadClaudeMdBlock();
6807
+ writeForgehiveDir(projectRoot, scanResult, capMap, block);
6808
+ const hash = computeHash(projectRoot);
6809
+ fs31.writeFileSync(path32.join(forgehiveDir, ".scan-hash"), hash, "utf8");
6810
+ const runtimeDir = path32.join(
6811
+ path32.dirname(new URL(import.meta.url).pathname),
6812
+ "..",
6813
+ "forgehive"
6814
+ );
6815
+ initForgehiveRuntime(forgehiveDir, runtimeDir);
6816
+ console.log("\u2713 forgehive initialisiert\n");
6817
+ console.log(buildCapabilitySummary(capMap.confirmed.map((c) => c.id)));
6818
+ console.log();
6819
+ if (subcommand === "--yes" || rest.includes("--yes")) {
6820
+ confirm(projectRoot);
6821
+ console.log("\u2713 Capabilities best\xE4tigt\n");
6822
+ } else {
6823
+ const ok = await promptConfirm(" Capabilities best\xE4tigen? [Y/n] ");
6824
+ if (ok) {
6825
+ confirm(projectRoot);
6826
+ console.log("\u2713 Capabilities best\xE4tigt\n");
6827
+ } else {
6828
+ console.log(" \xDCberpr\xFCfe .forgehive/capabilities.yaml, dann: fh confirm\n");
6829
+ }
6830
+ }
6831
+ })().catch((err) => {
6832
+ console.error(`Fehler: ${err.message}`);
6833
+ process.exit(1);
6834
+ });
6797
6835
  } else if (command === "confirm") {
6798
6836
  try {
6799
6837
  confirm(projectRoot);
@@ -7671,7 +7709,6 @@ Setze diese Umgebungsvariablen:`);
7671
7709
  } else if (subcommand === "onboard") {
7672
7710
  const outputArg = rest.includes("--output") ? rest[rest.indexOf("--output") + 1] : null;
7673
7711
  const outputPath = outputArg ?? path32.join(projectRoot, "ONBOARDING.md");
7674
- fs31.mkdirSync(path32.dirname(outputPath), { recursive: true });
7675
7712
  const doc = generateOnboardingDoc(projectRoot, forgehiveDir);
7676
7713
  fs31.writeFileSync(outputPath, doc, "utf8");
7677
7714
  console.log(`\u2714 Onboarding-Dokument geschrieben: ${outputPath}`);
@@ -7681,11 +7718,12 @@ Setze diese Umgebungsvariablen:`);
7681
7718
  const since = sinceArg ?? getLatestTag(projectRoot) ?? void 0;
7682
7719
  const rawLog = getGitLogSince(projectRoot, since);
7683
7720
  const commits = parseGitLog(rawLog);
7684
- let pkgVersion = "unreleased";
7721
+ let pkg = {};
7685
7722
  try {
7686
- pkgVersion = JSON.parse(fs31.readFileSync(path32.join(projectRoot, "package.json"), "utf8")).version ?? "unreleased";
7723
+ pkg = JSON.parse(fs31.readFileSync(path32.join(projectRoot, "package.json"), "utf8"));
7687
7724
  } catch {
7688
7725
  }
7726
+ const pkgVersion = pkg.version ?? "unreleased";
7689
7727
  const md = formatChangelog(commits, pkgVersion);
7690
7728
  const outputPath = outputArg ?? path32.join(projectRoot, "CHANGELOG.md");
7691
7729
  let existing = "";
@@ -7698,9 +7736,31 @@ Setze diese Umgebungsvariablen:`);
7698
7736
  console.error("Usage: fh docs adr <titel>");
7699
7737
  process.exit(1);
7700
7738
  }
7701
- const adrPath = createAdr(forgehiveDir, projectRoot, title);
7702
- const adrFilename = path32.relative(projectRoot, adrPath);
7703
- console.log(`\u2714 ADR erstellt: ${adrFilename}`);
7739
+ const adrsDir = path32.join(forgehiveDir, "memory", "adrs");
7740
+ fs31.mkdirSync(adrsDir, { recursive: true });
7741
+ const existing = fs31.readdirSync(adrsDir).filter((f) => f.endsWith(".md")).length;
7742
+ const adrId = String(existing + 1).padStart(4, "0");
7743
+ const slug = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
7744
+ const filename = `${adrId}-${slug}.md`;
7745
+ const content = `# ADR-${adrId}: ${title}
7746
+
7747
+ **Datum:** ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}
7748
+ **Status:** proposed
7749
+
7750
+ ## Kontext
7751
+
7752
+ (Beschreibe das Problem oder die Situation.)
7753
+
7754
+ ## Entscheidung
7755
+
7756
+ (Beschreibe die getroffene Entscheidung.)
7757
+
7758
+ ## Konsequenzen
7759
+
7760
+ (Beschreibe die Auswirkungen dieser Entscheidung.)
7761
+ `;
7762
+ fs31.writeFileSync(path32.join(adrsDir, filename), content, "utf8");
7763
+ console.log(`\u2714 ADR erstellt: .forgehive/memory/adrs/${filename}`);
7704
7764
  } else {
7705
7765
  console.error("Verf\xFCgbar: fh docs [list|user|api|onboard|changelog|adr <titel>]");
7706
7766
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forgehive",
3
- "version": "0.7.8",
3
+ "version": "0.7.9",
4
4
  "description": "Context-aware AI development environment — one binary, your stack.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -22,6 +22,7 @@
22
22
  "forgehive",
23
23
  "development"
24
24
  ],
25
+ "license": "Elastic-2.0",
25
26
  "engines": {
26
27
  "node": ">=18"
27
28
  },