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,157 @@
1
+ #!/bin/bash
2
+
3
+ # V-Bounce Engine: Hotfix Manager
4
+ # Handles edge cases for L1 Trivial tasks to save tokens and ensure framework integrity.
5
+
6
+ set -euo pipefail
7
+
8
+ # Ensure we're in a git repository
9
+ REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null) || {
10
+ echo "❌ Error: Not inside a git repository."
11
+ exit 1
12
+ }
13
+
14
+ COMMAND="${1:-}"
15
+
16
+ function show_help {
17
+ echo "V-Bounce Engine — Hotfix Manager"
18
+ echo ""
19
+ echo "Usage: ./.vbounce/scripts/hotfix_manager.sh <command> [args]"
20
+ echo ""
21
+ echo "Commands:"
22
+ echo " audit Run a lightweight static analysis on recent commits to detect architectural drift."
23
+ echo " sync Rebase all active git worktrees against the current sprint branch."
24
+ echo " ledger <title> <desc> Append a Hotfix entry to §8 Applied Hotfixes in the active DELIVERY_PLAN.md."
25
+ echo ""
26
+ echo "Examples:"
27
+ echo " ./.vbounce/scripts/hotfix_manager.sh audit"
28
+ echo " ./.vbounce/scripts/hotfix_manager.sh sync"
29
+ echo " ./.vbounce/scripts/hotfix_manager.sh ledger \"Fix Header\" \"Aligned the logo to the left\""
30
+ exit 1
31
+ }
32
+
33
+ if [ -z "$COMMAND" ]; then
34
+ show_help
35
+ fi
36
+
37
+ case "$COMMAND" in
38
+ audit)
39
+ echo "🔍 Running Token-Saving Hotfix Audit..."
40
+
41
+ # Determine how many commits exist on the branch so we don't overshoot
42
+ TOTAL_COMMITS=$(git rev-list --count HEAD 2>/dev/null || echo "0")
43
+ LOOKBACK=5
44
+ if [ "$TOTAL_COMMITS" -lt "$LOOKBACK" ]; then
45
+ LOOKBACK="$TOTAL_COMMITS"
46
+ fi
47
+
48
+ if [ "$LOOKBACK" -eq 0 ]; then
49
+ echo "✅ No commits to audit."
50
+ exit 0
51
+ fi
52
+
53
+ SUSPICIOUS=$(git diff "HEAD~${LOOKBACK}" HEAD -G'style=|console\.log|// TODO' --name-only 2>/dev/null || true)
54
+
55
+ if [ -n "$SUSPICIOUS" ]; then
56
+ echo "⚠️ WARNING: Potential architectural drift detected in recent commits."
57
+ echo "The following files contain inline styles, console.logs, or TODOs:"
58
+ echo "$SUSPICIOUS"
59
+ echo ""
60
+ echo "Action Required: The Architect agent MUST perform a Deep Audit on these files."
61
+ exit 1
62
+ else
63
+ echo "✅ No obvious architectural drift detected in recent commits."
64
+ exit 0
65
+ fi
66
+ ;;
67
+
68
+ sync)
69
+ echo "🔄 Syncing active worktrees with the latest changes..."
70
+
71
+ WORKTREE_DIR="${REPO_ROOT}/.worktrees"
72
+
73
+ if [ ! -d "$WORKTREE_DIR" ]; then
74
+ echo "✅ No active worktrees found at ${WORKTREE_DIR}. Nothing to sync."
75
+ exit 0
76
+ fi
77
+
78
+ CURRENT_BRANCH=$(git branch --show-current)
79
+
80
+ if [ -z "$CURRENT_BRANCH" ]; then
81
+ echo "❌ Error: Detached HEAD state. Cannot determine sprint branch for sync."
82
+ exit 1
83
+ fi
84
+
85
+ SYNC_COUNT=0
86
+ FAIL_COUNT=0
87
+
88
+ for dir in "${WORKTREE_DIR}"/*/; do
89
+ if [ -d "$dir" ]; then
90
+ WORKTREE_NAME=$(basename "$dir")
91
+ echo "Syncing worktree: $WORKTREE_NAME..."
92
+
93
+ if (cd "$dir" && git fetch origin && git rebase "origin/$CURRENT_BRANCH"); then
94
+ echo " ✅ Successfully synced $WORKTREE_NAME."
95
+ SYNC_COUNT=$((SYNC_COUNT + 1))
96
+ else
97
+ echo " ❌ Failed to sync $WORKTREE_NAME. Manual intervention required."
98
+ FAIL_COUNT=$((FAIL_COUNT + 1))
99
+ fi
100
+ fi
101
+ done
102
+
103
+ echo ""
104
+ echo "Sync complete: $SYNC_COUNT succeeded, $FAIL_COUNT failed."
105
+ [ "$FAIL_COUNT" -gt 0 ] && exit 1 || exit 0
106
+ ;;
107
+
108
+ ledger)
109
+ TITLE="${2:-}"
110
+ DESC="${3:-}"
111
+
112
+ if [ -z "$TITLE" ] || [ -z "$DESC" ]; then
113
+ echo "❌ Error: Missing title or description for the ledger."
114
+ echo "Usage: ./.vbounce/scripts/hotfix_manager.sh ledger \"Fix Header\" \"Aligned the logo to the left\""
115
+ exit 1
116
+ fi
117
+
118
+ # Find the active delivery plan (search from repo root)
119
+ DELIVERY_PLAN=$(find "${REPO_ROOT}/product_plans" -name "DELIVERY_PLAN.md" 2>/dev/null | head -n 1)
120
+
121
+ if [ -z "$DELIVERY_PLAN" ]; then
122
+ echo "❌ Error: No DELIVERY_PLAN.md found in product_plans/."
123
+ exit 1
124
+ fi
125
+
126
+ echo "📝 Updating Hotfix Ledger in $DELIVERY_PLAN..."
127
+
128
+ # Check if §8 Applied Hotfixes exists, if not, create it
129
+ if ! grep -q "## 8. Applied Hotfixes" "$DELIVERY_PLAN"; then
130
+ echo "" >> "$DELIVERY_PLAN"
131
+ echo "---" >> "$DELIVERY_PLAN"
132
+ echo "" >> "$DELIVERY_PLAN"
133
+ echo "## 8. Applied Hotfixes" >> "$DELIVERY_PLAN"
134
+ echo "" >> "$DELIVERY_PLAN"
135
+ echo "> L1 Trivial fixes that bypassed the Epic/Story hierarchy. Auto-appended by \`hotfix_manager.sh ledger\`." >> "$DELIVERY_PLAN"
136
+ echo "" >> "$DELIVERY_PLAN"
137
+ echo "| Date | Title | Brief Description |" >> "$DELIVERY_PLAN"
138
+ echo "|------|-------|-------------------|" >> "$DELIVERY_PLAN"
139
+ fi
140
+
141
+ # Append the new row
142
+ DATE=$(date "+%Y-%m-%d")
143
+ echo "| $DATE | $TITLE | $DESC |" >> "$DELIVERY_PLAN"
144
+
145
+ echo "✅ Ledger updated: \"$TITLE\" added to §8 Applied Hotfixes."
146
+ ;;
147
+
148
+ --help|-h|help)
149
+ show_help
150
+ ;;
151
+
152
+ *)
153
+ echo "❌ Unknown command: $COMMAND"
154
+ echo ""
155
+ show_help
156
+ ;;
157
+ esac
@@ -0,0 +1,151 @@
1
+ #!/usr/bin/env bash
2
+ # init_gate_config.sh — Auto-detect project stack and generate .vbounce/gate-checks.json
3
+ # Usage: ./.vbounce/scripts/init_gate_config.sh [project-path]
4
+ #
5
+ # Run once during project setup or when the improve skill suggests new checks.
6
+ # Safe to re-run — merges with existing config (preserves custom checks).
7
+
8
+ set -euo pipefail
9
+
10
+ PROJECT_PATH="${1:-.}"
11
+ PROJECT_PATH="$(cd "$PROJECT_PATH" && pwd)"
12
+ CONFIG_PATH="${PROJECT_PATH}/.vbounce/gate-checks.json"
13
+
14
+ RED='\033[0;31m'
15
+ GREEN='\033[0;32m'
16
+ YELLOW='\033[1;33m'
17
+ CYAN='\033[0;36m'
18
+ NC='\033[0m'
19
+
20
+ echo -e "${CYAN}V-Bounce Engine Gate Config Initializer${NC}"
21
+ echo -e "Project: ${PROJECT_PATH}"
22
+ echo ""
23
+
24
+ # ── Detect stack ─────────────────────────────────────────────────────
25
+
26
+ LANGUAGE="unknown"
27
+ FRAMEWORK="unknown"
28
+ TEST_RUNNER="unknown"
29
+ BUILD_CMD=""
30
+ LINT_CMD=""
31
+ TEST_CMD=""
32
+
33
+ # Language detection
34
+ if [[ -f "${PROJECT_PATH}/tsconfig.json" ]]; then
35
+ LANGUAGE="typescript"
36
+ elif [[ -f "${PROJECT_PATH}/package.json" ]]; then
37
+ LANGUAGE="javascript"
38
+ elif [[ -f "${PROJECT_PATH}/pyproject.toml" || -f "${PROJECT_PATH}/setup.py" || -f "${PROJECT_PATH}/requirements.txt" ]]; then
39
+ LANGUAGE="python"
40
+ elif [[ -f "${PROJECT_PATH}/Cargo.toml" ]]; then
41
+ LANGUAGE="rust"
42
+ elif [[ -f "${PROJECT_PATH}/go.mod" ]]; then
43
+ LANGUAGE="go"
44
+ elif [[ -f "${PROJECT_PATH}/build.gradle" || -f "${PROJECT_PATH}/pom.xml" ]]; then
45
+ LANGUAGE="java"
46
+ elif [[ -f "${PROJECT_PATH}/Package.swift" ]]; then
47
+ LANGUAGE="swift"
48
+ fi
49
+
50
+ echo -e "Language: ${GREEN}${LANGUAGE}${NC}"
51
+
52
+ # Framework detection (JS/TS ecosystem)
53
+ if [[ -f "${PROJECT_PATH}/package.json" ]]; then
54
+ PKG_CONTENT=$(cat "${PROJECT_PATH}/package.json")
55
+
56
+ if echo "$PKG_CONTENT" | grep -q '"next"'; then FRAMEWORK="nextjs"
57
+ elif echo "$PKG_CONTENT" | grep -q '"react"'; then FRAMEWORK="react"
58
+ elif echo "$PKG_CONTENT" | grep -q '"vue"'; then FRAMEWORK="vue"
59
+ elif echo "$PKG_CONTENT" | grep -q '"svelte"'; then FRAMEWORK="svelte"
60
+ elif echo "$PKG_CONTENT" | grep -q '"express"'; then FRAMEWORK="express"
61
+ elif echo "$PKG_CONTENT" | grep -q '"fastify"'; then FRAMEWORK="fastify"
62
+ elif echo "$PKG_CONTENT" | grep -q '"@angular/core"'; then FRAMEWORK="angular"
63
+ fi
64
+
65
+ # Test runner
66
+ if echo "$PKG_CONTENT" | grep -q '"vitest"'; then TEST_RUNNER="vitest"
67
+ elif echo "$PKG_CONTENT" | grep -q '"jest"'; then TEST_RUNNER="jest"
68
+ elif echo "$PKG_CONTENT" | grep -q '"mocha"'; then TEST_RUNNER="mocha"
69
+ elif echo "$PKG_CONTENT" | grep -q '"ava"'; then TEST_RUNNER="ava"
70
+ fi
71
+
72
+ # Commands from scripts
73
+ BUILD_CMD=$(node -e "try{const p=require('${PROJECT_PATH}/package.json');console.log(p.scripts&&p.scripts.build||'')}catch(e){}" 2>/dev/null || echo "")
74
+ LINT_CMD=$(node -e "try{const p=require('${PROJECT_PATH}/package.json');console.log(p.scripts&&p.scripts.lint||'')}catch(e){}" 2>/dev/null || echo "")
75
+ TEST_CMD=$(node -e "try{const p=require('${PROJECT_PATH}/package.json');const t=p.scripts&&p.scripts.test||'';if(t&&!t.includes('no test specified'))console.log(t);else console.log('')}catch(e){}" 2>/dev/null || echo "")
76
+ elif [[ "$LANGUAGE" == "python" ]]; then
77
+ if command -v pytest &>/dev/null; then TEST_RUNNER="pytest"; fi
78
+ if command -v ruff &>/dev/null; then LINT_CMD="ruff check ."; fi
79
+ elif [[ "$LANGUAGE" == "rust" ]]; then
80
+ TEST_RUNNER="cargo"
81
+ BUILD_CMD="cargo build"
82
+ LINT_CMD="cargo clippy"
83
+ elif [[ "$LANGUAGE" == "go" ]]; then
84
+ TEST_RUNNER="go"
85
+ BUILD_CMD="go build ./..."
86
+ LINT_CMD="golangci-lint run"
87
+ fi
88
+
89
+ echo -e "Framework: ${GREEN}${FRAMEWORK}${NC}"
90
+ echo -e "Test runner: ${GREEN}${TEST_RUNNER}${NC}"
91
+ [[ -n "$BUILD_CMD" ]] && echo -e "Build: ${GREEN}${BUILD_CMD}${NC}"
92
+ [[ -n "$LINT_CMD" ]] && echo -e "Lint: ${GREEN}${LINT_CMD}${NC}"
93
+ echo ""
94
+
95
+ # ── Generate config ──────────────────────────────────────────────────
96
+
97
+ # Build QA checks array
98
+ QA_CHECKS='[
99
+ { "id": "tests_exist", "enabled": true, "description": "Verify test files exist for modified source files" },
100
+ { "id": "tests_pass", "enabled": true, "description": "Run test suite" },
101
+ { "id": "build", "enabled": true, "description": "Run build command" },
102
+ { "id": "lint", "enabled": true, "description": "Run linter" },
103
+ { "id": "no_debug_output", "enabled": true, "description": "No debug statements in modified files" },
104
+ { "id": "no_todo_fixme", "enabled": true, "description": "No TODO/FIXME in modified files" },
105
+ { "id": "exports_have_docs", "enabled": true, "description": "Exported symbols have doc comments" }
106
+ ]'
107
+
108
+ # Build Architect checks array
109
+ ARCH_CHECKS='[
110
+ { "id": "tests_exist", "enabled": true, "description": "Verify test files exist for modified source files" },
111
+ { "id": "tests_pass", "enabled": true, "description": "Run test suite" },
112
+ { "id": "build", "enabled": true, "description": "Run build command" },
113
+ { "id": "lint", "enabled": true, "description": "Run linter" },
114
+ { "id": "no_debug_output", "enabled": true, "description": "No debug statements in modified files" },
115
+ { "id": "no_todo_fixme", "enabled": true, "description": "No TODO/FIXME in modified files" },
116
+ { "id": "exports_have_docs", "enabled": true, "description": "Exported symbols have doc comments" },
117
+ { "id": "no_new_deps", "enabled": true, "description": "No new dependencies without review" },
118
+ { "id": "file_size", "enabled": true, "max_lines": 500, "description": "Source files under 500 lines" }
119
+ ]'
120
+
121
+ # Write config
122
+ mkdir -p "$(dirname "$CONFIG_PATH")"
123
+
124
+ cat > "$CONFIG_PATH" << HEREDOC
125
+ {
126
+ "version": 1,
127
+ "detected_stack": {
128
+ "language": "${LANGUAGE}",
129
+ "framework": "${FRAMEWORK}",
130
+ "test_runner": "${TEST_RUNNER}",
131
+ "build_cmd": "${BUILD_CMD}",
132
+ "lint_cmd": "${LINT_CMD}",
133
+ "test_cmd": "${TEST_CMD}"
134
+ },
135
+ "qa_checks": ${QA_CHECKS},
136
+ "arch_checks": ${ARCH_CHECKS},
137
+ "custom_checks": []
138
+ }
139
+ HEREDOC
140
+
141
+ echo -e "${GREEN}Generated: ${CONFIG_PATH}${NC}"
142
+ echo ""
143
+ echo "Universal checks enabled. To add project-specific checks:"
144
+ echo " 1. Run sprints and let agents collect Process Feedback"
145
+ echo " 2. Use the 'improve' skill to propose new checks"
146
+ echo " 3. Or manually add entries to the custom_checks array"
147
+ echo ""
148
+ echo -e "Example custom check (add to custom_checks):"
149
+ echo ' { "id": "custom_grep", "gate": "arch", "enabled": true,'
150
+ echo ' "pattern": "var\\(--my-prefix-", "glob": "*.tsx",'
151
+ echo ' "should_find": false, "description": "No raw CSS vars in components" }'
@@ -0,0 +1,129 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * init_sprint.mjs
5
+ * Sprint setup automation — creates state.json, sprint plan dir, and prints git commands.
6
+ *
7
+ * Usage:
8
+ * ./.vbounce/scripts/init_sprint.mjs S-06 D-02 --stories STORY-011-05,STORY-005-01,STORY-005-02
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
+
21
+ if (args.length < 2) {
22
+ console.error('Usage: init_sprint.mjs S-XX D-NN [--stories STORY-ID1,STORY-ID2,...]');
23
+ process.exit(1);
24
+ }
25
+
26
+ const sprintId = args[0]; // e.g. S-06
27
+ const deliveryId = args[1]; // e.g. D-02
28
+
29
+ if (!/^S-\d{2}$/.test(sprintId)) {
30
+ console.error(`ERROR: sprint_id "${sprintId}" must match S-XX format`);
31
+ process.exit(1);
32
+ }
33
+ if (!/^D-\d{2}$/.test(deliveryId)) {
34
+ console.error(`ERROR: delivery_id "${deliveryId}" must match D-NN format`);
35
+ process.exit(1);
36
+ }
37
+
38
+ const storiesArg = args.indexOf('--stories');
39
+ const storyIds = storiesArg !== -1 ? args[storiesArg + 1].split(',') : [];
40
+
41
+ // 1. Create .vbounce/ directory
42
+ const bounceDir = path.join(ROOT, '.vbounce');
43
+ fs.mkdirSync(bounceDir, { recursive: true });
44
+ fs.mkdirSync(path.join(bounceDir, 'archive'), { recursive: true });
45
+ fs.mkdirSync(path.join(bounceDir, 'reports'), { recursive: true });
46
+
47
+ // 2. Create state.json
48
+ const stateFile = path.join(bounceDir, 'state.json');
49
+ if (fs.existsSync(stateFile)) {
50
+ console.warn(`⚠ state.json already exists. Overwriting...`);
51
+ }
52
+
53
+ const sprintNum = sprintId.replace('S-', '');
54
+ const stories = {};
55
+ for (const id of storyIds) {
56
+ stories[id.trim()] = {
57
+ state: 'Draft',
58
+ qa_bounces: 0,
59
+ arch_bounces: 0,
60
+ worktree: null
61
+ };
62
+ }
63
+
64
+ const state = {
65
+ sprint_id: sprintId,
66
+ delivery_id: deliveryId,
67
+ sprint_plan: `product_plans/sprints/sprint-${sprintNum}/sprint-${sprintNum}.md`,
68
+ delivery_plan: `product_plans/strategy/${deliveryId}_DELIVERY_PLAN.md`,
69
+ stories,
70
+ phase: 'Phase 1',
71
+ last_action: `Sprint ${sprintId} initialized`,
72
+ updated_at: new Date().toISOString()
73
+ };
74
+
75
+ fs.writeFileSync(stateFile, JSON.stringify(state, null, 2));
76
+ console.log(`✓ Created .vbounce/state.json`);
77
+
78
+ // 3. Create sprint plan directory
79
+ const sprintDir = path.join(ROOT, 'product_plans', 'sprints', `sprint-${sprintNum}`);
80
+ fs.mkdirSync(sprintDir, { recursive: true });
81
+
82
+ const sprintPlanFile = path.join(sprintDir, `sprint-${sprintNum}.md`);
83
+ if (!fs.existsSync(sprintPlanFile)) {
84
+ // Copy from template
85
+ const templateFile = path.join(ROOT, '.vbounce', 'templates', 'sprint.md');
86
+ if (fs.existsSync(templateFile)) {
87
+ let content = fs.readFileSync(templateFile, 'utf8');
88
+ // Replace placeholders
89
+ content = content.replace(/sprint-\{XX\}/g, `sprint-${sprintNum}`);
90
+ content = content.replace(/S-\{XX\}/g, sprintId);
91
+ content = content.replace(/D-\{NN\}/g, deliveryId);
92
+ content = content.replace(/status: "Planning \/ Active \/ Completed"/, 'status: "Planning"');
93
+ // Strip instructions block
94
+ content = content.replace(/<instructions>[\s\S]*?<\/instructions>\n\n/, '');
95
+ fs.writeFileSync(sprintPlanFile, content);
96
+ console.log(`✓ Created product_plans/sprints/sprint-${sprintNum}/sprint-${sprintNum}.md`);
97
+ } else {
98
+ // Create minimal sprint plan
99
+ const minimal = `---\nsprint_id: "${sprintId}"\nsprint_goal: "TBD"\ndates: "TBD"\nstatus: "Planning"\ndelivery: "${deliveryId}"\n---\n\n# Sprint ${sprintId} Plan\n\n## 1. Active Scope\n\n| Priority | Story | Epic | Label | V-Bounce State | Blocker |\n|----------|-------|------|-------|----------------|---------|\n${storyIds.map((id, i) => `| ${i + 1} | ${id.trim()} | — | L2 | Draft | — |`).join('\n')}\n\n### Escalated / Parking Lot\n- (none)\n\n---\n\n## 2. Execution Strategy\n\n### Phase Plan\n- **Phase 1 (parallel)**: ${storyIds.join(', ')}\n\n### Risk Flags\n- (TBD)\n\n---\n\n## 3. Sprint Open Questions\n\n| Question | Options | Impact | Owner | Status |\n|----------|---------|--------|-------|--------|\n\n---\n\n<!-- EXECUTION_LOG_START -->\n## 4. Execution Log\n\n| Story | Final State | QA Bounces | Arch Bounces | Correction Tax | Notes |\n|-------|-------------|------------|--------------|----------------|-------|\n<!-- EXECUTION_LOG_END -->\n`;
100
+ fs.writeFileSync(sprintPlanFile, minimal);
101
+ console.log(`✓ Created product_plans/sprints/sprint-${sprintNum}/sprint-${sprintNum}.md (minimal — template not found)`);
102
+ }
103
+ } else {
104
+ console.log(` Sprint plan already exists: product_plans/sprints/sprint-${sprintNum}/sprint-${sprintNum}.md`);
105
+ }
106
+
107
+ // 4. Print git commands (don't execute)
108
+ console.log('');
109
+ console.log('Run these git commands to initialize the sprint branch:');
110
+ console.log(` git checkout -b sprint/${sprintId} main`);
111
+ if (storyIds.length > 0) {
112
+ console.log('');
113
+ console.log('Then create worktrees for each story:');
114
+ storyIds.forEach(id => {
115
+ const trimmed = id.trim();
116
+ console.log(` git worktree add .worktrees/${trimmed} -b story/${trimmed} sprint/${sprintId}`);
117
+ console.log(` mkdir -p .worktrees/${trimmed}/.vbounce/{tasks,reports}`);
118
+ });
119
+ }
120
+
121
+ // 5. Regenerate product graph (non-blocking)
122
+ const graphScript = path.join(__dirname, 'product_graph.mjs');
123
+ if (fs.existsSync(graphScript)) {
124
+ const graphResult = spawnSync(process.execPath, [graphScript], { stdio: 'pipe', cwd: ROOT });
125
+ if (graphResult.status === 0) console.log('✓ Product graph regenerated');
126
+ }
127
+
128
+ console.log('');
129
+ console.log(`✓ Sprint ${sprintId} initialized. Stories: ${storyIds.length > 0 ? storyIds.join(', ') : 'none (add manually)'}`);