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.
- package/README.md +2 -2
- package/dist/cli.js +101 -41
- 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-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
|
|
6766
|
-
|
|
6767
|
-
|
|
6768
|
-
|
|
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
|
-
|
|
6771
|
-
|
|
6772
|
-
|
|
6773
|
-
|
|
6774
|
-
|
|
6775
|
-
|
|
6776
|
-
|
|
6777
|
-
|
|
6778
|
-
|
|
6779
|
-
|
|
6780
|
-
|
|
6781
|
-
|
|
6782
|
-
|
|
6783
|
-
|
|
6784
|
-
|
|
6785
|
-
|
|
6786
|
-
|
|
6787
|
-
|
|
6788
|
-
|
|
6789
|
-
|
|
6790
|
-
|
|
6791
|
-
|
|
6792
|
-
console.log(`
|
|
6793
|
-
|
|
6794
|
-
|
|
6795
|
-
|
|
6796
|
-
|
|
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
|
|
7721
|
+
let pkg = {};
|
|
7685
7722
|
try {
|
|
7686
|
-
|
|
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
|
|
7702
|
-
|
|
7703
|
-
|
|
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.
|
|
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
|
},
|