vbounce-engine 2.5.1

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 (165) hide show
  1. package/README.md +142 -0
  2. package/VBOUNCE_MANIFEST.md +404 -0
  3. package/bin/vbounce.mjs +882 -0
  4. package/brains/AGENTS.md +71 -0
  5. package/brains/CHANGELOG.md +398 -0
  6. package/brains/CLAUDE.md +90 -0
  7. package/brains/GEMINI.md +102 -0
  8. package/brains/SETUP.md +195 -0
  9. package/brains/claude-agents/architect.md +226 -0
  10. package/brains/claude-agents/developer.md +133 -0
  11. package/brains/claude-agents/devops.md +267 -0
  12. package/brains/claude-agents/explorer.md +157 -0
  13. package/brains/claude-agents/qa.md +225 -0
  14. package/brains/claude-agents/scribe.md +171 -0
  15. package/brains/copilot/copilot-instructions.md +54 -0
  16. package/brains/cursor-rules/vbounce-docs.mdc +45 -0
  17. package/brains/cursor-rules/vbounce-process.mdc +51 -0
  18. package/brains/cursor-rules/vbounce-rules.mdc +29 -0
  19. package/brains/windsurf/.windsurfrules +35 -0
  20. package/docs/HOTFIX_EDGE_CASES.md +37 -0
  21. package/docs/IMPROVEMENT.md +46 -0
  22. package/docs/agent-skill-profiles.docx +0 -0
  23. package/docs/icons/alert.svg +1 -0
  24. package/docs/icons/beaker.svg +1 -0
  25. package/docs/icons/book.svg +1 -0
  26. package/docs/icons/git-branch.svg +1 -0
  27. package/docs/icons/git-merge.svg +1 -0
  28. package/docs/icons/graph.svg +1 -0
  29. package/docs/icons/light-bulb.svg +1 -0
  30. package/docs/icons/logo.svg +9 -0
  31. package/docs/icons/pencil.svg +1 -0
  32. package/docs/icons/rocket.svg +1 -0
  33. package/docs/icons/shield.svg +1 -0
  34. package/docs/icons/sync.svg +1 -0
  35. package/docs/icons/terminal.svg +1 -0
  36. package/docs/icons/tools.svg +1 -0
  37. package/docs/icons/zap.svg +1 -0
  38. package/docs/images/bounce_loop_diagram.png +0 -0
  39. package/docs/vbounce-os-manual.docx +0 -0
  40. package/package.json +48 -0
  41. package/scripts/close_sprint.mjs +134 -0
  42. package/scripts/complete_story.mjs +121 -0
  43. package/scripts/count_tokens.mjs +494 -0
  44. package/scripts/doctor.mjs +144 -0
  45. package/scripts/hotfix_manager.sh +157 -0
  46. package/scripts/init_gate_config.sh +151 -0
  47. package/scripts/init_sprint.mjs +129 -0
  48. package/scripts/post_sprint_improve.mjs +486 -0
  49. package/scripts/pre_gate_common.sh +576 -0
  50. package/scripts/pre_gate_runner.sh +176 -0
  51. package/scripts/prep_arch_context.mjs +178 -0
  52. package/scripts/prep_qa_context.mjs +152 -0
  53. package/scripts/prep_sprint_context.mjs +141 -0
  54. package/scripts/prep_sprint_summary.mjs +154 -0
  55. package/scripts/product_graph.mjs +387 -0
  56. package/scripts/product_impact.mjs +167 -0
  57. package/scripts/sprint_trends.mjs +160 -0
  58. package/scripts/suggest_improvements.mjs +363 -0
  59. package/scripts/update_state.mjs +132 -0
  60. package/scripts/validate_bounce_readiness.mjs +152 -0
  61. package/scripts/validate_report.mjs +165 -0
  62. package/scripts/validate_sprint_plan.mjs +117 -0
  63. package/scripts/validate_state.mjs +99 -0
  64. package/scripts/vdoc_match.mjs +269 -0
  65. package/scripts/vdoc_staleness.mjs +199 -0
  66. package/scripts/verify_framework.mjs +122 -0
  67. package/scripts/verify_framework.sh +13 -0
  68. package/skills/agent-team/SKILL.md +579 -0
  69. package/skills/agent-team/references/cleanup.md +42 -0
  70. package/skills/agent-team/references/delivery-sync.md +43 -0
  71. package/skills/agent-team/references/discovery.md +97 -0
  72. package/skills/agent-team/references/git-strategy.md +52 -0
  73. package/skills/agent-team/references/mid-sprint-triage.md +85 -0
  74. package/skills/agent-team/references/report-naming.md +34 -0
  75. package/skills/doc-manager/SKILL.md +444 -0
  76. package/skills/file-organization/SKILL.md +146 -0
  77. package/skills/file-organization/TEST-RESULTS.md +193 -0
  78. package/skills/file-organization/evals/evals.json +41 -0
  79. package/skills/file-organization/references/gitignore-template.md +53 -0
  80. package/skills/file-organization/references/quick-checklist.md +48 -0
  81. package/skills/improve/SKILL.md +296 -0
  82. package/skills/lesson/SKILL.md +136 -0
  83. package/skills/product-graph/SKILL.md +102 -0
  84. package/skills/react-best-practices/SKILL.md +3014 -0
  85. package/skills/react-best-practices/rules/_sections.md +46 -0
  86. package/skills/react-best-practices/rules/_template.md +28 -0
  87. package/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  88. package/skills/react-best-practices/rules/advanced-init-once.md +42 -0
  89. package/skills/react-best-practices/rules/advanced-use-latest.md +39 -0
  90. package/skills/react-best-practices/rules/async-api-routes.md +38 -0
  91. package/skills/react-best-practices/rules/async-defer-await.md +80 -0
  92. package/skills/react-best-practices/rules/async-dependencies.md +51 -0
  93. package/skills/react-best-practices/rules/async-parallel.md +28 -0
  94. package/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
  95. package/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
  96. package/skills/react-best-practices/rules/bundle-conditional.md +31 -0
  97. package/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
  98. package/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  99. package/skills/react-best-practices/rules/bundle-preload.md +50 -0
  100. package/skills/react-best-practices/rules/client-event-listeners.md +74 -0
  101. package/skills/react-best-practices/rules/client-localstorage-schema.md +71 -0
  102. package/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
  103. package/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
  104. package/skills/react-best-practices/rules/js-batch-dom-css.md +107 -0
  105. package/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
  106. package/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
  107. package/skills/react-best-practices/rules/js-cache-storage.md +70 -0
  108. package/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
  109. package/skills/react-best-practices/rules/js-early-exit.md +50 -0
  110. package/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
  111. package/skills/react-best-practices/rules/js-index-maps.md +37 -0
  112. package/skills/react-best-practices/rules/js-length-check-first.md +49 -0
  113. package/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
  114. package/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
  115. package/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  116. package/skills/react-best-practices/rules/rendering-activity.md +26 -0
  117. package/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  118. package/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
  119. package/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
  120. package/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  121. package/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  122. package/skills/react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
  123. package/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
  124. package/skills/react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  125. package/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
  126. package/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
  127. package/skills/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  128. package/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
  129. package/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
  130. package/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  131. package/skills/react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
  132. package/skills/react-best-practices/rules/rerender-memo.md +44 -0
  133. package/skills/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  134. package/skills/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  135. package/skills/react-best-practices/rules/rerender-transitions.md +40 -0
  136. package/skills/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  137. package/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
  138. package/skills/react-best-practices/rules/server-auth-actions.md +96 -0
  139. package/skills/react-best-practices/rules/server-cache-lru.md +41 -0
  140. package/skills/react-best-practices/rules/server-cache-react.md +76 -0
  141. package/skills/react-best-practices/rules/server-dedup-props.md +65 -0
  142. package/skills/react-best-practices/rules/server-parallel-fetching.md +83 -0
  143. package/skills/react-best-practices/rules/server-serialization.md +38 -0
  144. package/skills/vibe-code-review/SKILL.md +70 -0
  145. package/skills/vibe-code-review/references/deep-audit.md +259 -0
  146. package/skills/vibe-code-review/references/pr-review.md +234 -0
  147. package/skills/vibe-code-review/references/quick-scan.md +178 -0
  148. package/skills/vibe-code-review/references/report-template.md +189 -0
  149. package/skills/vibe-code-review/references/trend-check.md +224 -0
  150. package/skills/vibe-code-review/scripts/generate-snapshot.sh +89 -0
  151. package/skills/vibe-code-review/scripts/pr-analyze.sh +180 -0
  152. package/skills/write-skill/SKILL.md +133 -0
  153. package/templates/bug.md +100 -0
  154. package/templates/change_request.md +105 -0
  155. package/templates/charter.md +144 -0
  156. package/templates/delivery_plan.md +44 -0
  157. package/templates/epic.md +203 -0
  158. package/templates/hotfix.md +58 -0
  159. package/templates/risk_registry.md +87 -0
  160. package/templates/roadmap.md +174 -0
  161. package/templates/spike.md +143 -0
  162. package/templates/sprint.md +134 -0
  163. package/templates/sprint_context.md +61 -0
  164. package/templates/sprint_report.md +215 -0
  165. package/templates/story.md +193 -0
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * close_sprint.mjs
5
+ * Sprint close automation — validates, archives, updates state.json.
6
+ *
7
+ * Usage:
8
+ * ./.vbounce/scripts/close_sprint.mjs S-05
9
+ */
10
+
11
+ import fs from 'fs';
12
+ import path from 'path';
13
+ import { fileURLToPath } from 'url';
14
+ import { spawnSync } from 'child_process';
15
+
16
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
17
+ const ROOT = path.resolve(__dirname, '../..');
18
+
19
+ const args = process.argv.slice(2);
20
+ if (args.length < 1) {
21
+ console.error('Usage: close_sprint.mjs S-XX');
22
+ process.exit(1);
23
+ }
24
+
25
+ const sprintId = args[0];
26
+ if (!/^S-\d{2}$/.test(sprintId)) {
27
+ console.error(`ERROR: sprint_id "${sprintId}" must match S-XX format`);
28
+ process.exit(1);
29
+ }
30
+
31
+ const sprintNum = sprintId.replace('S-', '');
32
+ const stateFile = path.join(ROOT, '.vbounce', 'state.json');
33
+
34
+ // 1. Read state.json
35
+ if (!fs.existsSync(stateFile)) {
36
+ console.error(`ERROR: .vbounce/state.json not found`);
37
+ process.exit(1);
38
+ }
39
+
40
+ const state = JSON.parse(fs.readFileSync(stateFile, 'utf8'));
41
+
42
+ if (state.sprint_id !== sprintId) {
43
+ console.error(`ERROR: state.json is for sprint ${state.sprint_id}, not ${sprintId}`);
44
+ process.exit(1);
45
+ }
46
+
47
+ // 2. Check all stories are terminal
48
+ const activeStories = Object.entries(state.stories || {}).filter(
49
+ ([, s]) => !['Done', 'Escalated', 'Parking Lot'].includes(s.state)
50
+ );
51
+
52
+ if (activeStories.length > 0) {
53
+ console.warn(`⚠ ${activeStories.length} stories are not in a terminal state:`);
54
+ activeStories.forEach(([id, s]) => console.warn(` - ${id}: ${s.state}`));
55
+ console.warn(' Proceed? These stories will be left incomplete.');
56
+ }
57
+
58
+ // 3. Create archive directory
59
+ const archiveDir = path.join(ROOT, '.vbounce', 'archive', sprintId);
60
+ fs.mkdirSync(archiveDir, { recursive: true });
61
+
62
+ // 4. Move sprint report if it exists
63
+ const reportSrc = path.join(ROOT, '.vbounce', `sprint-report-${sprintId}.md`);
64
+ const reportLegacy = path.join(ROOT, '.vbounce', 'sprint-report.md');
65
+ const reportDst = path.join(archiveDir, `sprint-report-${sprintId}.md`);
66
+
67
+ if (fs.existsSync(reportSrc)) {
68
+ fs.copyFileSync(reportSrc, reportDst);
69
+ console.log(`✓ Archived sprint report → .vbounce/archive/${sprintId}/sprint-report-${sprintId}.md`);
70
+ } else if (fs.existsSync(reportLegacy)) {
71
+ fs.copyFileSync(reportLegacy, reportDst);
72
+ console.log(`✓ Archived sprint report → .vbounce/archive/${sprintId}/sprint-report-${sprintId}.md`);
73
+ }
74
+
75
+ // 5. Update state.json
76
+ state.last_action = `Sprint ${sprintId} closed`;
77
+ state.updated_at = new Date().toISOString();
78
+ fs.writeFileSync(stateFile, JSON.stringify(state, null, 2));
79
+ console.log(`✓ Updated state.json`);
80
+
81
+ // 6. Print manual steps
82
+ const sprintPlanPath = `product_plans/sprints/sprint-${sprintNum}`;
83
+ const archivePath = `product_plans/archive/sprints/sprint-${sprintNum}`;
84
+
85
+ // 7. Auto-run improvement pipeline
86
+ console.log('');
87
+ console.log('Running self-improvement pipeline...');
88
+ const suggestScript = path.join(__dirname, 'suggest_improvements.mjs');
89
+ if (fs.existsSync(suggestScript)) {
90
+ // Run trends first (if available)
91
+ const trendsScript = path.join(__dirname, 'sprint_trends.mjs');
92
+ if (fs.existsSync(trendsScript)) {
93
+ const trendsResult = spawnSync(process.execPath, [trendsScript], {
94
+ stdio: 'inherit',
95
+ cwd: process.cwd(),
96
+ });
97
+ if (trendsResult.status !== 0) {
98
+ console.warn(' ⚠ Trends analysis returned non-zero — continuing.');
99
+ }
100
+ }
101
+
102
+ // Run suggest (which internally runs post_sprint_improve.mjs)
103
+ const suggestResult = spawnSync(process.execPath, [suggestScript, sprintId], {
104
+ stdio: 'inherit',
105
+ cwd: process.cwd(),
106
+ });
107
+ if (suggestResult.status !== 0) {
108
+ console.warn(' ⚠ Improvement suggestions returned non-zero.');
109
+ }
110
+ } else {
111
+ console.warn(' ⚠ suggest_improvements.mjs not found — skipping improvement pipeline.');
112
+ }
113
+
114
+ // Regenerate product graph (non-blocking)
115
+ const graphScript = path.join(__dirname, 'product_graph.mjs');
116
+ if (fs.existsSync(graphScript)) {
117
+ const graphResult = spawnSync(process.execPath, [graphScript], { stdio: 'pipe', cwd: process.cwd() });
118
+ if (graphResult.status === 0) {
119
+ console.log('✓ Product graph regenerated');
120
+ }
121
+ }
122
+
123
+ console.log('');
124
+ console.log('Manual steps remaining:');
125
+ console.log(` 1. Archive sprint plan folder:`);
126
+ console.log(` mv ${sprintPlanPath}/ ${archivePath}/`);
127
+ console.log(` 2. Update Delivery Plan §4 Completed Sprints with a summary row`);
128
+ console.log(` 3. Remove delivered stories from Delivery Plan §3 Backlog`);
129
+ console.log(` 4. Delete sprint branch (after merge to main):`);
130
+ console.log(` git branch -d sprint/${sprintId}`);
131
+ console.log(` 5. Review .vbounce/improvement-suggestions.md — approve/reject/defer each item`);
132
+ console.log(` 6. Run /improve to apply approved changes with brain-file sync`);
133
+ console.log('');
134
+ console.log(`✓ Sprint ${sprintId} closed.`);
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * complete_story.mjs
5
+ * Mark a story as Done — updates Sprint Plan §1 + §4, and state.json atomically.
6
+ *
7
+ * Usage:
8
+ * ./.vbounce/scripts/complete_story.mjs STORY-005-02 --qa-bounces 1 --arch-bounces 0 --correction-tax 5 --notes "Missing validation fixed"
9
+ */
10
+
11
+ import fs from 'fs';
12
+ import path from 'path';
13
+ import { fileURLToPath } from 'url';
14
+ import { spawnSync } from 'child_process';
15
+
16
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
17
+ const ROOT = path.resolve(__dirname, '../..');
18
+
19
+ function parseArgs(argv) {
20
+ const result = { storyId: null, qaBounces: 0, archBounces: 0, correctionTax: '0%', notes: '' };
21
+ const args = argv.slice(2);
22
+ result.storyId = args[0];
23
+ for (let i = 1; i < args.length; i++) {
24
+ if (args[i] === '--qa-bounces') result.qaBounces = parseInt(args[++i], 10) || 0;
25
+ else if (args[i] === '--arch-bounces') result.archBounces = parseInt(args[++i], 10) || 0;
26
+ else if (args[i] === '--correction-tax') result.correctionTax = args[++i] + (args[i].includes('%') ? '' : '%');
27
+ else if (args[i] === '--notes') result.notes = args[++i];
28
+ }
29
+ return result;
30
+ }
31
+
32
+ const { storyId, qaBounces, archBounces, correctionTax, notes } = parseArgs(process.argv);
33
+
34
+ if (!storyId) {
35
+ console.error('Usage: complete_story.mjs STORY-ID [--qa-bounces N] [--arch-bounces N] [--correction-tax N] [--notes "text"]');
36
+ process.exit(1);
37
+ }
38
+
39
+ // 1. Update state.json
40
+ const stateFile = path.join(ROOT, '.vbounce', 'state.json');
41
+ if (!fs.existsSync(stateFile)) {
42
+ console.error('ERROR: .vbounce/state.json not found');
43
+ process.exit(1);
44
+ }
45
+ const state = JSON.parse(fs.readFileSync(stateFile, 'utf8'));
46
+ if (!state.stories[storyId]) {
47
+ console.error(`ERROR: Story "${storyId}" not found in state.json`);
48
+ process.exit(1);
49
+ }
50
+ state.stories[storyId].state = 'Done';
51
+ state.stories[storyId].qa_bounces = qaBounces;
52
+ state.stories[storyId].arch_bounces = archBounces;
53
+ state.stories[storyId].worktree = null;
54
+ state.last_action = `${storyId} completed`;
55
+ state.updated_at = new Date().toISOString();
56
+ fs.writeFileSync(stateFile, JSON.stringify(state, null, 2));
57
+ console.log(`✓ Updated state.json: ${storyId} → Done`);
58
+
59
+ // 2. Find sprint plan
60
+ const sprintNum = state.sprint_id.replace('S-', '');
61
+ const sprintPlanPath = path.join(ROOT, 'product_plans', 'sprints', `sprint-${sprintNum}`, `sprint-${sprintNum}.md`);
62
+
63
+ if (!fs.existsSync(sprintPlanPath)) {
64
+ console.warn(`⚠ Sprint plan not found at ${sprintPlanPath}. Update §1 and §4 manually.`);
65
+ process.exit(0);
66
+ }
67
+
68
+ let content = fs.readFileSync(sprintPlanPath, 'utf8');
69
+
70
+ // 3. Update §1 table — find the row with storyId and change V-Bounce State to Done
71
+ const tableRowRegex = new RegExp(`(\\|[^|]*\\|[^|]*${storyId.replace(/[-]/g, '[-]')}[^|]*\\|[^|]*\\|[^|]*\\|)([^|]+)(\\|[^|]*\\|)`, 'g');
72
+ let updated = false;
73
+ content = content.replace(tableRowRegex, (match, before, stateCell, after) => {
74
+ updated = true;
75
+ return `${before} Done ${after}`;
76
+ });
77
+
78
+ if (!updated) {
79
+ console.warn(`⚠ Could not find ${storyId} row in §1 table. Update V-Bounce State manually.`);
80
+ }
81
+
82
+ // 4. Add row to §4 Execution Log
83
+ const logStart = '<!-- EXECUTION_LOG_START -->';
84
+ const logEnd = '<!-- EXECUTION_LOG_END -->';
85
+ const newRow = `| ${storyId} | Done | ${qaBounces} | ${archBounces} | ${correctionTax} | ${notes || '—'} |`;
86
+
87
+ if (content.includes(logStart)) {
88
+ // Find the table in the execution log section and append a row
89
+ const startIdx = content.indexOf(logStart);
90
+ const endIdx = content.indexOf(logEnd);
91
+
92
+ if (endIdx > startIdx) {
93
+ const before = content.substring(0, endIdx);
94
+ const after = content.substring(endIdx);
95
+
96
+ // Check if header row exists, if not add it
97
+ const section = before.substring(startIdx);
98
+ if (!section.includes('| Story |')) {
99
+ const headerRow = `\n| Story | Final State | QA Bounces | Arch Bounces | Correction Tax | Notes |\n|-------|-------------|------------|--------------|----------------|-------|`;
100
+ content = before + headerRow + '\n' + newRow + '\n' + after;
101
+ } else {
102
+ content = before + newRow + '\n' + after;
103
+ }
104
+ console.log(`✓ Added row to §4 Execution Log`);
105
+ }
106
+ } else {
107
+ // Append §4 section at end
108
+ content += `\n\n<!-- EXECUTION_LOG_START -->\n## 4. Execution Log\n\n| Story | Final State | QA Bounces | Arch Bounces | Correction Tax | Notes |\n|-------|-------------|------------|--------------|----------------|-------|\n${newRow}\n<!-- EXECUTION_LOG_END -->\n`;
109
+ console.log(`✓ Created §4 Execution Log with first row`);
110
+ }
111
+
112
+ fs.writeFileSync(sprintPlanPath, content);
113
+ console.log(`✓ Updated sprint plan: ${storyId} Done`);
114
+ console.log(`\n QA bounces: ${qaBounces} | Arch bounces: ${archBounces} | Correction tax: ${correctionTax}`);
115
+
116
+ // Regenerate product graph (non-blocking)
117
+ const graphScript = path.join(__dirname, 'product_graph.mjs');
118
+ if (fs.existsSync(graphScript)) {
119
+ const graphResult = spawnSync(process.execPath, [graphScript], { stdio: 'pipe', cwd: ROOT });
120
+ if (graphResult.status === 0) console.log('✓ Product graph regenerated');
121
+ }