@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
package/README.md CHANGED
@@ -38,22 +38,12 @@ V-Bounce OS organizes planning documents (`product_plans/`) through a strict sta
38
38
 
39
39
  ## 🛠️ The Tech Stack
40
40
 
41
- V-Bounce OS is built to be **local-first, privacy-conscious, and blazing fast**.
41
+ V-Bounce OS is built to be **local-first, privacy-conscious, and dependency-light**.
42
42
 
43
- - **Vector Database**: [LanceDB](https://lancedb.com/)A serverless, local vector DB used to store and query project context.
44
- - **Embeddings**: [Xenova Transformers](https://github.com/xenova/transformers.js) Local execution of `all-MiniLM-L6-v2`. **No private code is ever sent to external embedding APIs for RAG.**
45
- - **Runtime**: Node.jsPowering the validation pipeline and semantic search engine.
46
- - **Data Contract**: YAML Frontmatter + Markdown Ensures human-readable agent handoffs that are also strictly machine-parsable.
47
-
48
- ---
49
-
50
- ## 🧠 Semantic Context (Local RAG)
51
-
52
- V-Bounce OS doesn't just dump your entire codebase into a prompt. It uses **Retrieval-Augmented Generation (RAG)** to find only the rules that matter right now.
53
-
54
- 1. **Indexing**: The `pre_bounce_sync.sh` script crawls your `product_plans/`, `LESSONS.md`, and `Roadmap ADRs`, converting them into searchable vectors.
55
- 2. **Querying**: Agents use the built-in `./scripts/vbounce_ask.mjs` tool to ask questions like *"What are the architectural constraints for auth?"* or *"What mistakes did we make with the last React component?"*.
56
- 3. **Targeted Context**: The agent receives only the most relevant 3-5 snippets of project history, preventing context-window bloat and improving instruction following.
43
+ - **Runtime**: Node.jsPowering the validation pipeline, context preparation, and CLI.
44
+ - **Data Contract**: YAML Frontmatter + Markdown Human-readable agent handoffs that are also strictly machine-parsable.
45
+ - **State Management**: `.bounce/state.json`Machine-readable sprint state for instant crash recovery without re-reading documents.
46
+ - **Context Budget**: On-demand prep scripts (`vbounce prep sprint/qa/arch`) generate capped context packs no embedding or vector DB required.
57
47
 
58
48
  ---
59
49
 
@@ -80,11 +70,111 @@ npx @sandrinio/vbounce install codex
80
70
 
81
71
  ### What gets installed?
82
72
  - **Agent Instructions:** The "Brain" file (e.g., `CLAUDE.md`, `.cursor/rules/`) that teaches your AI how to follow the V-Bounce process.
83
- - **Templates:** Markdown templates for your Charter, Roadmap, Epics, and Stories.
84
- - **Bundled Scripts:** Our validation pipeline (`validate_report.mjs`) and RAG synchronization engine (`pre_bounce_sync.sh`).
85
- - **Autonomous RAG Setup:** The installer automatically runs `npm install` for required libraries and initializes your local LanceDB knowledge base (`.bounce/.lancedb/`).
73
+ - **Templates:** Markdown templates for your Charter, Roadmap, Epics, Stories, Sprint Plans, and Delivery Plans.
74
+ - **Bundled Scripts:** 16+ automation scripts — validation pipeline, context preparation, state management, sprint lifecycle, and the self-improvement loop.
75
+ - **Lightweight Dependencies:** The installer runs `npm install` for `js-yaml`, `marked`, and `commander` nothing else. No vector DBs, no embedding models.
86
76
  - **vdoc Integration:** The installer offers to install [`@sandrinio/vdoc`](https://github.com/sandrinio/vdoc) for your platform — enabling automatic semantic product documentation generation via the Scribe agent.
87
77
 
78
+ After installing, run `vbounce doctor` to verify your setup is complete.
79
+
80
+ ---
81
+
82
+ ## 🛠️ The `vbounce` CLI
83
+
84
+ All V-Bounce OS operations route through a unified CLI. Every command is designed to be run by the Team Lead agent — not just humans.
85
+
86
+ ```bash
87
+ # Sprint lifecycle
88
+ vbounce sprint init S-01 D-01 # Initialize sprint state.json + plan dir
89
+ vbounce sprint close S-01 # Validate terminal states, archive, close
90
+
91
+ # Story lifecycle
92
+ vbounce story complete STORY-001-01-login # Update state.json + sprint plan §4
93
+
94
+ # State management (crash recovery)
95
+ vbounce state show # Print current state.json
96
+ vbounce state update STORY-001-01-login "QA Passed" # Update story state
97
+ vbounce state update STORY-001-01-login "Bouncing" --qa-bounce # Increment QA bounce
98
+
99
+ # Context preparation (context budget management)
100
+ vbounce prep sprint S-01 # Generate sprint-context-S-01.md (≤200 lines)
101
+ vbounce prep qa STORY-001-01-login # Generate qa-context-STORY-ID.md (≤300 lines)
102
+ vbounce prep arch STORY-001-01-login # Generate arch-context with truncated diff
103
+
104
+ # Validation gates
105
+ vbounce validate report .bounce/reports/STORY-001-01-login-qa.md
106
+ vbounce validate state # Validate state.json schema
107
+ vbounce validate sprint S-01 # Validate sprint plan structure + cross-refs
108
+ vbounce validate ready STORY-001-01-login # Pre-bounce readiness gate
109
+
110
+ # Self-improvement loop
111
+ vbounce trends # Compute sprint metrics → .bounce/trends.md
112
+ vbounce suggest S-01 # Generate improvement suggestions
113
+
114
+ # Framework health
115
+ vbounce doctor # Check all required files, scripts, templates
116
+ ```
117
+
118
+ ---
119
+
120
+ ## 🔄 State Management & Crash Recovery
121
+
122
+ V-Bounce OS tracks sprint state in `.bounce/state.json` — a machine-readable snapshot that survives context resets and session interruptions.
123
+
124
+ ```json
125
+ {
126
+ "sprint_id": "S-01",
127
+ "delivery_id": "D-01",
128
+ "current_phase": "bouncing",
129
+ "last_action": "QA failed STORY-001-01-login — bounce 1",
130
+ "stories": {
131
+ "STORY-001-01-login": {
132
+ "state": "Bouncing",
133
+ "qa_bounces": 1,
134
+ "arch_bounces": 0,
135
+ "worktree": ".worktrees/STORY-001-01-login",
136
+ "updated_at": "2026-03-12T10:00:00Z"
137
+ }
138
+ }
139
+ }
140
+ ```
141
+
142
+ When a new session starts, the Team Lead reads `state.json` in under 5 seconds to know exactly where the sprint left off — no re-reading 10 markdown files.
143
+
144
+ ---
145
+
146
+ ## 📊 Self-Improvement Loop
147
+
148
+ V-Bounce OS tracks its own performance and suggests improvements automatically.
149
+
150
+ 1. **Root Cause Tagging**: Every QA and Architect FAIL report includes a `root_cause:` field (e.g., `missing_tests`, `adr_violation`, `spec_ambiguity`) that feeds into trend analysis.
151
+ 2. **Sprint Trends**: `vbounce trends` scans all archived reports to compute first-pass rate, average bounce count, correction tax, and root cause breakdown per sprint.
152
+ 3. **Improvement Suggestions**: `vbounce suggest S-{XX}` reads trends, LESSONS.md, and the improvement log to flag stale lessons, recurring failure patterns, and graduation candidates.
153
+ 4. **Improvement Log**: `.bounce/improvement-log.md` tracks every suggestion with Applied/Rejected/Deferred status — so nothing falls through the cracks.
154
+
155
+ ---
156
+
157
+ ## 🔧 Tool Tier Model
158
+
159
+ V-Bounce OS supports four tiers of AI tools with dedicated brain files for each.
160
+
161
+ | Tier | Tools | Brain File | Capabilities |
162
+ |------|-------|------------|--------------|
163
+ | **Tier 1** | Claude Code | `brains/CLAUDE.md` | Full orchestration — spawns subagents, manages state, runs all CLI commands |
164
+ | **Tier 2** | Gemini CLI, OpenAI Codex | `brains/GEMINI.md`, `brains/codex/` | Single-agent — follows bounce loop, reads state.json, all CLI commands |
165
+ | **Tier 3** | Cursor | `brains/cursor-rules/` | Role-specific context injection via `.cursor/rules/` MDC files |
166
+ | **Tier 4** | GitHub Copilot, Windsurf | `brains/copilot/`, `brains/windsurf/` | Awareness mode — checklist-driven, reads state.json, CLI commands for safe operations |
167
+
168
+ Install the appropriate brain for your tool:
169
+ ```bash
170
+ npx @sandrinio/vbounce install claude # Tier 1
171
+ npx @sandrinio/vbounce install gemini # Tier 2
172
+ npx @sandrinio/vbounce install cursor # Tier 3
173
+ npx @sandrinio/vbounce install vscode # Tier 4
174
+ ```
175
+
176
+ ---
177
+
88
178
  ### 🧰 The Bundled Skills
89
179
  V-Bounce OS installs a powerful suite of specialized markdown `skills/` directly into your workspace. These act as modular capabilities you can invoke dynamically or that the Team Lead agent will invoke automatically during the SDLC process:
90
180
 
package/bin/vbounce.mjs CHANGED
@@ -5,7 +5,7 @@ import path from 'path';
5
5
  import { fileURLToPath } from 'url';
6
6
  import readline from 'readline';
7
7
 
8
- import { execSync } from 'child_process';
8
+ import { execSync, spawnSync } from 'child_process';
9
9
 
10
10
  const __filename = fileURLToPath(import.meta.url);
11
11
  const __dirname = path.dirname(__filename);
@@ -13,7 +13,7 @@ const pkgRoot = path.join(__dirname, '..');
13
13
 
14
14
  const args = process.argv.slice(2);
15
15
  const command = args[0];
16
- const targetPlatform = args[1]?.toLowerCase();
16
+ const sub = args[1];
17
17
 
18
18
  if (command === '-v' || command === '--version') {
19
19
  const pkgPath = path.join(pkgRoot, 'package.json');
@@ -26,7 +26,32 @@ if (command === '-v' || command === '--version') {
26
26
  process.exit(0);
27
27
  }
28
28
 
29
- // Utility for interactive prompt
29
+ // ---------------------------------------------------------------------------
30
+ // Script runner helper
31
+ // ---------------------------------------------------------------------------
32
+
33
+ /**
34
+ * Run a Node.js script from the scripts/ directory with forwarded args.
35
+ * @param {string} scriptName - filename inside scripts/ (e.g. 'doctor.mjs')
36
+ * @param {string[]} scriptArgs - additional CLI arguments
37
+ */
38
+ function runScript(scriptName, scriptArgs = []) {
39
+ const scriptPath = path.join(pkgRoot, 'scripts', scriptName);
40
+ if (!fs.existsSync(scriptPath)) {
41
+ console.error(`Error: Script not found: scripts/${scriptName}`);
42
+ console.error('Run `vbounce doctor` to check which scripts are missing.');
43
+ process.exit(1);
44
+ }
45
+ const result = spawnSync(process.execPath, [scriptPath, ...scriptArgs], {
46
+ stdio: 'inherit',
47
+ cwd: process.cwd()
48
+ });
49
+ process.exit(result.status ?? 0);
50
+ }
51
+
52
+ // ---------------------------------------------------------------------------
53
+ // Utility for interactive prompt (used by install)
54
+ // ---------------------------------------------------------------------------
30
55
  const rl = readline.createInterface({
31
56
  input: process.stdin,
32
57
  output: process.stdout
@@ -34,14 +59,33 @@ const rl = readline.createInterface({
34
59
 
35
60
  const askQuestion = (query) => new Promise(resolve => rl.question(query, resolve));
36
61
 
62
+ // ---------------------------------------------------------------------------
63
+ // Help text
64
+ // ---------------------------------------------------------------------------
65
+
37
66
  function displayHelp() {
38
67
  console.log(`
39
- 🎯 V-Bounce OS Installer
68
+ V-Bounce OS CLI
40
69
 
41
70
  Usage:
42
- npx vbounce install <platform>
43
-
44
- Supported Platforms:
71
+ vbounce install <platform> Install V-Bounce OS into a project
72
+ vbounce state show Show current sprint state
73
+ vbounce state update <storyId> <state|--qa-bounce>
74
+ vbounce sprint init <sprintId> <deliveryId> [--stories STORY-001,...]
75
+ vbounce sprint close <sprintId>
76
+ vbounce story complete <storyId> [options]
77
+ vbounce validate report <file> Validate agent report YAML
78
+ vbounce validate state Validate state.json
79
+ vbounce validate sprint [file] Validate Sprint Plan
80
+ vbounce validate ready <storyId> Pre-bounce gate check
81
+ vbounce prep qa <storyId> Generate QA context pack
82
+ vbounce prep arch <storyId> Generate Architect context pack
83
+ vbounce prep sprint <sprintId> Generate Sprint context pack
84
+ vbounce trends Cross-sprint trend analysis
85
+ vbounce suggest <sprintId> Generate improvement suggestions
86
+ vbounce doctor Validate all configs and state files
87
+
88
+ Install Platforms:
45
89
  claude : Installs CLAUDE.md and Claude Code subagents
46
90
  cursor : Installs modular .cursor/rules/
47
91
  gemini : Installs GEMINI.md and Antigravity skills
@@ -52,179 +96,280 @@ Supported Platforms:
52
96
  process.exit(0);
53
97
  }
54
98
 
55
- if (!command || command !== 'install' || !targetPlatform) {
56
- displayHelp();
57
- }
99
+ // ---------------------------------------------------------------------------
100
+ // Route commands
101
+ // ---------------------------------------------------------------------------
58
102
 
59
- const CWD = process.cwd();
60
-
61
- // Map vbounce platform names to vdoc platform names
62
- const vdocPlatformMap = {
63
- claude: 'claude',
64
- cursor: 'cursor',
65
- gemini: 'gemini',
66
- codex: 'agents',
67
- vscode: 'vscode',
68
- copilot: 'vscode'
69
- };
70
-
71
- const platformMappings = {
72
- claude: [
73
- { src: 'brains/CLAUDE.md', dest: 'CLAUDE.md' },
74
- { src: 'brains/claude-agents', dest: '.claude/agents' },
75
- { src: 'templates', dest: 'templates' },
76
- { src: 'skills', dest: 'skills' },
77
- { src: 'scripts', dest: 'scripts' }
78
- ],
79
- cursor: [
80
- { src: 'brains/cursor-rules', dest: '.cursor/rules' },
81
- { src: 'templates', dest: 'templates' },
82
- { src: 'skills', dest: 'skills' },
83
- { src: 'scripts', dest: 'scripts' }
84
- ],
85
- gemini: [
86
- { src: 'brains/GEMINI.md', dest: 'GEMINI.md' },
87
- { src: 'templates', dest: 'templates' },
88
- { src: 'skills', dest: 'skills' },
89
- { src: 'skills', dest: '.agents/skills' },
90
- { src: 'scripts', dest: 'scripts' }
91
- ],
92
- codex: [
93
- { src: 'brains/AGENTS.md', dest: 'AGENTS.md' },
94
- { src: 'templates', dest: 'templates' },
95
- { src: 'skills', dest: 'skills' },
96
- { src: 'scripts', dest: 'scripts' }
97
- ],
98
- vscode: [
99
- { src: 'brains/CLAUDE.md', dest: '.github/copilot-instructions.md' },
100
- { src: 'templates', dest: 'templates' },
101
- { src: 'skills', dest: 'skills' },
102
- { src: 'scripts', dest: 'scripts' }
103
- ],
104
- copilot: [
105
- { src: 'brains/CLAUDE.md', dest: '.github/copilot-instructions.md' },
106
- { src: 'templates', dest: 'templates' },
107
- { src: 'skills', dest: 'skills' },
108
- { src: 'scripts', dest: 'scripts' }
109
- ]
110
- };
111
-
112
- const mapping = platformMappings[targetPlatform];
113
-
114
- if (!mapping) {
115
- console.error(`Error: Unsupported platform '${targetPlatform}'.\n`);
103
+ if (!command || command === 'help' || command === '--help' || command === '-h') {
104
+ rl.close();
116
105
  displayHelp();
117
106
  }
118
107
 
119
- console.log(`\n🚀 Preparing to install V-Bounce OS for \x1b[36m${targetPlatform}\x1b[0m...\n`);
120
-
121
- const toCopy = [];
122
- const toOverwrite = [];
108
+ // -- state --
109
+ if (command === 'state') {
110
+ rl.close();
111
+ if (sub === 'show') {
112
+ runScript('update_state.mjs', ['--show']);
113
+ } else if (sub === 'update') {
114
+ // vbounce state update <storyId> <newState|--qa-bounce>
115
+ runScript('update_state.mjs', args.slice(2));
116
+ } else {
117
+ console.error(`Unknown state subcommand: ${sub}`);
118
+ console.error('Usage: vbounce state show | vbounce state update <storyId> <state|--qa-bounce>');
119
+ process.exit(1);
120
+ }
121
+ }
123
122
 
124
- mapping.forEach(rule => {
125
- const sourcePath = path.join(pkgRoot, rule.src);
126
- const destPath = path.join(CWD, rule.dest);
123
+ // -- sprint --
124
+ if (command === 'sprint') {
125
+ rl.close();
126
+ if (sub === 'init') {
127
+ runScript('init_sprint.mjs', args.slice(2));
128
+ } else if (sub === 'close') {
129
+ runScript('close_sprint.mjs', args.slice(2));
130
+ } else {
131
+ console.error(`Unknown sprint subcommand: ${sub}`);
132
+ console.error('Usage: vbounce sprint init <sprintId> <deliveryId> | vbounce sprint close <sprintId>');
133
+ process.exit(1);
134
+ }
135
+ }
127
136
 
128
- if (!fs.existsSync(sourcePath)) {
129
- return; // Source does not exist internally, skip
137
+ // -- story --
138
+ if (command === 'story') {
139
+ rl.close();
140
+ if (sub === 'complete') {
141
+ runScript('complete_story.mjs', args.slice(2));
142
+ } else {
143
+ console.error(`Unknown story subcommand: ${sub}`);
144
+ console.error('Usage: vbounce story complete <storyId> [options]');
145
+ process.exit(1);
130
146
  }
147
+ }
131
148
 
132
- if (fs.existsSync(destPath)) {
133
- toOverwrite.push(rule.dest);
149
+ // -- validate --
150
+ if (command === 'validate') {
151
+ rl.close();
152
+ if (sub === 'report') {
153
+ runScript('validate_report.mjs', args.slice(2));
154
+ } else if (sub === 'state') {
155
+ runScript('validate_state.mjs', args.slice(2));
156
+ } else if (sub === 'sprint') {
157
+ runScript('validate_sprint_plan.mjs', args.slice(2));
158
+ } else if (sub === 'ready') {
159
+ runScript('validate_bounce_readiness.mjs', args.slice(2));
134
160
  } else {
135
- toCopy.push(rule.dest);
161
+ console.error(`Unknown validate subcommand: ${sub}`);
162
+ console.error('Usage: vbounce validate report <file> | state | sprint [file] | ready <storyId>');
163
+ process.exit(1);
136
164
  }
137
- });
165
+ }
138
166
 
139
- if (toCopy.length > 0) {
140
- console.log('The following will be \x1b[32mCREATED\x1b[0m:');
141
- toCopy.forEach(f => console.log(` + ${f}`));
167
+ // -- prep --
168
+ if (command === 'prep') {
169
+ rl.close();
170
+ if (sub === 'qa') {
171
+ runScript('prep_qa_context.mjs', args.slice(2));
172
+ } else if (sub === 'arch') {
173
+ runScript('prep_arch_context.mjs', args.slice(2));
174
+ } else if (sub === 'sprint') {
175
+ runScript('prep_sprint_context.mjs', args.slice(2));
176
+ } else {
177
+ console.error(`Unknown prep subcommand: ${sub}`);
178
+ console.error('Usage: vbounce prep qa <storyId> | arch <storyId> | sprint <sprintId>');
179
+ process.exit(1);
180
+ }
142
181
  }
143
182
 
144
- if (toOverwrite.length > 0) {
145
- console.log('\nThe following will be \x1b[33mOVERWRITTEN\x1b[0m:');
146
- toOverwrite.forEach(f => console.log(` ! ${f}`));
183
+ // -- trends --
184
+ if (command === 'trends') {
185
+ rl.close();
186
+ runScript('sprint_trends.mjs', args.slice(1));
147
187
  }
148
188
 
149
- console.log('');
189
+ // -- suggest --
190
+ if (command === 'suggest') {
191
+ rl.close();
192
+ runScript('suggest_improvements.mjs', args.slice(1));
193
+ }
150
194
 
151
- askQuestion('Proceed with installation? [y/N] ').then(async answer => {
195
+ // -- doctor --
196
+ if (command === 'doctor') {
152
197
  rl.close();
153
- const confirmation = answer.trim().toLowerCase();
198
+ runScript('doctor.mjs', args.slice(1));
199
+ }
200
+
201
+ // ---------------------------------------------------------------------------
202
+ // install command (original functionality)
203
+ // ---------------------------------------------------------------------------
204
+
205
+ if (command === 'install') {
206
+ const targetPlatform = sub?.toLowerCase();
154
207
 
155
- if (confirmation !== 'y' && confirmation !== 'yes') {
156
- console.log('\n❌ Installation cancelled.\n');
157
- process.exit(0);
208
+ if (!targetPlatform) {
209
+ rl.close();
210
+ displayHelp();
158
211
  }
159
212
 
160
- console.log('\n📦 Installing files...');
213
+ const CWD = process.cwd();
214
+
215
+ // Map vbounce platform names to vdoc platform names
216
+ const vdocPlatformMap = {
217
+ claude: 'claude',
218
+ cursor: 'cursor',
219
+ gemini: 'gemini',
220
+ codex: 'agents',
221
+ vscode: 'vscode',
222
+ copilot: 'vscode'
223
+ };
224
+
225
+ const platformMappings = {
226
+ claude: [
227
+ { src: 'brains/CLAUDE.md', dest: 'CLAUDE.md' },
228
+ { src: 'brains/claude-agents', dest: '.claude/agents' },
229
+ { src: 'templates', dest: 'templates' },
230
+ { src: 'skills', dest: 'skills' },
231
+ { src: 'scripts', dest: 'scripts' }
232
+ ],
233
+ cursor: [
234
+ { src: 'brains/cursor-rules', dest: '.cursor/rules' },
235
+ { src: 'templates', dest: 'templates' },
236
+ { src: 'skills', dest: 'skills' },
237
+ { src: 'scripts', dest: 'scripts' }
238
+ ],
239
+ gemini: [
240
+ { src: 'brains/GEMINI.md', dest: 'GEMINI.md' },
241
+ { src: 'templates', dest: 'templates' },
242
+ { src: 'skills', dest: 'skills' },
243
+ { src: 'skills', dest: '.agents/skills' },
244
+ { src: 'scripts', dest: 'scripts' }
245
+ ],
246
+ codex: [
247
+ { src: 'brains/AGENTS.md', dest: 'AGENTS.md' },
248
+ { src: 'templates', dest: 'templates' },
249
+ { src: 'skills', dest: 'skills' },
250
+ { src: 'scripts', dest: 'scripts' }
251
+ ],
252
+ vscode: [
253
+ { src: 'brains/CLAUDE.md', dest: '.github/copilot-instructions.md' },
254
+ { src: 'templates', dest: 'templates' },
255
+ { src: 'skills', dest: 'skills' },
256
+ { src: 'scripts', dest: 'scripts' }
257
+ ],
258
+ copilot: [
259
+ { src: 'brains/CLAUDE.md', dest: '.github/copilot-instructions.md' },
260
+ { src: 'templates', dest: 'templates' },
261
+ { src: 'skills', dest: 'skills' },
262
+ { src: 'scripts', dest: 'scripts' }
263
+ ]
264
+ };
265
+
266
+ const mapping = platformMappings[targetPlatform];
267
+
268
+ if (!mapping) {
269
+ rl.close();
270
+ console.error(`Error: Unsupported platform '${targetPlatform}'.\n`);
271
+ displayHelp();
272
+ }
273
+
274
+ console.log(`\n🚀 Preparing to install V-Bounce OS for \x1b[36m${targetPlatform}\x1b[0m...\n`);
275
+
276
+ const toCopy = [];
277
+ const toOverwrite = [];
161
278
 
162
279
  mapping.forEach(rule => {
163
280
  const sourcePath = path.join(pkgRoot, rule.src);
164
281
  const destPath = path.join(CWD, rule.dest);
165
282
 
166
- if (!fs.existsSync(sourcePath)) return;
283
+ if (!fs.existsSync(sourcePath)) {
284
+ return; // Source does not exist internally, skip
285
+ }
167
286
 
168
- const stats = fs.statSync(sourcePath);
169
- if (stats.isDirectory()) {
170
- fs.mkdirSync(destPath, { recursive: true });
171
- fs.cpSync(sourcePath, destPath, { recursive: true, force: true });
287
+ if (fs.existsSync(destPath)) {
288
+ toOverwrite.push(rule.dest);
172
289
  } else {
173
- const destDir = path.dirname(destPath);
174
- if (!fs.existsSync(destDir)) {
175
- fs.mkdirSync(destDir, { recursive: true });
176
- }
177
- fs.copyFileSync(sourcePath, destPath);
290
+ toCopy.push(rule.dest);
178
291
  }
179
- console.log(` \x1b[32m✓\x1b[0m ${rule.dest}`);
180
292
  });
181
293
 
182
- console.log('\n⚙️ Installing RAG dependencies...');
183
- try {
184
- const deps = [
185
- '@lancedb/lancedb',
186
- '@xenova/transformers',
187
- 'js-yaml',
188
- 'marked',
189
- 'commander'
190
- ];
191
- console.log(` Running: npm install ${deps.join(' ')}`);
192
- execSync(`npm install ${deps.join(' ')}`, { stdio: 'inherit', cwd: CWD });
193
- console.log(' \x1b[32m✓\x1b[0m Dependencies installed.');
194
- } catch (err) {
195
- console.error(' \x1b[31m✖\x1b[0m Failed to install dependencies. You may need to run it manually.');
294
+ if (toCopy.length > 0) {
295
+ console.log('The following will be \x1b[32mCREATED\x1b[0m:');
296
+ toCopy.forEach(f => console.log(` + ${f}`));
196
297
  }
197
298
 
198
- console.log('\n🧠 Initializing RAG Knowledge Base...');
199
- try {
200
- const syncScript = path.join(CWD, 'scripts', 'pre_bounce_sync.sh');
201
- if (fs.existsSync(syncScript)) {
202
- execSync(`chmod +x "${syncScript}" && "${syncScript}"`, { stdio: 'inherit', cwd: CWD });
203
- console.log(' \x1b[32m✓\x1b[0m Knowledge base initialized.');
204
- }
205
- } catch (err) {
206
- console.error(' \x1b[31m✖\x1b[0m Failed to initialize knowledge base. Run ./scripts/pre_bounce_sync.sh manually.');
299
+ if (toOverwrite.length > 0) {
300
+ console.log('\nThe following will be \x1b[33mOVERWRITTEN\x1b[0m:');
301
+ toOverwrite.forEach(f => console.log(` ! ${f}`));
207
302
  }
208
303
 
209
- // vdoc integration
210
- const vdocPlatform = vdocPlatformMap[targetPlatform];
211
- if (vdocPlatform) {
212
- const rl2 = readline.createInterface({ input: process.stdin, output: process.stdout });
213
- const vdocAnswer = await new Promise(resolve => rl2.question('\n📝 Install vdoc (AI-powered documentation generator)? [y/N] ', resolve));
214
- rl2.close();
215
-
216
- if (vdocAnswer.trim().toLowerCase() === 'y' || vdocAnswer.trim().toLowerCase() === 'yes') {
217
- console.log(`\n📝 Installing vdoc for ${vdocPlatform}...`);
218
- try {
219
- execSync(`npx @sandrinio/vdoc install ${vdocPlatform}`, { stdio: 'inherit', cwd: CWD });
220
- console.log(' \x1b[32m✓\x1b[0m vdoc installed.');
221
- } catch (err) {
222
- console.error(` \x1b[31m✖\x1b[0m Failed to install vdoc. Run manually: npx @sandrinio/vdoc install ${vdocPlatform}`);
304
+ console.log('');
305
+
306
+ askQuestion('Proceed with installation? [y/N] ').then(async answer => {
307
+ rl.close();
308
+ const confirmation = answer.trim().toLowerCase();
309
+
310
+ if (confirmation !== 'y' && confirmation !== 'yes') {
311
+ console.log('\n❌ Installation cancelled.\n');
312
+ process.exit(0);
313
+ }
314
+
315
+ console.log('\n📦 Installing files...');
316
+
317
+ mapping.forEach(rule => {
318
+ const sourcePath = path.join(pkgRoot, rule.src);
319
+ const destPath = path.join(CWD, rule.dest);
320
+
321
+ if (!fs.existsSync(sourcePath)) return;
322
+
323
+ const stats = fs.statSync(sourcePath);
324
+ if (stats.isDirectory()) {
325
+ fs.mkdirSync(destPath, { recursive: true });
326
+ fs.cpSync(sourcePath, destPath, { recursive: true, force: true });
327
+ } else {
328
+ const destDir = path.dirname(destPath);
329
+ if (!fs.existsSync(destDir)) {
330
+ fs.mkdirSync(destDir, { recursive: true });
331
+ }
332
+ fs.copyFileSync(sourcePath, destPath);
223
333
  }
224
- } else {
225
- console.log(`\n Skipped. You can install later: npx @sandrinio/vdoc install ${vdocPlatform}`);
334
+ console.log(` \x1b[32m✓\x1b[0m ${rule.dest}`);
335
+ });
336
+
337
+ console.log('\n⚙️ Installing dependencies...');
338
+ try {
339
+ const deps = ['js-yaml', 'marked', 'commander'];
340
+ console.log(` Running: npm install ${deps.join(' ')}`);
341
+ execSync(`npm install ${deps.join(' ')}`, { stdio: 'inherit', cwd: CWD });
342
+ console.log(' \x1b[32m✓\x1b[0m Dependencies installed.');
343
+ } catch (err) {
344
+ console.error(' \x1b[31m✖\x1b[0m Failed to install dependencies. You may need to run it manually.');
226
345
  }
227
- }
228
346
 
229
- console.log('\n✅ V-Bounce OS successfully installed! Welcome to the team.\n');
230
- });
347
+ // vdoc integration
348
+ const vdocPlatform = vdocPlatformMap[targetPlatform];
349
+ if (vdocPlatform) {
350
+ const rl2 = readline.createInterface({ input: process.stdin, output: process.stdout });
351
+ const vdocAnswer = await new Promise(resolve => rl2.question('\n📝 Install vdoc (AI-powered documentation generator)? [y/N] ', resolve));
352
+ rl2.close();
353
+
354
+ if (vdocAnswer.trim().toLowerCase() === 'y' || vdocAnswer.trim().toLowerCase() === 'yes') {
355
+ console.log(`\n📝 Installing vdoc for ${vdocPlatform}...`);
356
+ try {
357
+ execSync(`npx @sandrinio/vdoc install ${vdocPlatform}`, { stdio: 'inherit', cwd: CWD });
358
+ console.log(' \x1b[32m✓\x1b[0m vdoc installed.');
359
+ } catch (err) {
360
+ console.error(` \x1b[31m✖\x1b[0m Failed to install vdoc. Run manually: npx @sandrinio/vdoc install ${vdocPlatform}`);
361
+ }
362
+ } else {
363
+ console.log(`\n Skipped. You can install later: npx @sandrinio/vdoc install ${vdocPlatform}`);
364
+ }
365
+ }
366
+
367
+ console.log('\n✅ V-Bounce OS successfully installed! Welcome to the team.\n');
368
+ });
369
+
370
+ } else {
371
+ // Unknown command fallthrough
372
+ rl.close();
373
+ console.error(`Unknown command: ${command}`);
374
+ displayHelp();
375
+ }