bmad-visio 0.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.
package/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ William Mesiti
package/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # bmad-visio
2
+
3
+ Visualize [BMAD Method](https://github.com/bmad-method) epics and user stories from structured `.md` files on a localhost dashboard. Optionally uses local AI (Transformers.js) to match git commits to stories.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ npx bmad-visio
9
+ ```
10
+
11
+ Run from your project root. Auto-detects BMAD structure:
12
+
13
+ - `_bmad-output/planning-artifacts/` + `_bmad-output/implementation-artifacts/` (new BMAD)
14
+ - `docs/sprint-artifacts/epics/` + `docs/sprint-artifacts/stories/` (old BMAD)
15
+
16
+ ## Features
17
+
18
+ - **Epic overview** — Grid of all epics with story counts and progress
19
+ - **Kanban board** — Stories in 4 columns: To Do → Active → Review → Done
20
+ - **Drag & drop** — Move stories between columns, writes status back to `.md` files
21
+ - **Story detail** — Acceptance criteria, tasks with checkboxes, progress ring
22
+ - **Live editing** — Toggle AC and tasks directly, updates files on disk
23
+ - **Git commit matching** — AI-powered mapping of commits to stories (optional)
24
+
25
+ ## AI Commit Matching
26
+
27
+ Install the optional dependency for commit-to-story matching:
28
+
29
+ ```bash
30
+ npm install @huggingface/transformers
31
+ ```
32
+
33
+ The dashboard will then:
34
+
35
+ 1. Parse your git history
36
+ 2. Embed stories and commits with `all-MiniLM-L6-v2`
37
+ 3. Re-rank ambiguous matches with zero-shot NLI (`mobilebert-uncased-mnli`)
38
+ 4. Persist mappings in `bmad-visio/gitmap.json`
39
+ 5. Show related commits on each story's detail page
40
+
41
+ First run downloads models (~180MB total). Everything runs locally, no API keys needed.
42
+
43
+ ## Options
44
+
45
+ ```
46
+ npx bmad-visio [path] [options]
47
+
48
+ Arguments:
49
+ path Project root (default: .)
50
+
51
+ Options:
52
+ -p, --port <n> Port number (default: 3333)
53
+ --no-git Skip git commit matching
54
+ --debug Dump parsed data as JSON and exit
55
+ -h, --help Show help
56
+ ```
57
+
58
+ ## Status Mapping
59
+
60
+ | BMAD Status | Board Column |
61
+ | -------------------------- | ---------------- |
62
+ | `backlog`, `ready-for-dev` | To Do |
63
+ | `in-progress` | Active |
64
+ | `review` | Ready for Review |
65
+ | `done` | Done |
66
+
67
+ ## License
68
+
69
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env node
2
+ import path from "node:path";
3
+ import { parseBmadProject } from "./parser/index.js";
4
+ import { matchCommitsToStories } from "./git/index.js";
5
+ import { createServer } from "./server/index.js";
6
+ const args = process.argv.slice(2);
7
+ if (args.includes("--help") || args.includes("-h")) {
8
+ console.log(`
9
+ bmad-visio — Visualize BMAD epics, stories & git history
10
+
11
+ Usage:
12
+ npx bmad-visio [path] [options]
13
+
14
+ Arguments:
15
+ path Project root (default: .)
16
+
17
+ Options:
18
+ -p, --port <n> Port number (default: 3333)
19
+ --no-git Skip git commit matching
20
+ --debug Dump parsed data as JSON and exit
21
+ -h, --help Show this help
22
+
23
+ Detects BMAD structure automatically:
24
+ _bmad-output/planning-artifacts/ (new BMAD)
25
+ docs/sprint-artifacts/ (old BMAD)
26
+ `);
27
+ process.exit(0);
28
+ }
29
+ const portIdx = args.findIndex((a) => a === "-p" || a === "--port");
30
+ const port = portIdx !== -1 ? parseInt(args[portIdx + 1], 10) : 3333;
31
+ const debug = args.includes("--debug");
32
+ const noGit = args.includes("--no-git");
33
+ const dir = path.resolve(args.find((a) => !a.startsWith("-") && a !== String(port)) ?? ".");
34
+ console.log(`\n 📂 Scanning: ${dir}`);
35
+ const project = parseBmadProject({ dir });
36
+ const storyCount = project.epics.reduce((n, e) => n + e.stories.length, 0);
37
+ console.log(` ✅ Found ${project.epics.length} epics, ${storyCount} stories`);
38
+ if (debug) {
39
+ console.log(JSON.stringify(project.epics, null, 2));
40
+ process.exit(0);
41
+ }
42
+ // Git matching
43
+ if (!noGit) {
44
+ try {
45
+ const mappings = await matchCommitsToStories(project, dir);
46
+ project.commitMappings = mappings;
47
+ }
48
+ catch (err) {
49
+ console.log(` ⚠️ Git matching skipped: ${err.message}`);
50
+ }
51
+ }
52
+ else {
53
+ console.log(" ⏭️ Git matching skipped (--no-git)");
54
+ }
55
+ createServer(project, port);
56
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEnC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;IACnD,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;GAkBX,CAAC,CAAC;IACH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,QAAQ,CAAC,CAAC;AACpE,MAAM,IAAI,GAAG,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACrE,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AACvC,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;AAExC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CACtB,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,CAClE,CAAC;AAEF,OAAO,CAAC,GAAG,CAAC,qBAAqB,GAAG,EAAE,CAAC,CAAC;AAExC,MAAM,OAAO,GAAG,gBAAgB,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;AAE1C,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AAC3E,OAAO,CAAC,GAAG,CAAC,cAAc,OAAO,CAAC,KAAK,CAAC,MAAM,WAAW,UAAU,UAAU,CAAC,CAAC;AAE/E,IAAI,KAAK,EAAE,CAAC;IACV,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,eAAe;AACf,IAAI,CAAC,KAAK,EAAE,CAAC;IACX,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,qBAAqB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAC3D,OAAO,CAAC,cAAc,GAAG,QAAQ,CAAC;IACpC,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,OAAO,CAAC,GAAG,CAAC,+BAA+B,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAC5D,CAAC;AACH,CAAC;KAAM,CAAC;IACN,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;AACvD,CAAC;AAED,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { BmadProject, CommitMapping } from "../types/index.js";
2
+ export declare function matchCommitsToStories(project: BmadProject, projectDir: string, opts?: {
3
+ skipEmbedding?: boolean;
4
+ }): Promise<CommitMapping[]>;
@@ -0,0 +1,302 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { simpleGit } from "simple-git";
4
+ // ─── Math helpers ───────────────────────────────────────────────────
5
+ function dotProduct(a, b) {
6
+ let sum = 0;
7
+ for (let i = 0; i < a.length; i++)
8
+ sum += a[i] * b[i];
9
+ return sum;
10
+ }
11
+ // ─── Keyword overlap (Jaccard on lowercased tokens) ─────────────────
12
+ function tokenize(text) {
13
+ return new Set(text.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((t) => t.length > 2));
14
+ }
15
+ function jaccardSimilarity(a, b) {
16
+ if (a.size === 0 && b.size === 0)
17
+ return 0;
18
+ let intersection = 0;
19
+ for (const t of a) {
20
+ if (b.has(t))
21
+ intersection++;
22
+ }
23
+ return intersection / (a.size + b.size - intersection);
24
+ }
25
+ // ─── Build text for embedding / matching ────────────────────────────
26
+ function storyEmbedText(story) {
27
+ const parts = [`Story ${story.id}: ${story.title}`];
28
+ if (story.description)
29
+ parts.push(story.description);
30
+ if (story.acceptanceCriteria.length > 0) {
31
+ parts.push(story.acceptanceCriteria.map((ac) => ac.description).join(". "));
32
+ }
33
+ return parts.join(" — ").slice(0, 500);
34
+ }
35
+ /** Short label for zero-shot NLI — just title + story text */
36
+ function storyLabel(story) {
37
+ const parts = [story.title];
38
+ if (story.description)
39
+ parts.push(story.description.split("\n")[0]);
40
+ return parts.join(": ").slice(0, 150);
41
+ }
42
+ function commitEmbedText(message, body, files) {
43
+ const parts = [message];
44
+ if (body)
45
+ parts.push(body);
46
+ const filePart = files.slice(0, 10).join(", ");
47
+ if (filePart)
48
+ parts.push(`[files: ${filePart}]`);
49
+ return parts.join(" ").slice(0, 500);
50
+ }
51
+ function commitNliText(message, body) {
52
+ const parts = [message];
53
+ if (body)
54
+ parts.push(body);
55
+ return parts.join(". ").slice(0, 200);
56
+ }
57
+ // ─── Gitmap file I/O ────────────────────────────────────────────────
58
+ function getGitMapPath(projectDir) {
59
+ return path.join(projectDir, "bmad-visio", "gitmap.json");
60
+ }
61
+ function loadGitMap(projectDir) {
62
+ const p = getGitMapPath(projectDir);
63
+ if (fs.existsSync(p)) {
64
+ try {
65
+ const data = JSON.parse(fs.readFileSync(p, "utf-8"));
66
+ if (data.version === 1)
67
+ return { version: 2, mappings: data.mappings ?? {} };
68
+ return data;
69
+ }
70
+ catch { /* corrupted */ }
71
+ }
72
+ return { version: 2, mappings: {} };
73
+ }
74
+ function saveGitMap(projectDir, gitmap) {
75
+ const p = getGitMapPath(projectDir);
76
+ fs.mkdirSync(path.dirname(p), { recursive: true });
77
+ fs.writeFileSync(p, JSON.stringify({ version: 2, mappings: gitmap.mappings }, null, 2), "utf-8");
78
+ }
79
+ // ─── Model loaders (lazy, cached) ───────────────────────────────────
80
+ let _embedFn = null;
81
+ let _classifyFn = null;
82
+ let _transformersAvailable = null;
83
+ async function checkTransformers() {
84
+ if (_transformersAvailable !== null)
85
+ return _transformersAvailable;
86
+ try {
87
+ await import("@huggingface/transformers");
88
+ _transformersAvailable = true;
89
+ }
90
+ catch {
91
+ _transformersAvailable = false;
92
+ }
93
+ return _transformersAvailable;
94
+ }
95
+ async function getEmbedFn() {
96
+ if (_embedFn)
97
+ return _embedFn;
98
+ console.log(" 🤖 Loading embedding model...");
99
+ const { pipeline } = await import("@huggingface/transformers");
100
+ const extractor = await pipeline("feature-extraction", "Xenova/all-MiniLM-L6-v2");
101
+ console.log(" ✅ Embedding model loaded");
102
+ _embedFn = async (texts) => {
103
+ const results = [];
104
+ for (let i = 0; i < texts.length; i += 16) {
105
+ const batch = texts.slice(i, i + 16);
106
+ const output = await extractor(batch, { pooling: "mean", normalize: true });
107
+ results.push(...output.tolist());
108
+ }
109
+ return results;
110
+ };
111
+ return _embedFn;
112
+ }
113
+ async function getClassifyFn() {
114
+ if (_classifyFn)
115
+ return _classifyFn;
116
+ console.log(" 🧠 Loading zero-shot classifier for re-ranking...");
117
+ const { pipeline } = await import("@huggingface/transformers");
118
+ const classifier = await pipeline("zero-shot-classification", "Xenova/mobilebert-uncased-mnli");
119
+ console.log(" ✅ Classifier loaded");
120
+ _classifyFn = async (text, labels) => {
121
+ const result = await classifier(text, labels, { multi_label: true });
122
+ // Result shape: { sequence, labels: string[], scores: number[] }
123
+ return result.labels.map((label, i) => ({
124
+ label,
125
+ score: result.scores[i],
126
+ }));
127
+ };
128
+ return _classifyFn;
129
+ }
130
+ // ─── Scoring weights ────────────────────────────────────────────────
131
+ //
132
+ // Three-stage pipeline for the report:
133
+ // Stage 1 — Bi-encoder embedding: fast retrieval, narrows to top K
134
+ // Stage 2 — Heuristics: story ID regex + keyword overlap
135
+ // Stage 3 — Zero-shot NLI: re-ranks ambiguous candidates
136
+ //
137
+ // Final score = weighted combination of all signals.
138
+ const WEIGHTS = {
139
+ embedding: 0.35,
140
+ keyword: 0.15,
141
+ idBoost: 0.20, // only when an ID is detected
142
+ nli: 0.30,
143
+ };
144
+ const MATCH_THRESHOLD = 0.25; // on the combined scale
145
+ const RERANK_TOP_K = 3; // send top K to the NLI classifier
146
+ const RERANK_AMBIGUITY = 0.12; // trigger re-rank if gap between #1 and #2 is below this
147
+ const RERANK_CEILING = 0.55; // always re-rank if top score is below this
148
+ // ─── Main: match commits to stories ─────────────────────────────────
149
+ export async function matchCommitsToStories(project, projectDir, opts) {
150
+ const allStories = [];
151
+ for (const epic of project.epics)
152
+ allStories.push(...epic.stories);
153
+ if (allStories.length === 0)
154
+ return [];
155
+ // ── Git log ──
156
+ const git = simpleGit(projectDir);
157
+ let commits;
158
+ try {
159
+ const log = await git.log(["--name-only"]);
160
+ commits = log.all.map((entry) => ({
161
+ sha: entry.hash, message: entry.message,
162
+ body: entry.body?.trim() ?? "", date: entry.date,
163
+ files: (entry.diff?.files?.map((f) => f.file) ?? []),
164
+ }));
165
+ }
166
+ catch {
167
+ console.log(" ⚠️ Not a git repository or git not available");
168
+ return [];
169
+ }
170
+ if (commits.length === 0)
171
+ return [];
172
+ // ── Load gitmap, find new commits ──
173
+ const gitmap = loadGitMap(projectDir);
174
+ const newCommits = commits.filter((c) => !gitmap.mappings[c.sha]);
175
+ if (newCommits.length === 0) {
176
+ console.log(" 📋 All commits already mapped");
177
+ return Object.values(gitmap.mappings);
178
+ }
179
+ if (opts?.skipEmbedding)
180
+ return Object.values(gitmap.mappings);
181
+ // Check if @huggingface/transformers is installed (it's an optional dep)
182
+ if (!(await checkTransformers())) {
183
+ console.log(" ⚠️ @huggingface/transformers not installed — run: npm install @huggingface/transformers");
184
+ console.log(" Skipping AI commit matching. Dashboard will work without it.");
185
+ return Object.values(gitmap.mappings);
186
+ }
187
+ // ═══════════════════════════════════════════════════════════════════
188
+ // STAGE 1: Bi-encoder embedding — fast retrieval
189
+ // ═══════════════════════════════════════════════════════════════════
190
+ const embed = await getEmbedFn();
191
+ const storyIds = allStories.map((s) => s.id);
192
+ const storyIdSet = new Set(storyIds);
193
+ const storyTexts = allStories.map((s) => storyEmbedText(s));
194
+ const storyLabels = allStories.map((s) => storyLabel(s));
195
+ const storyTokens = storyTexts.map((t) => tokenize(t));
196
+ console.log(` 📝 Embedding ${storyTexts.length} stories...`);
197
+ const storyVecs = await embed(storyTexts);
198
+ console.log(` 🔗 Matching ${newCommits.length} new commits...`);
199
+ const commitTexts = newCommits.map((c) => commitEmbedText(c.message, c.body, c.files));
200
+ const commitVectors = await embed(commitTexts);
201
+ const allCandidates = [];
202
+ for (let ci = 0; ci < newCommits.length; ci++) {
203
+ const commit = newCommits[ci];
204
+ const cVec = commitVectors[ci];
205
+ const fullText = `${commit.message} ${commit.body}`;
206
+ const commitTokens = tokenize(fullText);
207
+ // Detect story ID references
208
+ const referencedIds = new Set();
209
+ const idPattern = /\b(\d+\.\d+)\b/g;
210
+ let m;
211
+ while ((m = idPattern.exec(fullText)) !== null) {
212
+ if (storyIdSet.has(m[1]))
213
+ referencedIds.add(m[1]);
214
+ }
215
+ const candidates = storyIds.map((sid, si) => ({
216
+ storyId: sid,
217
+ embeddingScore: dotProduct(cVec, storyVecs[si]),
218
+ idBoost: referencedIds.has(sid) ? 1.0 : 0.0,
219
+ keywordScore: jaccardSimilarity(commitTokens, storyTokens[si]),
220
+ nliScore: 0, // filled in stage 3
221
+ finalScore: 0, // computed after all stages
222
+ }));
223
+ // Pre-compute score without NLI to determine if re-rank is needed
224
+ for (const c of candidates) {
225
+ c.finalScore = c.embeddingScore * (WEIGHTS.embedding + WEIGHTS.nli) // NLI weight goes to embedding when skipped
226
+ + c.keywordScore * WEIGHTS.keyword
227
+ + c.idBoost * WEIGHTS.idBoost;
228
+ }
229
+ candidates.sort((a, b) => b.finalScore - a.finalScore);
230
+ // Decide if we need NLI re-ranking
231
+ const top = candidates[0];
232
+ const second = candidates[1];
233
+ const gap = top && second ? top.finalScore - second.finalScore : 1;
234
+ const needsRerank = top.finalScore < RERANK_CEILING || gap < RERANK_AMBIGUITY;
235
+ allCandidates.push({ commit, candidates, needsRerank });
236
+ }
237
+ // ═══════════════════════════════════════════════════════════════════
238
+ // STAGE 3: Zero-shot NLI re-ranking (only for ambiguous matches)
239
+ // ═══════════════════════════════════════════════════════════════════
240
+ const ambiguous = allCandidates.filter((cc) => cc.needsRerank);
241
+ if (ambiguous.length > 0) {
242
+ console.log(` 🧠 Re-ranking ${ambiguous.length}/${newCommits.length} ambiguous commits with NLI...`);
243
+ const classify = await getClassifyFn();
244
+ for (const cc of ambiguous) {
245
+ const topK = cc.candidates.slice(0, RERANK_TOP_K);
246
+ const commitText = commitNliText(cc.commit.message, cc.commit.body);
247
+ const labels = topK.map((c) => {
248
+ const idx = storyIds.indexOf(c.storyId);
249
+ return storyLabels[idx];
250
+ });
251
+ try {
252
+ const nliResults = await classify(commitText, labels);
253
+ // Map NLI scores back to candidates
254
+ for (const c of topK) {
255
+ const idx = storyIds.indexOf(c.storyId);
256
+ const label = storyLabels[idx];
257
+ const nliResult = nliResults.find((r) => r.label === label);
258
+ c.nliScore = nliResult?.score ?? 0;
259
+ }
260
+ }
261
+ catch (err) {
262
+ console.log(` ⚠️ NLI failed for "${cc.commit.message.slice(0, 40)}": ${err.message}`);
263
+ // Fall back — NLI scores stay at 0, embedding carries full weight
264
+ }
265
+ // Recompute final scores with NLI
266
+ for (const c of cc.candidates) {
267
+ c.finalScore =
268
+ c.embeddingScore * WEIGHTS.embedding +
269
+ c.keywordScore * WEIGHTS.keyword +
270
+ c.idBoost * WEIGHTS.idBoost +
271
+ c.nliScore * WEIGHTS.nli;
272
+ }
273
+ cc.candidates.sort((a, b) => b.finalScore - a.finalScore);
274
+ }
275
+ }
276
+ else {
277
+ console.log(` ⏭️ All matches confident, NLI re-ranking skipped`);
278
+ }
279
+ // ═══════════════════════════════════════════════════════════════════
280
+ // Build final mappings
281
+ // ═══════════════════════════════════════════════════════════════════
282
+ for (const cc of allCandidates) {
283
+ const best = cc.candidates[0];
284
+ const score = Math.min(Math.round(best.finalScore * 100) / 100, 1.0);
285
+ gitmap.mappings[cc.commit.sha] = {
286
+ sha: cc.commit.sha,
287
+ message: cc.commit.message,
288
+ body: cc.commit.body,
289
+ files: cc.commit.files,
290
+ date: cc.commit.date,
291
+ storyId: score >= MATCH_THRESHOLD ? best.storyId : null,
292
+ score,
293
+ };
294
+ }
295
+ saveGitMap(projectDir, gitmap);
296
+ const allMappings = Object.values(gitmap.mappings);
297
+ const matched = allMappings.filter((m) => m.storyId !== null).length;
298
+ const reranked = ambiguous.length;
299
+ console.log(` ✅ ${matched}/${allMappings.length} commits matched (${reranked} re-ranked by NLI)`);
300
+ return allMappings;
301
+ }
302
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/git/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { BmadProject } from "../types/index.js";
2
+ export declare const BOARD_COLUMNS: readonly ["todo", "active", "review", "done"];
3
+ export type BoardStatus = (typeof BOARD_COLUMNS)[number];
4
+ export interface ParseOptions {
5
+ dir: string;
6
+ mode?: "auto" | "bmad-new" | "bmad-old" | "flat";
7
+ }
8
+ export declare function parseBmadProject(opts: ParseOptions): BmadProject;
9
+ export declare function updateStoryStatus(project: BmadProject, epicId: string, storyId: string, newStatus: BoardStatus): {
10
+ ok: boolean;
11
+ error?: string;
12
+ };
13
+ export declare function toggleAcceptanceCriteria(project: BmadProject, epicId: string, storyId: string, acIndex: number, done: boolean): {
14
+ ok: boolean;
15
+ error?: string;
16
+ };
17
+ export declare function toggleTask(project: BmadProject, epicId: string, storyId: string, taskId: string, done: boolean): {
18
+ ok: boolean;
19
+ error?: string;
20
+ };