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.
- package/README.md +142 -0
- package/VBOUNCE_MANIFEST.md +404 -0
- package/bin/vbounce.mjs +882 -0
- package/brains/AGENTS.md +71 -0
- package/brains/CHANGELOG.md +398 -0
- package/brains/CLAUDE.md +90 -0
- package/brains/GEMINI.md +102 -0
- package/brains/SETUP.md +195 -0
- package/brains/claude-agents/architect.md +226 -0
- package/brains/claude-agents/developer.md +133 -0
- package/brains/claude-agents/devops.md +267 -0
- package/brains/claude-agents/explorer.md +157 -0
- package/brains/claude-agents/qa.md +225 -0
- package/brains/claude-agents/scribe.md +171 -0
- package/brains/copilot/copilot-instructions.md +54 -0
- package/brains/cursor-rules/vbounce-docs.mdc +45 -0
- package/brains/cursor-rules/vbounce-process.mdc +51 -0
- package/brains/cursor-rules/vbounce-rules.mdc +29 -0
- package/brains/windsurf/.windsurfrules +35 -0
- package/docs/HOTFIX_EDGE_CASES.md +37 -0
- package/docs/IMPROVEMENT.md +46 -0
- package/docs/agent-skill-profiles.docx +0 -0
- package/docs/icons/alert.svg +1 -0
- package/docs/icons/beaker.svg +1 -0
- package/docs/icons/book.svg +1 -0
- package/docs/icons/git-branch.svg +1 -0
- package/docs/icons/git-merge.svg +1 -0
- package/docs/icons/graph.svg +1 -0
- package/docs/icons/light-bulb.svg +1 -0
- package/docs/icons/logo.svg +9 -0
- package/docs/icons/pencil.svg +1 -0
- package/docs/icons/rocket.svg +1 -0
- package/docs/icons/shield.svg +1 -0
- package/docs/icons/sync.svg +1 -0
- package/docs/icons/terminal.svg +1 -0
- package/docs/icons/tools.svg +1 -0
- package/docs/icons/zap.svg +1 -0
- package/docs/images/bounce_loop_diagram.png +0 -0
- package/docs/vbounce-os-manual.docx +0 -0
- package/package.json +48 -0
- package/scripts/close_sprint.mjs +134 -0
- package/scripts/complete_story.mjs +121 -0
- package/scripts/count_tokens.mjs +494 -0
- package/scripts/doctor.mjs +144 -0
- package/scripts/hotfix_manager.sh +157 -0
- package/scripts/init_gate_config.sh +151 -0
- package/scripts/init_sprint.mjs +129 -0
- package/scripts/post_sprint_improve.mjs +486 -0
- package/scripts/pre_gate_common.sh +576 -0
- package/scripts/pre_gate_runner.sh +176 -0
- package/scripts/prep_arch_context.mjs +178 -0
- package/scripts/prep_qa_context.mjs +152 -0
- package/scripts/prep_sprint_context.mjs +141 -0
- package/scripts/prep_sprint_summary.mjs +154 -0
- package/scripts/product_graph.mjs +387 -0
- package/scripts/product_impact.mjs +167 -0
- package/scripts/sprint_trends.mjs +160 -0
- package/scripts/suggest_improvements.mjs +363 -0
- package/scripts/update_state.mjs +132 -0
- package/scripts/validate_bounce_readiness.mjs +152 -0
- package/scripts/validate_report.mjs +165 -0
- package/scripts/validate_sprint_plan.mjs +117 -0
- package/scripts/validate_state.mjs +99 -0
- package/scripts/vdoc_match.mjs +269 -0
- package/scripts/vdoc_staleness.mjs +199 -0
- package/scripts/verify_framework.mjs +122 -0
- package/scripts/verify_framework.sh +13 -0
- package/skills/agent-team/SKILL.md +579 -0
- package/skills/agent-team/references/cleanup.md +42 -0
- package/skills/agent-team/references/delivery-sync.md +43 -0
- package/skills/agent-team/references/discovery.md +97 -0
- package/skills/agent-team/references/git-strategy.md +52 -0
- package/skills/agent-team/references/mid-sprint-triage.md +85 -0
- package/skills/agent-team/references/report-naming.md +34 -0
- package/skills/doc-manager/SKILL.md +444 -0
- package/skills/file-organization/SKILL.md +146 -0
- package/skills/file-organization/TEST-RESULTS.md +193 -0
- package/skills/file-organization/evals/evals.json +41 -0
- package/skills/file-organization/references/gitignore-template.md +53 -0
- package/skills/file-organization/references/quick-checklist.md +48 -0
- package/skills/improve/SKILL.md +296 -0
- package/skills/lesson/SKILL.md +136 -0
- package/skills/product-graph/SKILL.md +102 -0
- package/skills/react-best-practices/SKILL.md +3014 -0
- package/skills/react-best-practices/rules/_sections.md +46 -0
- package/skills/react-best-practices/rules/_template.md +28 -0
- package/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/skills/react-best-practices/rules/advanced-init-once.md +42 -0
- package/skills/react-best-practices/rules/advanced-use-latest.md +39 -0
- package/skills/react-best-practices/rules/async-api-routes.md +38 -0
- package/skills/react-best-practices/rules/async-defer-await.md +80 -0
- package/skills/react-best-practices/rules/async-dependencies.md +51 -0
- package/skills/react-best-practices/rules/async-parallel.md +28 -0
- package/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
- package/skills/react-best-practices/rules/bundle-conditional.md +31 -0
- package/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/skills/react-best-practices/rules/bundle-preload.md +50 -0
- package/skills/react-best-practices/rules/client-event-listeners.md +74 -0
- package/skills/react-best-practices/rules/client-localstorage-schema.md +71 -0
- package/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
- package/skills/react-best-practices/rules/js-batch-dom-css.md +107 -0
- package/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
- package/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/skills/react-best-practices/rules/js-cache-storage.md +70 -0
- package/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/skills/react-best-practices/rules/js-early-exit.md +50 -0
- package/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/skills/react-best-practices/rules/js-index-maps.md +37 -0
- package/skills/react-best-practices/rules/js-length-check-first.md +49 -0
- package/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/skills/react-best-practices/rules/rendering-activity.md +26 -0
- package/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/skills/react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
- package/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/skills/react-best-practices/rules/rendering-usetransition-loading.md +75 -0
- package/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/skills/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
- package/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/skills/react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
- package/skills/react-best-practices/rules/rerender-memo.md +44 -0
- package/skills/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
- package/skills/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
- package/skills/react-best-practices/rules/rerender-transitions.md +40 -0
- package/skills/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
- package/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/skills/react-best-practices/rules/server-auth-actions.md +96 -0
- package/skills/react-best-practices/rules/server-cache-lru.md +41 -0
- package/skills/react-best-practices/rules/server-cache-react.md +76 -0
- package/skills/react-best-practices/rules/server-dedup-props.md +65 -0
- package/skills/react-best-practices/rules/server-parallel-fetching.md +83 -0
- package/skills/react-best-practices/rules/server-serialization.md +38 -0
- package/skills/vibe-code-review/SKILL.md +70 -0
- package/skills/vibe-code-review/references/deep-audit.md +259 -0
- package/skills/vibe-code-review/references/pr-review.md +234 -0
- package/skills/vibe-code-review/references/quick-scan.md +178 -0
- package/skills/vibe-code-review/references/report-template.md +189 -0
- package/skills/vibe-code-review/references/trend-check.md +224 -0
- package/skills/vibe-code-review/scripts/generate-snapshot.sh +89 -0
- package/skills/vibe-code-review/scripts/pr-analyze.sh +180 -0
- package/skills/write-skill/SKILL.md +133 -0
- package/templates/bug.md +100 -0
- package/templates/change_request.md +105 -0
- package/templates/charter.md +144 -0
- package/templates/delivery_plan.md +44 -0
- package/templates/epic.md +203 -0
- package/templates/hotfix.md +58 -0
- package/templates/risk_registry.md +87 -0
- package/templates/roadmap.md +174 -0
- package/templates/spike.md +143 -0
- package/templates/sprint.md +134 -0
- package/templates/sprint_context.md +61 -0
- package/templates/sprint_report.md +215 -0
- 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)'}`);
|