@sandrinio/vbounce 1.5.0 → 1.7.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.
Files changed (50) hide show
  1. package/README.md +108 -18
  2. package/bin/vbounce.mjs +291 -146
  3. package/brains/AGENTS.md +12 -10
  4. package/brains/CHANGELOG.md +99 -1
  5. package/brains/CLAUDE.md +29 -22
  6. package/brains/GEMINI.md +47 -9
  7. package/brains/SETUP.md +11 -5
  8. package/brains/claude-agents/architect.md +22 -6
  9. package/brains/claude-agents/developer.md +2 -2
  10. package/brains/claude-agents/devops.md +3 -0
  11. package/brains/claude-agents/qa.md +25 -9
  12. package/brains/copilot/copilot-instructions.md +49 -0
  13. package/brains/cursor-rules/vbounce-process.mdc +9 -7
  14. package/brains/windsurf/.windsurfrules +30 -0
  15. package/package.json +2 -4
  16. package/scripts/close_sprint.mjs +94 -0
  17. package/scripts/complete_story.mjs +113 -0
  18. package/scripts/doctor.mjs +144 -0
  19. package/scripts/init_gate_config.sh +151 -0
  20. package/scripts/init_sprint.mjs +121 -0
  21. package/scripts/pre_gate_common.sh +576 -0
  22. package/scripts/pre_gate_runner.sh +176 -0
  23. package/scripts/prep_arch_context.mjs +178 -0
  24. package/scripts/prep_qa_context.mjs +134 -0
  25. package/scripts/prep_sprint_context.mjs +118 -0
  26. package/scripts/prep_sprint_summary.mjs +154 -0
  27. package/scripts/sprint_trends.mjs +160 -0
  28. package/scripts/suggest_improvements.mjs +200 -0
  29. package/scripts/update_state.mjs +132 -0
  30. package/scripts/validate_bounce_readiness.mjs +125 -0
  31. package/scripts/validate_report.mjs +39 -2
  32. package/scripts/validate_sprint_plan.mjs +117 -0
  33. package/scripts/validate_state.mjs +99 -0
  34. package/skills/agent-team/SKILL.md +56 -21
  35. package/skills/agent-team/references/cleanup.md +42 -0
  36. package/skills/agent-team/references/delivery-sync.md +43 -0
  37. package/skills/agent-team/references/git-strategy.md +52 -0
  38. package/skills/agent-team/references/mid-sprint-triage.md +71 -0
  39. package/skills/agent-team/references/report-naming.md +34 -0
  40. package/skills/doc-manager/SKILL.md +5 -4
  41. package/skills/improve/SKILL.md +27 -1
  42. package/skills/lesson/SKILL.md +23 -0
  43. package/templates/delivery_plan.md +1 -1
  44. package/templates/hotfix.md +1 -1
  45. package/templates/sprint.md +65 -13
  46. package/templates/sprint_report.md +8 -1
  47. package/templates/story.md +1 -1
  48. package/scripts/pre_bounce_sync.sh +0 -37
  49. package/scripts/vbounce_ask.mjs +0 -98
  50. package/scripts/vbounce_index.mjs +0 -184
@@ -1,184 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import fs from 'fs';
4
- import path from 'path';
5
- import { connect } from '@lancedb/lancedb';
6
- import { pipeline } from '@xenova/transformers';
7
- import { marked } from 'marked';
8
- import { program } from 'commander';
9
-
10
- const LANCE_DIR = path.join(process.cwd(), '.bounce', '.lancedb');
11
-
12
- program
13
- .name('vbounce_index')
14
- .description('Index V-Bounce OS documents into local LanceDB')
15
- .argument('[path]', 'File or directory path to index (or use --all)')
16
- .option('--all', 'Index all standard V-Bounce directories')
17
- .parse(process.argv);
18
-
19
- const options = program.opts();
20
- const targetPath = program.args[0];
21
-
22
- // Initialize local embedding model wrapper
23
- class LocalEmbeddingFunction {
24
- constructor() {
25
- this.modelName = 'Xenova/all-MiniLM-L6-v2';
26
- this.extractor = null;
27
- }
28
-
29
- async init() {
30
- if (!this.extractor) {
31
- console.log(`Loading embedding model (${this.modelName})...`);
32
- this.extractor = await pipeline('feature-extraction', this.modelName, {
33
- quantized: true,
34
- });
35
- }
36
- }
37
-
38
- async computeSourceEmbeddings(texts) {
39
- await this.init();
40
- const embeddings = [];
41
- for (const text of texts) {
42
- const output = await this.extractor(text, { pooling: 'mean', normalize: true });
43
- embeddings.push(Array.from(output.data));
44
- }
45
- return embeddings;
46
- }
47
- }
48
-
49
- // Function to chunk Markdown files semantically (simplified for MVP)
50
- function chunkMarkdown(content, metadata) {
51
- const tokens = marked.lexer(content);
52
- const chunks = [];
53
- let currentHeader = 'General';
54
- let buffer = '';
55
-
56
- for (const token of tokens) {
57
- if (token.type === 'heading') {
58
- if (buffer.trim()) {
59
- chunks.push({ text: buffer.trim(), section: currentHeader, ...metadata });
60
- }
61
- currentHeader = token.text;
62
- buffer = `${token.raw}\n`;
63
- } else {
64
- buffer += `${token.raw}\n`;
65
- }
66
- }
67
-
68
- if (buffer.trim()) {
69
- chunks.push({ text: buffer.trim(), section: currentHeader, ...metadata });
70
- }
71
-
72
- return chunks;
73
- }
74
-
75
- async function indexFile(filePath, embedder) {
76
- console.log(`Processing file: ${filePath}`);
77
- const content = fs.readFileSync(filePath, 'utf-8');
78
- const basename = path.basename(filePath);
79
-
80
- let type = 'unknown';
81
- if (filePath.includes('LESSONS.md')) type = 'lesson';
82
- else if (filePath.includes('ROADMAP.md')) type = 'adr';
83
- else if (filePath.includes('.bounce/reports')) type = 'report';
84
- else if (filePath.includes('product_plans')) type = 'plan';
85
- else if (filePath.includes('vdocs')) type = 'documentation';
86
-
87
- const metadata = { file: basename, type };
88
- const chunks = chunkMarkdown(content, metadata);
89
-
90
- if (chunks.length === 0) return [];
91
-
92
- console.log(` Extracted ${chunks.length} chunks. Generating embeddings...`);
93
-
94
- const textsToEmbed = chunks.map(c => `[${c.type} - ${c.file} - ${c.section}]\n${c.text}`);
95
- const vectors = await embedder.computeSourceEmbeddings(textsToEmbed);
96
-
97
- return chunks.map((chunk, i) => ({
98
- id: `${chunk.file}-${i}`,
99
- file: chunk.file,
100
- type: chunk.type,
101
- section: chunk.section,
102
- text: chunk.text,
103
- vector: vectors[i]
104
- }));
105
- }
106
-
107
- async function main() {
108
- if (!targetPath && !options.all) {
109
- console.error("Error: Must specify a path or use --all");
110
- process.exit(1);
111
- }
112
-
113
- const embedder = new LocalEmbeddingFunction();
114
-
115
- // Ensure table exists
116
- if (!fs.existsSync(LANCE_DIR)) {
117
- fs.mkdirSync(LANCE_DIR, { recursive: true });
118
- }
119
-
120
- const db = await connect(LANCE_DIR);
121
- let table;
122
-
123
- try {
124
- table = await db.openTable('vbounce_context');
125
- } catch (e) {
126
- // Table doesn't exist, will create dynamically on first insert
127
- console.log("Creating new vbounce_context table...");
128
- }
129
-
130
- const filesToIndex = [];
131
-
132
- function walkDir(dir) {
133
- if (!fs.existsSync(dir)) return;
134
- const files = fs.readdirSync(dir);
135
- for (const file of files) {
136
- const fullPath = path.join(dir, file);
137
- const stat = fs.statSync(fullPath);
138
- if (stat.isDirectory()) {
139
- walkDir(fullPath);
140
- } else if (fullPath.endsWith('.md')) {
141
- filesToIndex.push(fullPath);
142
- }
143
- }
144
- }
145
-
146
- if (options.all) {
147
- if (fs.existsSync('LESSONS.md')) filesToIndex.push('LESSONS.md');
148
- if (fs.existsSync('ROADMAP.md')) filesToIndex.push('ROADMAP.md');
149
- walkDir('product_plans');
150
- walkDir('vdocs');
151
- walkDir('.bounce/reports');
152
- } else if (targetPath) {
153
- const stat = fs.statSync(targetPath);
154
- if (stat.isFile()) {
155
- filesToIndex.push(targetPath);
156
- } else if (stat.isDirectory()) {
157
- walkDir(targetPath);
158
- }
159
- }
160
-
161
- if (filesToIndex.length === 0) {
162
- console.log("No files found to index.");
163
- process.exit(0);
164
- }
165
-
166
- let allRecords = [];
167
- for (const file of filesToIndex) {
168
- const records = await indexFile(file, embedder);
169
- allRecords = allRecords.concat(records);
170
- }
171
-
172
- if (allRecords.length > 0) {
173
- if (table) {
174
- console.log(`Adding ${allRecords.length} records to existing table...`);
175
- await table.add(allRecords);
176
- } else {
177
- console.log(`Creating table with ${allRecords.length} records...`);
178
- table = await db.createTable('vbounce_context', allRecords);
179
- }
180
- console.log(`Successfully indexed into LanceDB.`);
181
- }
182
- }
183
-
184
- main().catch(console.error);