@sandrinio/vbounce 1.2.0 → 1.3.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/README.md CHANGED
@@ -48,7 +48,9 @@ npx @sandrinio/vbounce install codex
48
48
  ### What gets installed?
49
49
  - **Agent Instructions:** The "Brain" file (e.g., `CLAUDE.md`, `.cursor/rules/`) that teaches your AI how to follow the V-Bounce process.
50
50
  - **Templates:** Markdown templates for your Charter, Roadmap, Epics, and Stories.
51
- - **vdoc Integration:** Fully bundled with [`@sandrinio/vdoc`](https://github.com/sandrinio/vdoc) to automatically construct the `vdocs/` semantic documentation folder.
51
+ - **Bundled Scripts:** Our validation pipeline (`validate_report.mjs`) and RAG synchronization engine (`pre_bounce_sync.sh`).
52
+ - **Autonomous RAG Setup:** The installer automatically runs `npm install` for required libraries and initializes your local LanceDB knowledge base (`.bounce/.lancedb/`).
53
+ - **vdoc Integration:** Fully compatible with [`@sandrinio/vdoc`](https://github.com/sandrinio/vdoc) to automatically construct semantic product documentation.
52
54
 
53
55
  ### 🧰 The Bundled Skills
54
56
  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:
package/bin/vbounce.mjs CHANGED
@@ -5,6 +5,8 @@ import path from 'path';
5
5
  import { fileURLToPath } from 'url';
6
6
  import readline from 'readline';
7
7
 
8
+ import { execSync } from 'child_process';
9
+
8
10
  const __filename = fileURLToPath(import.meta.url);
9
11
  const __dirname = path.dirname(__filename);
10
12
  const pkgRoot = path.join(__dirname, '..');
@@ -61,33 +63,39 @@ const platformMappings = {
61
63
  { src: 'brains/CLAUDE.md', dest: 'CLAUDE.md' },
62
64
  { src: 'brains/claude-agents', dest: '.claude/agents' },
63
65
  { src: 'templates', dest: 'templates' },
64
- { src: 'skills', dest: 'skills' }
66
+ { src: 'skills', dest: 'skills' },
67
+ { src: 'scripts', dest: 'scripts' }
65
68
  ],
66
69
  cursor: [
67
70
  { src: 'brains/cursor-rules', dest: '.cursor/rules' },
68
71
  { src: 'templates', dest: 'templates' },
69
- { src: 'skills', dest: 'skills' }
72
+ { src: 'skills', dest: 'skills' },
73
+ { src: 'scripts', dest: 'scripts' }
70
74
  ],
71
75
  gemini: [
72
76
  { src: 'brains/GEMINI.md', dest: 'GEMINI.md' },
73
77
  { src: 'templates', dest: 'templates' },
74
78
  { src: 'skills', dest: 'skills' },
75
- { src: 'skills', dest: '.agents/skills' }
79
+ { src: 'skills', dest: '.agents/skills' },
80
+ { src: 'scripts', dest: 'scripts' }
76
81
  ],
77
82
  codex: [
78
83
  { src: 'brains/AGENTS.md', dest: 'AGENTS.md' },
79
84
  { src: 'templates', dest: 'templates' },
80
- { src: 'skills', dest: 'skills' }
85
+ { src: 'skills', dest: 'skills' },
86
+ { src: 'scripts', dest: 'scripts' }
81
87
  ],
82
88
  vscode: [
83
89
  { src: 'brains/CLAUDE.md', dest: '.github/copilot-instructions.md' },
84
90
  { src: 'templates', dest: 'templates' },
85
- { src: 'skills', dest: 'skills' }
91
+ { src: 'skills', dest: 'skills' },
92
+ { src: 'scripts', dest: 'scripts' }
86
93
  ],
87
94
  copilot: [
88
95
  { src: 'brains/CLAUDE.md', dest: '.github/copilot-instructions.md' },
89
96
  { src: 'templates', dest: 'templates' },
90
- { src: 'skills', dest: 'skills' }
97
+ { src: 'skills', dest: 'skills' },
98
+ { src: 'scripts', dest: 'scripts' }
91
99
  ]
92
100
  };
93
101
 
@@ -130,7 +138,7 @@ if (toOverwrite.length > 0) {
130
138
 
131
139
  console.log('');
132
140
 
133
- askQuestion('Proceed with installation? [y/N] ').then(answer => {
141
+ askQuestion('Proceed with installation? [y/N] ').then(async answer => {
134
142
  rl.close();
135
143
  const confirmation = answer.trim().toLowerCase();
136
144
 
@@ -161,5 +169,32 @@ askQuestion('Proceed with installation? [y/N] ').then(answer => {
161
169
  console.log(` \x1b[32m✓\x1b[0m ${rule.dest}`);
162
170
  });
163
171
 
172
+ console.log('\n⚙️ Installing RAG dependencies...');
173
+ try {
174
+ const deps = [
175
+ '@lancedb/lancedb',
176
+ '@xenova/transformers',
177
+ 'js-yaml',
178
+ 'marked',
179
+ 'commander'
180
+ ];
181
+ console.log(` Running: npm install ${deps.join(' ')}`);
182
+ execSync(`npm install ${deps.join(' ')}`, { stdio: 'inherit', cwd: CWD });
183
+ console.log(' \x1b[32m✓\x1b[0m Dependencies installed.');
184
+ } catch (err) {
185
+ console.error(' \x1b[31m✖\x1b[0m Failed to install dependencies. You may need to run it manually.');
186
+ }
187
+
188
+ console.log('\n🧠 Initializing RAG Knowledge Base...');
189
+ try {
190
+ const syncScript = path.join(CWD, 'scripts', 'pre_bounce_sync.sh');
191
+ if (fs.existsSync(syncScript)) {
192
+ execSync(`chmod +x "${syncScript}" && "${syncScript}"`, { stdio: 'inherit', cwd: CWD });
193
+ console.log(' \x1b[32m✓\x1b[0m Knowledge base initialized.');
194
+ }
195
+ } catch (err) {
196
+ console.error(' \x1b[31m✖\x1b[0m Failed to initialize knowledge base. Run ./scripts/pre_bounce_sync.sh manually.');
197
+ }
198
+
164
199
  console.log('\n✅ V-Bounce OS successfully installed! Welcome to the team.\n');
165
200
  });
package/brains/AGENTS.md CHANGED
@@ -38,9 +38,10 @@ Before starting any sprint, the Team Lead MUST:
38
38
 
39
39
  ### Phase 2: The Bounce (Implementation)
40
40
  **Standard Path (L2-L4 Stories):**
41
+ 0. Team Lead runs `./scripts/pre_bounce_sync.sh` to ensure LanceDB RAG context is fresh.
41
42
  1. Team Lead sends Story context pack to Developer.
42
- 2. Developer reads LESSONS.md, implements code, writes Implementation Report.
43
- 3. QA runs Quick Scan + PR Review, validates against Story §2 The Truth. If fail → Bug Report to Dev.
43
+ 2. Developer queries LanceDB, implements code, writes Implementation Report. CLI Orchestrator must run `./scripts/validate_report.mjs` on the report to enforce YAML strictness.
44
+ 3. QA runs Quick Scan + PR Review, validates against Story §2 The Truth. If fail → Bug Report to Dev. CLI Orchestrator must run `./scripts/validate_report.mjs` on the QA report before passing to Architect/Dev.
44
45
  4. Dev fixes and resubmits. 3+ failures → Escalated.
45
46
  5. Architect runs Deep Audit + Trend Check, validates Safe Zone compliance and ADR adherence.
46
47
  6. DevOps merges story branch into sprint branch, validates post-merge, handles release tagging.
@@ -92,6 +93,8 @@ Bouncing → Escalated (3+ failures)
92
93
  9. Reports are the only handoff. No direct agent-to-agent communication.
93
94
  10. One source of truth. Reference upstream documents, don't duplicate.
94
95
  11. Change Logs are mandatory on every document modification.
96
+ 12. Agent Reports MUST use YAML Frontmatter. Every `.bounce/report/` generated must start with a strict `---` YAML block containing the core status and metrics before the Markdown body.
97
+ 13. Framework Integrity. Any modification to a `brains/` or `skills/` file MUST be recorded in `brains/CHANGELOG.md` and trigger `./scripts/pre_bounce_sync.sh`.
95
98
 
96
99
  ## Framework Structure
97
100
 
@@ -0,0 +1,7 @@
1
+ # V-Bounce OS Brains & Skills Changelog
2
+
3
+ This log tracks modifications to the core agentic framework (e.g., `brains/`, `skills/`).
4
+ Per **Rule 13: Framework Integrity**, anytime an entry is made here, the orchestrator MUST trigger `./scripts/pre_bounce_sync.sh` to update the RAG embeddings globally.
5
+
6
+ ## [2026-03-02]
7
+ - **Initialized**: Created strict Framework Integrity tracking, YAML context handoffs, and RAG validation pipeline.
package/brains/CLAUDE.md CHANGED
@@ -50,9 +50,10 @@ Before starting any sprint, the Team Lead MUST:
50
50
 
51
51
  ### Phase 2: The Bounce (Implementation)
52
52
  **Standard Path (L2-L4 Stories):**
53
+ 0. Team Lead runs `./scripts/pre_bounce_sync.sh` to ensure LanceDB RAG context is fresh.
53
54
  1. Team Lead sends Story context pack to Developer.
54
- 2. Developer reads LESSONS.md, implements code, writes Implementation Report.
55
- 3. QA runs Quick Scan + PR Review, validates against Story §2 The Truth. If fail → Bug Report to Dev.
55
+ 2. Developer queries LanceDB, implements code, writes Implementation Report. CLI Orchestrator must run `./scripts/validate_report.mjs` on the report to enforce YAML strictness.
56
+ 3. QA runs Quick Scan + PR Review, validates against Story §2 The Truth. If fail → Bug Report to Dev. CLI Orchestrator must run `./scripts/validate_report.mjs` on the QA report before passing to Architect/Dev.
56
57
  4. Dev fixes and resubmits. 3+ failures → Escalated.
57
58
  5. Architect runs Deep Audit + Trend Check, validates Safe Zone compliance and ADR adherence.
58
59
  6. DevOps merges story branch into sprint branch, validates post-merge, handles release tagging.
@@ -106,6 +107,8 @@ Draft → Refinement → Ready to Bounce → Bouncing → QA Passed → Architec
106
107
  9. **Reports are the only handoff**. No direct agent-to-agent communication.
107
108
  10. **One source of truth**. Reference upstream documents, don't duplicate.
108
109
  11. **Change Logs are mandatory** on every document modification.
110
+ 12. **Agent Reports MUST use YAML Frontmatter**. Every `.bounce/report/` generated must start with a strict `---` YAML block containing the core status and metrics before the Markdown body.
111
+ 13. **Framework Integrity**. Any modification to a `brains/` or `skills/` file MUST be recorded in `brains/CHANGELOG.md` and trigger `./scripts/pre_bounce_sync.sh`.
109
112
 
110
113
  ## Framework Structure
111
114
 
package/brains/GEMINI.md CHANGED
@@ -41,9 +41,10 @@ Before starting any sprint, the Team Lead MUST:
41
41
 
42
42
  ### Phase 2: The Bounce (Implementation)
43
43
  **Standard Path (L2-L4 Stories):**
44
+ 0. Team Lead runs `./scripts/pre_bounce_sync.sh` to ensure LanceDB RAG context is fresh.
44
45
  1. Team Lead sends Story context pack to Developer.
45
- 2. Developer reads LESSONS.md, implements code, writes Implementation Report.
46
- 3. QA runs Quick Scan + PR Review, validates against Story §2 The Truth. If fail → Bug Report to Dev.
46
+ 2. Developer queries LanceDB, implements code, writes Implementation Report. CLI Orchestrator must run `./scripts/validate_report.mjs` on the report to enforce YAML strictness.
47
+ 3. QA runs Quick Scan + PR Review, validates against Story §2 The Truth. If fail → Bug Report to Dev. CLI Orchestrator must run `./scripts/validate_report.mjs` on the QA report before passing to Architect/Dev.
47
48
  4. Dev fixes and resubmits. 3+ failures → Escalated.
48
49
  5. Architect runs Deep Audit + Trend Check, validates Safe Zone compliance and ADR adherence.
49
50
  6. DevOps merges story branch into sprint branch, validates post-merge, handles release tagging.
@@ -97,6 +98,8 @@ Draft → Refinement → Ready to Bounce → Bouncing → QA Passed → Architec
97
98
  9. **Reports are the only handoff**. No direct agent-to-agent communication.
98
99
  10. **One source of truth**. Reference upstream documents, don't duplicate.
99
100
  11. **Change Logs are mandatory** on every document modification.
101
+ 12. **Agent Reports MUST use YAML Frontmatter**. Every `.bounce/report/` generated must start with a strict `---` YAML block containing the core status and metrics before the Markdown body.
102
+ 13. **Framework Integrity**. Any modification to a `brains/` or `skills/` file MUST be recorded in `brains/CHANGELOG.md` and trigger `./scripts/pre_bounce_sync.sh`.
100
103
 
101
104
  ## Framework Structure
102
105
 
package/brains/SETUP.md CHANGED
@@ -5,6 +5,7 @@ Step-by-step guide to set up V-Bounce OS in an existing or new project.
5
5
  ## Prerequisites
6
6
 
7
7
  - A git repository (V-Bounce OS uses branches and worktrees)
8
+ - Node.js installed (for validation and semantic search scripts)
8
9
  - At least one supported AI coding tool installed
9
10
  - The V-Bounce OS folder (this repo)
10
11
 
@@ -116,6 +117,17 @@ The agent will:
116
117
  4. Merge completed stories
117
118
  5. Generate a Sprint Report for your review
118
119
 
120
+ ## Step 7: Automated RAG Initialization
121
+
122
+ V-Bounce OS uses LanceDB to provide agents with targeted context. While the `npx @sandrinio/vbounce install` command handles this automatically, you can manually re-trigger a sync if you add new architectural rules or change your brains:
123
+
124
+ ```bash
125
+ # Re-build your local knowledge base
126
+ ./scripts/pre_bounce_sync.sh
127
+ ```
128
+
129
+ This updates your local embeddings in `.bounce/.lancedb/`. Agents use `./scripts/vbounce_ask.mjs` to fetch rules on demand, ensuring they are always aligned with your latest Roadmap and Lessons.
130
+
119
131
  ## Folder Structure After Setup
120
132
 
121
133
  ```
@@ -14,7 +14,7 @@ Audit the codebase for structural integrity, standards compliance, and long-term
14
14
 
15
15
  ## Before Auditing
16
16
 
17
- 1. **Read LESSONS.md** at the project root. Check for historical architectural decisions and past mistakes.
17
+ 1. **Query Project Lessons**: Run `./scripts/vbounce_ask.mjs "architectural constraints and historical mistakes for <story summary>"` to retrieve relevant context from `LESSONS.md` and past reports.
18
18
  2. **Read all reports** for this story (`.bounce/reports/STORY-{ID}-*.md`) — Dev Report, QA Report.
19
19
  3. **Read the full Story spec** — especially §3 Implementation Guide and §3.1 ADR References.
20
20
  4. **Read Roadmap §3 ADRs** — every architecture decision the implementation must comply with.
@@ -65,10 +65,18 @@ Check that the changes don't break existing functionality:
65
65
 
66
66
  ## Your Output
67
67
 
68
- Write an **Architectural Audit Report** to `.bounce/reports/STORY-{ID}-arch.md`:
68
+ Write an **Architectural Audit Report** to `.bounce/reports/STORY-{ID}-arch.md`.
69
+ You MUST include the YAML frontmatter block exactly as shown below:
69
70
 
70
71
  ### If Audit PASSES:
71
72
  ```markdown
73
+ ---
74
+ status: "PASS"
75
+ safe_zone_score: {SCORE}
76
+ ai_isms_detected: {count}
77
+ regression_risk: "{Low/Medium/High}"
78
+ ---
79
+
72
80
  # Architectural Audit Report: STORY-{ID} — PASS
73
81
 
74
82
  ## Safe Zone Compliance: {SCORE}/10
@@ -108,6 +116,12 @@ PASS — Ready for Sprint Review.
108
116
 
109
117
  ### If Audit FAILS:
110
118
  ```markdown
119
+ ---
120
+ status: "FAIL"
121
+ bounce_count: {N}
122
+ critical_failures: {count}
123
+ ---
124
+
111
125
  # Architectural Audit Report: STORY-{ID} — FAIL
112
126
 
113
127
  ## Critical Failures
@@ -12,8 +12,9 @@ Implement features and fix bugs as specified in Story documents. You write code
12
12
 
13
13
  ## Before Writing ANY Code
14
14
 
15
- 1. **Read LESSONS.md** at the project root. Treat every recorded rule as a hard constraint. No exceptions.
16
- 2. **Read the Story spec** §1 The Spec for requirements, §3 Implementation Guide for technical approach.
15
+ 1. **Query Project Lessons**: Run `./scripts/vbounce_ask.mjs "<summarize your specific coding task here>"` to retrieve relevant constraints and gotchas from `LESSONS.md` and historical reports. Treat these as hard constraints. No exceptions.
16
+ 2. **Query Architectural Decisions**: If your task involves core systems (auth, db, state), run `./scripts/vbounce_ask.mjs "<system> decisions"` to get relevant ADRs from the Roadmap.
17
+ 3. **Read the Story spec** — §1 The Spec for requirements, §3 Implementation Guide for technical approach.
17
18
  3. **Check ADR references** in §3.1 — comply with all architecture decisions from the Roadmap.
18
19
  4. **Read relevant react-best-practices rules** — consult `skills/react-best-practices/` for patterns matching your task.
19
20
  5. **Check product documentation** — if the task file references product docs from `product_documentation/`, read them. Understand how the existing feature works before changing adjacent code. If your implementation changes behavior described in a product doc, flag it in your report.
@@ -33,9 +34,18 @@ Do NOT proceed with a broken spec. Instead:
33
34
 
34
35
  ## Your Output
35
36
 
36
- Write a **Developer Implementation Report** to `.bounce/reports/STORY-{ID}-dev.md`:
37
+ Write a **Developer Implementation Report** to `.bounce/reports/STORY-{ID}-dev.md`.
38
+ You MUST include the YAML frontmatter block exactly as shown below:
37
39
 
38
40
  ```markdown
41
+ ---
42
+ status: "implemented"
43
+ correction_tax: {X}
44
+ files_modified:
45
+ - "path/to/file.ts"
46
+ lessons_flagged: {number of lessons}
47
+ ---
48
+
39
49
  # Developer Implementation Report: STORY-{ID}
40
50
 
41
51
  ## Files Modified
@@ -146,10 +146,17 @@ Before approving a deployment:
146
146
 
147
147
  ## Your Output
148
148
 
149
- Write a **DevOps Report** to `.bounce/reports/STORY-{ID}-devops.md` (for story merges) or `.bounce/reports/sprint-S-{XX}-devops.md` (for sprint releases):
149
+ Write a **DevOps Report** to `.bounce/reports/STORY-{ID}-devops.md` (for story merges) or `.bounce/reports/sprint-S-{XX}-devops.md` (for sprint releases).
150
+ You MUST include the YAML frontmatter block exactly as shown below:
150
151
 
151
152
  ### Story Merge Report
152
153
  ```markdown
154
+ ---
155
+ type: "story-merge"
156
+ status: "{Clean / Conflicts Resolved / Failed}"
157
+ conflicts_detected: {true/false}
158
+ ---
159
+
153
160
  # DevOps Report: STORY-{ID} Merge
154
161
 
155
162
  ## Pre-Merge Checks
@@ -178,6 +185,12 @@ Write a **DevOps Report** to `.bounce/reports/STORY-{ID}-devops.md` (for story m
178
185
 
179
186
  ### Sprint Release Report
180
187
  ```markdown
188
+ ---
189
+ type: "sprint-release"
190
+ status: "{Deployed / Pending / Manual}"
191
+ version: "{VERSION}"
192
+ ---
193
+
181
194
  # DevOps Report: Sprint S-{XX} Release
182
195
 
183
196
  ## Pre-Release Checks
@@ -12,7 +12,7 @@ Validate that the Developer's implementation meets the Story's acceptance criter
12
12
 
13
13
  ## Before Testing
14
14
 
15
- 1. **Read LESSONS.md** at the project root. Check for known failure patterns relevant to this story.
15
+ 1. **Query Project Lessons**: Run `./scripts/vbounce_ask.mjs "<summarize the story spec here>"` to retrieve known failure patterns relevant to this story from `LESSONS.md` and past reports.
16
16
  2. **Read the Developer Implementation Report** (`.bounce/reports/STORY-{ID}-dev.md`) to understand what was built.
17
17
  3. **Read Story §2 The Truth** — these are your pass/fail criteria. If the Gherkin scenarios don't pass, the bounce failed.
18
18
 
@@ -58,10 +58,18 @@ Check for unnecessary complexity the Developer added beyond the Story spec:
58
58
 
59
59
  ## Your Output
60
60
 
61
- Write a **QA Validation Report** to `.bounce/reports/STORY-{ID}-qa.md`:
61
+ Write a **QA Validation Report** to `.bounce/reports/STORY-{ID}-qa.md`.
62
+ You MUST include the YAML frontmatter block exactly as shown below:
62
63
 
63
64
  ### If Tests PASS:
64
65
  ```markdown
66
+ ---
67
+ status: "PASS"
68
+ bounce_count: {N}
69
+ bugs_found: 0
70
+ gold_plating_detected: false
71
+ ---
72
+
65
73
  # QA Validation Report: STORY-{ID} — PASS
66
74
 
67
75
  ## Quick Scan Results
@@ -98,6 +106,15 @@ PASS — Ready for Architect review.
98
106
 
99
107
  ### If Tests FAIL:
100
108
  ```markdown
109
+ ---
110
+ status: "FAIL"
111
+ bounce_count: {N}
112
+ bugs_found: {number of bugs}
113
+ gold_plating_detected: {true/false}
114
+ failed_scenarios:
115
+ - "{scenario name}"
116
+ ---
117
+
101
118
  # QA Validation Report: STORY-{ID} — FAIL (Bounce {N})
102
119
 
103
120
  ## Failures
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sandrinio/vbounce",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "V-Bounce OS: Turn your AI coding assistant into a full engineering team through structured SDLC skills.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -38,5 +38,12 @@
38
38
  "skills",
39
39
  "scripts",
40
40
  "docs"
41
- ]
42
- }
41
+ ],
42
+ "dependencies": {
43
+ "@lancedb/lancedb": "^0.26.2",
44
+ "@xenova/transformers": "^2.17.2",
45
+ "commander": "^14.0.3",
46
+ "js-yaml": "^4.1.1",
47
+ "marked": "^17.0.3"
48
+ }
49
+ }
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # pre_bounce_sync.sh
4
+ #
5
+ # Run this before kicking off the Implementation Loop (Bounce).
6
+ # This prevents the "Stale Context" edge case by forcing the LanceDB
7
+ # index to refresh with the latest rules from LESSONS.md and ROADMAP.md.
8
+
9
+ echo "==========================================="
10
+ echo " V-Bounce OS: Pre-Bounce Sync Started"
11
+ echo "==========================================="
12
+
13
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd)"
14
+ ROOT_DIR="$(dirname "$SCRIPT_DIR")"
15
+
16
+ cd "$ROOT_DIR" || exit 1
17
+
18
+ # 1. Check for Node Modules
19
+ if [ ! -d "node_modules" ]; then
20
+ echo "Error: node_modules not found. Run 'npm install'."
21
+ exit 1
22
+ fi
23
+
24
+ # 2. Rebuild the semantic search index
25
+ echo "Syncing V-Bounce Knowledge Base (LanceDB)..."
26
+ node ./scripts/vbounce_index.mjs --all
27
+
28
+ if [ $? -ne 0 ]; then
29
+ echo "Error: LanceDB index sync failed."
30
+ exit 1
31
+ fi
32
+
33
+ echo "==========================================="
34
+ echo " Pre-Bounce Sync Complete. RAG is fresh."
35
+ echo " Ready for Team Lead delegation."
36
+ echo "==========================================="
37
+ exit 0
@@ -0,0 +1,122 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * validate_report.mjs
5
+ *
6
+ * Strict YAML Frontmatter validation for V-Bounce OS Agent Reports.
7
+ * Fails loudly if an agent hallucinates formatting or omits required fields,
8
+ * so the orchestrator can bounce the prompt back.
9
+ */
10
+
11
+ import fs from 'fs';
12
+ import path from 'path';
13
+ import yaml from 'js-yaml';
14
+
15
+ // Defined schemas for each report type
16
+ const SCHEMAS = {
17
+ dev: ['status', 'correction_tax', 'files_modified', 'lessons_flagged'],
18
+ qa: {
19
+ base: ['status', 'bounce_count', 'bugs_found', 'gold_plating_detected'],
20
+ conditional: { 'FAIL': ['failed_scenarios'] }
21
+ },
22
+ arch: {
23
+ base: ['status'],
24
+ conditional: { 'PASS': ['safe_zone_score', 'ai_isms_detected', 'regression_risk'], 'FAIL': ['bounce_count', 'critical_failures'] }
25
+ },
26
+ devops: {
27
+ base: ['type', 'status'],
28
+ conditional: { 'story-merge': ['conflicts_detected'], 'sprint-release': ['version'] }
29
+ }
30
+ };
31
+
32
+ function extractFrontmatter(content) {
33
+ // Matches "---" at the start of the file or after whitespace
34
+ const match = content.match(/^---\s*[\r\n]+([\s\S]*?)[\r\n]+---\s*/);
35
+ if (!match) {
36
+ throw new Error('NO_FRONTMATTER: Report missing strict YAML --- delimiters at the top of the file.');
37
+ }
38
+ return match[1];
39
+ }
40
+
41
+ function validateDev(data) {
42
+ const missing = SCHEMAS.dev.filter(k => !(k in data));
43
+ if (missing.length > 0) throw new Error(`DEV_SCHEMA_ERROR: Missing required keys: ${missing.join(', ')}`);
44
+ if (!Array.isArray(data.files_modified)) throw new Error(`DEV_SCHEMA_ERROR: 'files_modified' must be an array.`);
45
+ }
46
+
47
+ function validateQA(data) {
48
+ const missing = SCHEMAS.qa.base.filter(k => !(k in data));
49
+ if (missing.length > 0) throw new Error(`QA_SCHEMA_ERROR: Missing required keys: ${missing.join(', ')}`);
50
+
51
+ if (data.status === 'FAIL') {
52
+ const conditionalMissing = SCHEMAS.qa.conditional.FAIL.filter(k => !(k in data));
53
+ if (conditionalMissing.length > 0) throw new Error(`QA_SCHEMA_ERROR: 'FAIL' status requires keys: ${conditionalMissing.join(', ')}`);
54
+ }
55
+ }
56
+
57
+ function validateArch(data) {
58
+ const missing = SCHEMAS.arch.base.filter(k => !(k in data));
59
+ if (missing.length > 0) throw new Error(`ARCH_SCHEMA_ERROR: Missing required keys: ${missing.join(', ')}`);
60
+
61
+ const s = data.status === 'PASS' ? 'PASS' : 'FAIL';
62
+ const conditionalMissing = SCHEMAS.arch.conditional[s].filter(k => !(k in data));
63
+ if (conditionalMissing.length > 0) throw new Error(`ARCH_SCHEMA_ERROR: '${s}' status requires keys: ${conditionalMissing.join(', ')}`);
64
+ }
65
+
66
+ function validateDevops(data) {
67
+ const missing = SCHEMAS.devops.base.filter(k => !(k in data));
68
+ if (missing.length > 0) throw new Error(`DEVOPS_SCHEMA_ERROR: Missing required keys: ${missing.join(', ')}`);
69
+
70
+ const typeStr = String(data.type);
71
+ if (SCHEMAS.devops.conditional[typeStr]) {
72
+ const conditionalMissing = SCHEMAS.devops.conditional[typeStr].filter(k => !(k in data));
73
+ if (conditionalMissing.length > 0) throw new Error(`DEVOPS_SCHEMA_ERROR: '${typeStr}' type requires keys: ${conditionalMissing.join(', ')}`);
74
+ }
75
+ }
76
+
77
+ function main() {
78
+ const filePath = process.argv[2];
79
+ if (!filePath) {
80
+ console.error("Usage: validate_report.mjs <path-to-markdown-file>");
81
+ process.exit(1);
82
+ }
83
+
84
+ const filename = path.basename(filePath);
85
+
86
+ // Infer agent type from filename convention
87
+ let agentType = 'unknown';
88
+ if (filename.endsWith('-dev.md')) agentType = 'dev';
89
+ else if (filename.endsWith('-qa.md')) agentType = 'qa';
90
+ else if (filename.endsWith('-arch.md')) agentType = 'arch';
91
+ else if (filename.endsWith('-devops.md')) agentType = 'devops';
92
+
93
+ if (agentType === 'unknown') {
94
+ console.error(`WARNING: Unrecognized report type for ${filename}. Ensure filename ends in -dev.md, -qa.md, -arch.md, or -devops.md.`);
95
+ process.exit(0); // Soft pass, not an agent workflow report
96
+ }
97
+
98
+ try {
99
+ const rawContent = fs.readFileSync(filePath, 'utf8');
100
+ const yamlString = extractFrontmatter(rawContent);
101
+ const data = yaml.load(yamlString);
102
+
103
+ if (!data || typeof data !== 'object') {
104
+ throw new Error("YAML_PARSE_ERROR: Frontmatter parsed to an empty or invalid object.");
105
+ }
106
+
107
+ if (agentType === 'dev') validateDev(data);
108
+ if (agentType === 'qa') validateQA(data);
109
+ if (agentType === 'arch') validateArch(data);
110
+ if (agentType === 'devops') validateDevops(data);
111
+
112
+ console.log(`VALID: ${filename} matches the ${agentType.toUpperCase()} schema.`);
113
+ process.exit(0);
114
+
115
+ } catch (error) {
116
+ // We print specifically to stdout so automation scripts can capture the payload and bounce it back to the AI
117
+ console.log(`VALIDATION_FAILED\n${error.message}`);
118
+ process.exit(1);
119
+ }
120
+ }
121
+
122
+ main();
@@ -0,0 +1,98 @@
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 { program } from 'commander';
8
+
9
+ const LANCE_DIR = path.join(process.cwd(), '.bounce', '.lancedb');
10
+
11
+ program
12
+ .name('vbounce_ask')
13
+ .description('Query V-Bounce OS LanceDB for relevant context')
14
+ .argument('<query>', 'The semantic query to search for')
15
+ .option('-f, --filter <field=value>', 'Filter by metadata (e.g., type=lesson)')
16
+ .option('-l, --limit <number>', 'Number of results to return', 3)
17
+ .parse(process.argv);
18
+
19
+ const options = program.opts();
20
+ const query = program.args[0];
21
+
22
+ class LocalEmbeddingFunction {
23
+ constructor() {
24
+ this.modelName = 'Xenova/all-MiniLM-L6-v2';
25
+ this.extractor = null;
26
+ }
27
+
28
+ async init() {
29
+ if (!this.extractor) {
30
+ this.extractor = await pipeline('feature-extraction', this.modelName, {
31
+ quantized: true,
32
+ });
33
+ }
34
+ }
35
+
36
+ async embedQuery(text) {
37
+ await this.init();
38
+ const output = await this.extractor(text, { pooling: 'mean', normalize: true });
39
+ return Array.from(output.data);
40
+ }
41
+ }
42
+
43
+ async function main() {
44
+ if (!query) {
45
+ console.error("Error: Must provide a semantic query string.");
46
+ process.exit(1);
47
+ }
48
+
49
+ if (!fs.existsSync(LANCE_DIR)) {
50
+ console.error(`Error: LanceDB not found at ${LANCE_DIR}. Have you run vbounce_index yet?`);
51
+ process.exit(1);
52
+ }
53
+
54
+ const db = await connect(LANCE_DIR);
55
+ let table;
56
+ try {
57
+ table = await db.openTable('vbounce_context');
58
+ } catch (e) {
59
+ console.error("Error: Table 'vbounce_context' not found. Please index documents first.");
60
+ process.exit(1);
61
+ }
62
+
63
+ const embedder = new LocalEmbeddingFunction();
64
+ const queryVector = await embedder.embedQuery(query);
65
+
66
+ let search = table.vectorSearch(queryVector).limit(parseInt(options.limit));
67
+
68
+ if (options.filter) {
69
+ const [field, value] = options.filter.split('=');
70
+ // LanceDB JS uses SQL-like string criteria for filtering
71
+ if (field === "type") {
72
+ search = search.where(`\`type\` = '${value}'`);
73
+ } else if (field === "section") {
74
+ search = search.where(`\`section\` = '${value}'`);
75
+ }
76
+ }
77
+
78
+ const results = await search.toArray();
79
+
80
+ if (results.length === 0) {
81
+ console.log("No relevant context found.");
82
+ return;
83
+ }
84
+
85
+ console.log(`\n--- V-Bounce Semantic Retrieval ---`);
86
+ console.log(`Query: "${query}"`);
87
+ console.log(`Found ${results.length} relevant chunks.\n`);
88
+
89
+ results.forEach((r, idx) => {
90
+ console.log(`[Result ${idx + 1}] Source: ${r.file} (${r.type || 'unknown'} > ${r.section || 'General'})`);
91
+ console.log(`Distance: ${r._distance ? r._distance.toFixed(4) : 'N/A'}`);
92
+ console.log('-'.repeat(40));
93
+ console.log(r.text.trim());
94
+ console.log('\n');
95
+ });
96
+ }
97
+
98
+ main().catch(console.error);
@@ -0,0 +1,184 @@
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('product_documentation')) 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('product_documentation');
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);
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * verify_framework.mjs
5
+ *
6
+ * Tests the backward-compatibility of the AI agent prompts against
7
+ * the strict YAML parsing schemas in validate_report.mjs.
8
+ *
9
+ * Triggered manually by humans or automatically by CI when updating brains/.
10
+ */
11
+
12
+ import fs from 'fs';
13
+ import path from 'path';
14
+
15
+ const AGENTS_DIR = path.join(process.cwd(), 'brains', 'claude-agents');
16
+
17
+ // The exact substring signatures that MUST exist in the agent instructions
18
+ // to ensure the LLM knows to output the correct YAML schema.
19
+ const EXPECTED_PROMPT_SIGNATURES = {
20
+ 'developer.md': [
21
+ 'status:',
22
+ 'correction_tax:',
23
+ 'files_modified:',
24
+ 'lessons_flagged:'
25
+ ],
26
+ 'qa.md': [
27
+ 'status: "PASS"',
28
+ 'bugs_found: 0',
29
+ 'status: "FAIL"',
30
+ 'failed_scenarios:'
31
+ ],
32
+ 'architect.md': [
33
+ 'status: "PASS"',
34
+ 'safe_zone_score:',
35
+ 'regression_risk:',
36
+ 'status: "FAIL"',
37
+ 'critical_failures:'
38
+ ],
39
+ 'devops.md': [
40
+ 'type: "story-merge"',
41
+ 'conflicts_detected:',
42
+ 'type: "sprint-release"',
43
+ 'version:'
44
+ ]
45
+ };
46
+
47
+ function main() {
48
+ console.log("===========================================");
49
+ console.log(" V-Bounce OS: Framework Integrity Check");
50
+ console.log("===========================================\n");
51
+
52
+ let hasErrors = false;
53
+
54
+ if (!fs.existsSync(AGENTS_DIR)) {
55
+ console.error(`ERROR: ${AGENTS_DIR} not found.`);
56
+ process.exit(1);
57
+ }
58
+
59
+ const files = fs.readdirSync(AGENTS_DIR).filter(f => f.endsWith('.md'));
60
+
61
+ for (const file of files) {
62
+ const filePath = path.join(AGENTS_DIR, file);
63
+ const content = fs.readFileSync(filePath, 'utf-8');
64
+
65
+ const requiredSignatures = EXPECTED_PROMPT_SIGNATURES[file];
66
+ if (!requiredSignatures) {
67
+ console.log(`[PASS] ${file} (No strict YAML signatures required)`);
68
+ continue;
69
+ }
70
+
71
+ let filePassed = true;
72
+ for (const sig of requiredSignatures) {
73
+ if (!content.includes(sig)) {
74
+ console.error(`[FAIL] ${file} is missing required YAML instruction key: '${sig}'`);
75
+ filePassed = false;
76
+ hasErrors = true;
77
+ }
78
+ }
79
+
80
+ // Check for general Rule 12 presence
81
+ if (!content.includes('YAML frontmatter') && !content.includes('YAML Frontmatter')) {
82
+ console.error(`[FAIL] ${file} appears to be missing the Rule 12 YAML Frontmatter instruction.`);
83
+ filePassed = false;
84
+ hasErrors = true;
85
+ }
86
+
87
+ if (filePassed) {
88
+ console.log(`[PASS] ${file} contains all required YAML extraction signatures.`);
89
+ }
90
+ }
91
+
92
+ console.log("\n-------------------------------------------");
93
+ if (hasErrors) {
94
+ console.error("❌ INTEGRITY CHECK FAILED.");
95
+ console.error("Agent prompts have drifted from the validate_report.mjs schema.");
96
+ console.error("Please fix the agent templates in brains/claude-agents/ to restore pipeline integrity.");
97
+ process.exit(1);
98
+ } else {
99
+ console.log("✅ INTEGRITY CHECK PASSED.");
100
+ console.log("All agent prompts strictly map to the required pipeline metadata schemas.");
101
+ process.exit(0);
102
+ }
103
+ }
104
+
105
+ main();
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # verify_framework.sh
4
+ #
5
+ # Wrapper script to execute the Framework Integrity Check.
6
+
7
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd)"
8
+ ROOT_DIR="$(dirname "$SCRIPT_DIR")"
9
+
10
+ cd "$ROOT_DIR" || exit 1
11
+
12
+ node ./scripts/verify_framework.mjs
13
+ exit $?
@@ -56,4 +56,5 @@ Do NOT output these instructions.
56
56
 
57
57
  - [ ] {Simple step, e.g., "Open the settings modal and verify the button is aligned."}
58
58
  - [ ] Automated tests still pass (`npm test`).
59
+ - [ ] **Framework Integrity**: If `brains/` or `skills/` were modified, log to `brains/CHANGELOG.md` and run `./scripts/pre_bounce_sync.sh`.
59
60
  - [ ] **Post-Fix Action**: Run `./scripts/hotfix_manager.sh ledger "HOTFIX: {Name}" "{Brief Fix Description}"`
@@ -148,3 +148,4 @@ POST /api/resource
148
148
  - [ ] LESSONS.md consulted before implementation.
149
149
  - [ ] No violations of Roadmap ADRs.
150
150
  - [ ] Documentation (API/Tech Stack) updated.
151
+ - [ ] **Framework Integrity**: If `brains/` or `skills/` were modified, log to `brains/CHANGELOG.md` and run `./scripts/pre_bounce_sync.sh`.