forgehive 0.7.5 → 0.7.6

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 CHANGED
@@ -14,8 +14,8 @@
14
14
  <p align="center">
15
15
  <img src="https://img.shields.io/badge/node-%3E%3D18-brightgreen" alt="Node.js ≥ 18">
16
16
  <img src="https://img.shields.io/badge/typescript-5.8-blue" alt="TypeScript">
17
- <img src="https://img.shields.io/badge/tests-267%20passing-success" alt="267 tests">
18
- <img src="https://img.shields.io/badge/bundle-247KB-lightgrey" alt="247KB bundle">
17
+ <img src="https://img.shields.io/badge/tests-273%20passing-success" alt="273 tests">
18
+ <img src="https://img.shields.io/badge/bundle-259KB-lightgrey" alt="259KB bundle">
19
19
  <img src="https://img.shields.io/badge/license-MIT-green" alt="MIT">
20
20
  </p>
21
21
 
@@ -45,9 +45,9 @@ Claude loses all project knowledge between sessions. forgehive solves this by wr
45
45
 
46
46
  ---
47
47
 
48
- ## Status: v0.7 — Stable
48
+ ## Status: v0.7.5 — Stable
49
49
 
50
- 267 passing tests back the commands listed below. The v0.7 feature set has been validated end-to-end.
50
+ 273 passing tests back the commands listed below. The v0.7 feature set has been validated end-to-end.
51
51
 
52
52
  **Stable — use with confidence:**
53
53
 
@@ -109,14 +109,14 @@ This makes both `fh` and `forgehive` available globally.
109
109
  git clone https://github.com/matharnica/forgehive
110
110
  cd forgehive
111
111
  npm install
112
- npm run build # compiles to dist/cli.js (~247 KB)
112
+ npm run build # compiles to dist/cli.js (~259 KB)
113
113
  npm link # makes 'fh' available globally
114
114
  ```
115
115
 
116
116
  Verify the installation:
117
117
 
118
118
  ```bash
119
- fh --version # should print 0.7.2
119
+ fh --version # should print 0.7.5
120
120
  fh --help # lists all available commands
121
121
  ```
122
122
 
@@ -332,6 +332,23 @@ Parses conventional commits (`feat:`, `fix:`, `chore:`, `docs:`, etc.) and group
332
332
 
333
333
  ---
334
334
 
335
+ ### Docs
336
+
337
+ ```bash
338
+ fh docs # list existing documentation
339
+ fh docs user [--output path] # generate user guide → docs/user-guide.md
340
+ fh docs api [--output path] # generate API reference → docs/api.md
341
+ fh docs onboard [--output path] # generate onboarding doc → ONBOARDING.md
342
+ fh docs changelog [--since tag] [--output path] # generate changelog → CHANGELOG.md
343
+ fh docs adr "<title>" # create Architecture Decision Record
344
+ ```
345
+
346
+ Generates documentation from your project's stack, memory, and git history. Each subcommand writes to a default path inside `docs/` (created if missing) or to the path given via `--output`. `fh docs user` and `fh docs api` write to `docs/user-guide.md` and `docs/api.md` respectively. `fh docs adr` creates a numbered ADR file in `.forgehive/memory/adrs/`.
347
+
348
+ > `fh docs onboard` and `fh onboard` both generate onboarding documentation — they share the same generator. `fh docs onboard` allows specifying a custom `--output` path; `fh onboard` writes to stdout by default.
349
+
350
+ ---
351
+
335
352
  ### Developer Metrics
336
353
 
337
354
  ```bash
@@ -847,9 +864,9 @@ Global credential store (chmod 600). Managed exclusively via `fh mcp auth` comma
847
864
  |---|---|
848
865
  | Runtime | Node.js ≥ 18, ESM |
849
866
  | Language | TypeScript |
850
- | Build | esbuild -> `dist/cli.js` (~247 KB, single bundle) |
867
+ | Build | esbuild -> `dist/cli.js` (~259 KB, single bundle) |
851
868
  | Type check | `tsc --noEmit` |
852
- | Tests | `node:test` (native) + tsx ESM loader, 267 tests |
869
+ | Tests | `node:test` (native) + tsx ESM loader, 273 tests |
853
870
  | Dependencies | `js-yaml` (sole runtime dependency) |
854
871
 
855
872
  ```bash
@@ -860,6 +877,19 @@ npm test # node --import tsx/esm --test test/*.test.ts
860
877
 
861
878
  ---
862
879
 
880
+ ## Changelog
881
+
882
+ | Version | What's new |
883
+ |---|---|
884
+ | **0.7.5** | `fh --version` reads from `package.json` (no longer hardcoded) |
885
+ | **0.7.4** | Party slash commands installed by `fh init` (`/party`, `/review-party`, `/design-party`, `/full-party`, `/security-party`) |
886
+ | **0.7.3** | User Docs generation (`fh docs user`, `fh docs api`, `fh docs list`) |
887
+ | **0.7.2** | `fh --help`, `fh init --force`, `fh story sprint`, `fh velocity show` fixes |
888
+ | **0.7.1** | Story Cards, Epics, Velocity tracking |
889
+ | **0.7.0** | CI, Map, Onboard, Changelog, Metrics, Sync, Background agents |
890
+
891
+ ---
892
+
863
893
  ## License
864
894
 
865
895
  MIT
package/dist/cli.js CHANGED
@@ -6460,7 +6460,7 @@ import fs30 from "node:fs";
6460
6460
  import path31 from "node:path";
6461
6461
  import { spawnSync as spawnSync11 } from "node:child_process";
6462
6462
  var SOURCE_EXTS = [".ts", ".tsx", ".js", ".jsx", ".py", ".go"];
6463
- var IGNORE_DIRS3 = ["node_modules", ".git", "dist", ".forgehive", "coverage", ".next", "build", "test"];
6463
+ var IGNORE_DIRS3 = ["node_modules", ".git", "dist", ".forgehive", "coverage", ".next", "build", "test", "__tests__", "spec"];
6464
6464
  var EXPORT_PATTERNS = [
6465
6465
  /^export\s+(?:async\s+)?function\s+(\w+)/gm,
6466
6466
  /^export\s+(?:const|let|var)\s+(\w+)/gm,
@@ -6476,6 +6476,27 @@ function readCapabilities2(forgehiveDir2) {
6476
6476
  return {};
6477
6477
  }
6478
6478
  }
6479
+ function extractCapabilityInfo(caps) {
6480
+ if (typeof caps.language === "string") {
6481
+ return {
6482
+ language: caps.language,
6483
+ packageManager: typeof caps.packageManager === "string" ? caps.packageManager : void 0,
6484
+ entryPoints: Array.isArray(caps.entryPoints) ? caps.entryPoints : void 0
6485
+ };
6486
+ }
6487
+ const confirmed = caps.capabilities?.confirmed ?? [];
6488
+ const ids = confirmed.map((c) => c.id ?? "").filter(Boolean);
6489
+ let language;
6490
+ if (ids.includes("typescript")) language = "typescript";
6491
+ else if (ids.includes("javascript")) language = "javascript";
6492
+ else if (ids.includes("python")) language = "python";
6493
+ else if (ids.includes("go")) language = "go";
6494
+ let packageManager;
6495
+ if (ids.includes("pnpm")) packageManager = "pnpm";
6496
+ else if (ids.includes("yarn")) packageManager = "yarn";
6497
+ else if (ids.includes("npm")) packageManager = "npm";
6498
+ return { language, packageManager };
6499
+ }
6479
6500
  function readMemoryFiles2(forgehiveDir2) {
6480
6501
  const memDir = path31.join(forgehiveDir2, "memory");
6481
6502
  if (!fs30.existsSync(memDir)) return {};
@@ -6518,6 +6539,7 @@ function walkSourceFiles(dir) {
6518
6539
  function generateUserGuide(projectRoot2, forgehiveDir2) {
6519
6540
  const projectName = path31.basename(projectRoot2);
6520
6541
  const caps = readCapabilities2(forgehiveDir2);
6542
+ const { language: lang, packageManager, entryPoints } = extractCapabilityInfo(caps);
6521
6543
  const memFiles = readMemoryFiles2(forgehiveDir2);
6522
6544
  const commits = getRecentCommits2(projectRoot2);
6523
6545
  const lines = [];
@@ -6528,16 +6550,15 @@ function generateUserGuide(projectRoot2, forgehiveDir2) {
6528
6550
  lines.push("## Overview");
6529
6551
  lines.push("");
6530
6552
  if (memFiles["project.md"]) {
6531
- const content = memFiles["project.md"].replace(/^---[\s\S]*?---\n/m, "").trim();
6553
+ const content = memFiles["project.md"].replace(/^---[\s\S]*?---\n/, "").trim();
6532
6554
  lines.push(content);
6533
6555
  } else {
6534
- lines.push(`${projectName} is a ${caps.language ?? "software"} application.`);
6556
+ lines.push(`${projectName} is a ${lang ?? "software"} application.`);
6535
6557
  }
6536
6558
  lines.push("");
6537
6559
  lines.push("## Requirements");
6538
6560
  lines.push("");
6539
- const pm = caps.packageManager ?? "npm";
6540
- const lang = caps.language;
6561
+ const pm = packageManager ?? "npm";
6541
6562
  if (lang === "typescript" || lang === "javascript") {
6542
6563
  lines.push("- **Node.js** \u2265 18");
6543
6564
  lines.push(`- **${pm}** (package manager)`);
@@ -6564,7 +6585,6 @@ function generateUserGuide(projectRoot2, forgehiveDir2) {
6564
6585
  }
6565
6586
  lines.push("```");
6566
6587
  lines.push("");
6567
- const entryPoints = caps.entryPoints;
6568
6588
  if (Array.isArray(entryPoints) && entryPoints.length > 0) {
6569
6589
  lines.push("## Getting Started");
6570
6590
  lines.push("");
@@ -6576,7 +6596,7 @@ function generateUserGuide(projectRoot2, forgehiveDir2) {
6576
6596
  if (memFiles["stack.md"]) {
6577
6597
  lines.push("## Configuration");
6578
6598
  lines.push("");
6579
- const content = memFiles["stack.md"].replace(/^---[\s\S]*?---\n/m, "").trim();
6599
+ const content = memFiles["stack.md"].replace(/^---[\s\S]*?---\n/, "").trim();
6580
6600
  lines.push(content);
6581
6601
  lines.push("");
6582
6602
  }
@@ -7665,8 +7685,8 @@ Setze diese Umgebungsvariablen:`);
7665
7685
  pkg = JSON.parse(fs31.readFileSync(path32.join(projectRoot, "package.json"), "utf8"));
7666
7686
  } catch {
7667
7687
  }
7668
- const version2 = pkg.version ?? "unreleased";
7669
- const md = formatChangelog(commits, version2);
7688
+ const pkgVersion = pkg.version ?? "unreleased";
7689
+ const md = formatChangelog(commits, pkgVersion);
7670
7690
  const outputPath = outputArg ?? path32.join(projectRoot, "CHANGELOG.md");
7671
7691
  let existing = "";
7672
7692
  if (fs31.existsSync(outputPath)) existing = fs31.readFileSync(outputPath, "utf8");
@@ -7680,7 +7700,7 @@ Setze diese Umgebungsvariablen:`);
7680
7700
  }
7681
7701
  const adrsDir = path32.join(forgehiveDir, "memory", "adrs");
7682
7702
  fs31.mkdirSync(adrsDir, { recursive: true });
7683
- const existing = fs31.existsSync(adrsDir) ? fs31.readdirSync(adrsDir).filter((f) => f.endsWith(".md")).length : 0;
7703
+ const existing = fs31.readdirSync(adrsDir).filter((f) => f.endsWith(".md")).length;
7684
7704
  const adrId = String(existing + 1).padStart(4, "0");
7685
7705
  const slug = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
7686
7706
  const filename = `${adrId}-${slug}.md`;
@@ -20,12 +20,22 @@ For interactive generation with editing, continue below.
20
20
  Ask the user: **"Was soll ich dokumentieren?"**
21
21
 
22
22
  Options:
23
- 1. **README update** — reflect recent features/changes
24
- 2. **API reference** — document endpoints or exported functions
25
- 3. **CHANGELOG** — run `fh changelog` and review the output
26
- 4. **ADR** — document an architecture decision (`fh memory adr "<title>"`)
27
- 5. **Inline docs** — add JSDoc/docstrings to changed functions
28
- 6. **ONBOARDING** — run `fh onboard` and review
23
+ 1. **User Guide** — write or update `docs/user-guide.md` for end users
24
+ 2. **README update** — reflect recent features/changes
25
+ 3. **API reference** — document endpoints or exported functions (`docs/api.md`)
26
+ 4. **CHANGELOG** — run `fh docs changelog` and review the output
27
+ 5. **ADR** — document an architecture decision (`fh docs adr "<title>"`)
28
+ 6. **Inline docs** — add JSDoc/docstrings to changed functions
29
+ 7. **ONBOARDING** — run `fh docs onboard` and review
30
+
31
+ ### For User Guide
32
+
33
+ 1. Run `fh docs user` to generate a baseline → `docs/user-guide.md`
34
+ 2. Read the generated file
35
+ 3. Read `.forgehive/memory/project.md` for additional context
36
+ 4. Expand sections that are thin: add real usage examples, explain non-obvious behavior, describe common workflows
37
+ 5. Remove or correct any placeholder text or auto-generated boilerplate that doesn't match the actual project
38
+ 6. Ensure the guide covers: installation, first run, core commands, configuration, troubleshooting
29
39
 
30
40
  ### For README updates
31
41
 
@@ -2,11 +2,11 @@ You are running a Full Party using ForgeHive.
2
2
 
3
3
  ## Full Party
4
4
 
5
- **Agents:** Nora (Senior Research Analyst), Eli (Documentation Architect), Remy (Product Strategist), Suki (Experience Designer), Viktor (Systems Architect), Kai (Principal Engineer), Sam (Quality Architect)
5
+ **Agents:** Nora (Senior Research Analyst), Eli (Documentation Architect), Remy (Product Strategist), Suki (Experience Designer), Viktor (Systems Architect), Kai (Principal Engineer), Sam (Quality Architect), Vera (Security Architect)
6
6
 
7
- **Mission:** Comprehensive multi-discipline review of a major feature or release — all seven specialists working in parallel on their domain.
7
+ **Mission:** Comprehensive multi-discipline review of a major feature or release — all eight specialists working in parallel on their domain.
8
8
 
9
- > **Warning:** This party spins up 7 worktrees simultaneously. Reserve this for major milestones, release candidates, and significant architectural changes. For smaller reviews, use `/review-party` or `/design-party` instead.
9
+ > **Warning:** This party spins up 8 worktrees simultaneously. Reserve this for major milestones, release candidates, and significant architectural changes. For smaller reviews, use `/review-party` or `/design-party` instead.
10
10
 
11
11
  ## Protocol
12
12
 
@@ -17,7 +17,7 @@ Run:
17
17
  fh party run --set full
18
18
  ```
19
19
 
20
- This spins up isolated worktrees for all 7 agents. Each works their specialization in parallel.
20
+ This spins up isolated worktrees for all 8 agents. Each works their specialization in parallel.
21
21
 
22
22
  ### Step 2: Define the milestone
23
23
 
@@ -63,6 +63,11 @@ Before the party starts, describe what is being reviewed — be specific:
63
63
  - Identifies high-risk paths with insufficient coverage
64
64
  - Produces: a test coverage and risk report
65
65
 
66
+ **Vera** (Security Architect) — threat modeling, attack surface analysis:
67
+ - Reviews authentication, authorization, and input handling
68
+ - Flags injection risks, insecure defaults, and data exposure
69
+ - Produces: a security review with severity-labeled findings
70
+
66
71
  ### Step 4: Check status
67
72
 
68
73
  After all agents complete:
package/package.json CHANGED
@@ -1,15 +1,29 @@
1
1
  {
2
2
  "name": "forgehive",
3
- "version": "0.7.5",
3
+ "version": "0.7.6",
4
4
  "description": "Context-aware AI development environment — one binary, your stack.",
5
5
  "type": "module",
6
6
  "bin": {
7
- "forgehive": "./dist/cli.js",
8
- "fh": "./dist/cli.js"
7
+ "forgehive": "dist/cli.js",
8
+ "fh": "dist/cli.js"
9
+ },
10
+ "files": [
11
+ "dist/",
12
+ "forgehive/"
13
+ ],
14
+ "keywords": [
15
+ "claude",
16
+ "claude-code",
17
+ "ai",
18
+ "mcp",
19
+ "agents",
20
+ "context",
21
+ "forgehive",
22
+ "development"
23
+ ],
24
+ "engines": {
25
+ "node": ">=18"
9
26
  },
10
- "files": ["dist/", "forgehive/"],
11
- "keywords": ["claude", "claude-code", "ai", "mcp", "agents", "context", "forgehive", "development"],
12
- "engines": { "node": ">=18" },
13
27
  "scripts": {
14
28
  "build": "esbuild src/cli.ts --bundle --platform=node --format=esm --outfile=dist/cli.js && chmod +x dist/cli.js",
15
29
  "prepublishOnly": "npm run build",