@pjmendonca/devflow 1.13.1 → 1.18.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/.claude/commands/agent.md +1 -1
- package/.claude/commands/bugfix.md +21 -0
- package/.claude/commands/checkpoint.md +0 -1
- package/.claude/commands/collab.md +0 -1
- package/.claude/commands/costs.md +88 -18
- package/.claude/commands/devflow.md +26 -0
- package/.claude/commands/handoff.md +0 -1
- package/.claude/commands/memory.md +0 -1
- package/.claude/commands/pair.md +0 -1
- package/.claude/commands/review.md +27 -0
- package/.claude/commands/route.md +0 -1
- package/.claude/commands/swarm.md +0 -1
- package/.claude/commands/validate.md +55 -0
- package/.claude/hooks/session-notification.sh +44 -0
- package/.claude/hooks/session-startup.sh +427 -0
- package/.claude/hooks/session-stop.sh +38 -0
- package/.claude/hooks/session_tracker.py +272 -0
- package/.claude/settings.json +38 -0
- package/.claude/skills/costs/SKILL.md +156 -0
- package/.claude/skills/validate/SKILL.md +101 -0
- package/CHANGELOG.md +254 -0
- package/README.md +207 -10
- package/bin/devflow-install.js +2 -1
- package/bin/devflow.js +5 -2
- package/lib/constants.js +0 -1
- package/lib/exec-python.js +1 -1
- package/package.json +1 -2
- package/tooling/.automation/.checkpoint_lock +1 -0
- package/tooling/.automation/agents/architect.md +19 -0
- package/tooling/.automation/agents/ba.md +19 -0
- package/tooling/.automation/agents/maintainer.md +19 -0
- package/tooling/.automation/agents/pm.md +19 -0
- package/tooling/.automation/agents/reviewer.md +1 -1
- package/tooling/.automation/agents/writer.md +19 -0
- package/tooling/.automation/benchmarks/benchmark_20251230_100119.json +314 -0
- package/tooling/.automation/benchmarks/benchmark_20251230_100216.json +314 -0
- package/tooling/.automation/costs/config.json +31 -0
- package/tooling/.automation/costs/sessions/2025-12-29_20251229_164128.json +22 -0
- package/tooling/.automation/memory/knowledge/kg_integration-test.json +707 -1
- package/tooling/.automation/memory/knowledge/kg_test-story.json +3273 -2
- package/tooling/.automation/memory/shared/shared_integration-test.json +181 -1
- package/tooling/.automation/memory/shared/shared_test-story.json +721 -1
- package/tooling/.automation/memory/shared/shared_test.json +1254 -0
- package/tooling/.automation/memory/shared/shared_validation-check.json +227 -0
- package/tooling/.automation/overrides/templates/architect/cloud-native.yaml +5 -5
- package/tooling/.automation/overrides/templates/architect/enterprise-architect.yaml +23 -5
- package/tooling/.automation/overrides/templates/architect/pragmatic-minimalist.yaml +24 -6
- package/tooling/.automation/overrides/templates/ba/agile-storyteller.yaml +4 -4
- package/tooling/.automation/overrides/templates/ba/domain-expert.yaml +4 -4
- package/tooling/.automation/overrides/templates/ba/requirements-engineer.yaml +4 -4
- package/tooling/.automation/overrides/templates/dev/performance-engineer.yaml +18 -0
- package/tooling/.automation/overrides/templates/dev/rapid-prototyper.yaml +19 -1
- package/tooling/.automation/overrides/templates/dev/security-focused.yaml +18 -0
- package/tooling/.automation/overrides/templates/dev/user-advocate.yaml +54 -0
- package/tooling/.automation/overrides/templates/maintainer/devops-maintainer.yaml +4 -4
- package/tooling/.automation/overrides/templates/maintainer/legacy-steward.yaml +4 -4
- package/tooling/.automation/overrides/templates/maintainer/oss-maintainer.yaml +4 -4
- package/tooling/.automation/overrides/templates/maintainer/reliability-engineer.yaml +55 -0
- package/tooling/.automation/overrides/templates/pm/agile-pm.yaml +4 -4
- package/tooling/.automation/overrides/templates/pm/hybrid-delivery.yaml +3 -3
- package/tooling/.automation/overrides/templates/pm/traditional-pm.yaml +4 -4
- package/tooling/.automation/overrides/templates/reviewer/quick-sanity.yaml +18 -0
- package/tooling/.automation/overrides/templates/reviewer/thorough-critic.yaml +18 -0
- package/tooling/.automation/overrides/templates/sm/agile-coach.yaml +2 -2
- package/tooling/.automation/overrides/templates/sm/startup-pm.yaml +3 -3
- package/tooling/.automation/overrides/templates/writer/api-documentarian.yaml +5 -5
- package/tooling/.automation/overrides/templates/writer/docs-as-code.yaml +4 -4
- package/tooling/.automation/overrides/templates/writer/user-guide-author.yaml +5 -5
- package/tooling/.automation/validation/history/2025-12-29_val_002a28c1.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_01273bb1.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_03369914.json +41 -0
- package/tooling/.automation/validation/history/2025-12-29_val_07a449ba.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_0df1f0a2.json +41 -0
- package/tooling/.automation/validation/history/2025-12-29_val_10ff3d34.json +41 -0
- package/tooling/.automation/validation/history/2025-12-29_val_110771d7.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_13f3a7f9.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_17ba9d21.json +41 -0
- package/tooling/.automation/validation/history/2025-12-29_val_22247089.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_227ea6a4.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_2335d5ae.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_246824bb.json +41 -0
- package/tooling/.automation/validation/history/2025-12-29_val_28b4b9cd.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_2abd12cc.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_2c801b2f.json +59 -0
- package/tooling/.automation/validation/history/2025-12-29_val_2c8cfa8e.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_2ce76eb0.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_30351948.json +41 -0
- package/tooling/.automation/validation/history/2025-12-29_val_30eb7229.json +41 -0
- package/tooling/.automation/validation/history/2025-12-29_val_34df0e77.json +41 -0
- package/tooling/.automation/validation/history/2025-12-29_val_376e4d6a.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_3a4e8a1a.json +59 -0
- package/tooling/.automation/validation/history/2025-12-29_val_3b77a628.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_3ea4e1cf.json +59 -0
- package/tooling/.automation/validation/history/2025-12-29_val_44aacdb4.json +59 -0
- package/tooling/.automation/validation/history/2025-12-29_val_457ddfa8.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_45af6238.json +41 -0
- package/tooling/.automation/validation/history/2025-12-29_val_4735dba1.json +41 -0
- package/tooling/.automation/validation/history/2025-12-29_val_486b203c.json +41 -0
- package/tooling/.automation/validation/history/2025-12-29_val_49dc56cd.json +59 -0
- package/tooling/.automation/validation/history/2025-12-29_val_4d863d6d.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_5149a808.json +59 -0
- package/tooling/.automation/validation/history/2025-12-29_val_52e0bb43.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_585d6319.json +59 -0
- package/tooling/.automation/validation/history/2025-12-29_val_5b2d859a.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_635a7081.json +41 -0
- package/tooling/.automation/validation/history/2025-12-29_val_64df4905.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_70634cee.json +41 -0
- package/tooling/.automation/validation/history/2025-12-29_val_714553f9.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_7f7bfdbf.json +41 -0
- package/tooling/.automation/validation/history/2025-12-29_val_7faad91d.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_81821f8f.json +41 -0
- package/tooling/.automation/validation/history/2025-12-29_val_8249f3c9.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_8422b50f.json +41 -0
- package/tooling/.automation/validation/history/2025-12-29_val_8446c134.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_879f4e26.json +59 -0
- package/tooling/.automation/validation/history/2025-12-29_val_8b6d5bd7.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_8c5cd787.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_91d20bc7.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_958a12b7.json +41 -0
- package/tooling/.automation/validation/history/2025-12-29_val_95d91108.json +41 -0
- package/tooling/.automation/validation/history/2025-12-29_val_980dbb74.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_9e40c79b.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_9f499b7c.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_9f7c3b57.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_a30d5bd4.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_a6eb09c7.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_a86f7b83.json +41 -0
- package/tooling/.automation/validation/history/2025-12-29_val_ad5347e1.json +41 -0
- package/tooling/.automation/validation/history/2025-12-29_val_b0a5a993.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_bcb0192e.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_bf3c9aaa.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_c461ff88.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_c4f4e258.json +41 -0
- package/tooling/.automation/validation/history/2025-12-29_val_c7f0fa6d.json +41 -0
- package/tooling/.automation/validation/history/2025-12-29_val_c911b0e6.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_cc581964.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_cdd5a33b.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_cfd42495.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_d1c7a4ee.json +41 -0
- package/tooling/.automation/validation/history/2025-12-29_val_d2280d0e.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_d2a6ff69.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_d8c53ab2.json +59 -0
- package/tooling/.automation/validation/history/2025-12-29_val_d9c1247a.json +41 -0
- package/tooling/.automation/validation/history/2025-12-29_val_d9d58569.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_dabb4fd9.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_dd8fe359.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_decdffc9.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_e3a95476.json +59 -0
- package/tooling/.automation/validation/history/2025-12-29_val_e776dfca.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_ea70969f.json +59 -0
- package/tooling/.automation/validation/history/2025-12-29_val_ef41ea95.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_f384f9b1.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_f8adc38c.json +41 -0
- package/tooling/.automation/validation/history/2025-12-29_val_fa40b69e.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_fc538d54.json +41 -0
- package/tooling/.automation/validation/history/2025-12-29_val_fe814665.json +32 -0
- package/tooling/.automation/validation/history/2025-12-29_val_ffea4b12.json +32 -0
- package/tooling/.automation/validation/history/2025-12-30_val_02d001e5.json +59 -0
- package/tooling/.automation/validation/history/2025-12-30_val_0b8966dc.json +32 -0
- package/tooling/.automation/validation/history/2025-12-30_val_15455fbf.json +59 -0
- package/tooling/.automation/validation/history/2025-12-30_val_157e34b9.json +32 -0
- package/tooling/.automation/validation/history/2025-12-30_val_28d1d933.json +32 -0
- package/tooling/.automation/validation/history/2025-12-30_val_3442a52c.json +32 -0
- package/tooling/.automation/validation/history/2025-12-30_val_37f1ce1e.json +32 -0
- package/tooling/.automation/validation/history/2025-12-30_val_4f1d8a93.json +32 -0
- package/tooling/.automation/validation/history/2025-12-30_val_56ff1de3.json +32 -0
- package/tooling/.automation/validation/history/2025-12-30_val_664fd4e2.json +41 -0
- package/tooling/.automation/validation/history/2025-12-30_val_66afb0a7.json +32 -0
- package/tooling/.automation/validation/history/2025-12-30_val_7634663c.json +41 -0
- package/tooling/.automation/validation/history/2025-12-30_val_8ea830c3.json +41 -0
- package/tooling/.automation/validation/history/2025-12-30_val_998957c2.json +32 -0
- package/tooling/.automation/validation/history/2025-12-30_val_a52177db.json +32 -0
- package/tooling/.automation/validation/history/2025-12-30_val_a5b65a63.json +32 -0
- package/tooling/.automation/validation/history/2025-12-30_val_ae391d0e.json +32 -0
- package/tooling/.automation/validation/history/2025-12-30_val_c7895339.json +41 -0
- package/tooling/.automation/validation/history/2025-12-30_val_ca416593.json +41 -0
- package/tooling/.automation/validation/history/2025-12-30_val_cee19422.json +32 -0
- package/tooling/.automation/validation/history/2025-12-30_val_ddd4f4e6.json +32 -0
- package/tooling/.automation/validation/history/2025-12-30_val_f2e1394b.json +32 -0
- package/tooling/.automation/validation/history/2025-12-30_val_f4a7fa06.json +41 -0
- package/tooling/.automation/validation/history/2025-12-30_val_ffea3369.json +32 -0
- package/tooling/.automation/validation-config.yaml +103 -0
- package/tooling/completions/DevflowCompletion.ps1 +21 -21
- package/tooling/completions/_run-story +3 -3
- package/tooling/completions/run-story-completion.bash +8 -8
- package/tooling/docs/DOC-STANDARD.md +14 -14
- package/tooling/docs/templates/migration-spec.md +4 -4
- package/tooling/scripts/context_checkpoint.py +5 -15
- package/tooling/scripts/cost_dashboard.py +610 -13
- package/tooling/scripts/create-persona.py +1 -12
- package/tooling/scripts/create-persona.sh +44 -44
- package/tooling/scripts/lib/__init__.py +12 -1
- package/tooling/scripts/lib/agent_handoff.py +11 -2
- package/tooling/scripts/lib/agent_router.py +31 -10
- package/tooling/scripts/lib/colors.py +106 -0
- package/tooling/scripts/lib/context_monitor.py +766 -0
- package/tooling/scripts/lib/cost_config.py +229 -10
- package/tooling/scripts/lib/cost_display.py +20 -45
- package/tooling/scripts/lib/cost_tracker.py +462 -15
- package/tooling/scripts/lib/currency_converter.py +28 -5
- package/tooling/scripts/lib/pair_programming.py +102 -3
- package/tooling/scripts/lib/personality_system.py +949 -0
- package/tooling/scripts/lib/platform.py +55 -0
- package/tooling/scripts/lib/shared_memory.py +9 -3
- package/tooling/scripts/lib/swarm_orchestrator.py +514 -75
- package/tooling/scripts/lib/validation_loop.py +1014 -0
- package/tooling/scripts/memory_summarize.py +9 -2
- package/tooling/scripts/new-doc.py +2 -9
- package/tooling/scripts/personalize_agent.py +1 -12
- package/tooling/scripts/rollback-migration.sh +60 -60
- package/tooling/scripts/run-collab.ps1 +16 -16
- package/tooling/scripts/run-collab.py +88 -53
- package/tooling/scripts/run-collab.sh +4 -4
- package/tooling/scripts/run-story.py +278 -20
- package/tooling/scripts/run-story.sh +3 -3
- package/tooling/scripts/setup-checkpoint-service.py +2 -9
- package/tooling/scripts/tech-debt-tracker.py +1 -12
- package/tooling/scripts/test_adversarial_swarm.py +452 -0
- package/tooling/scripts/update_version.py +48 -2
- package/tooling/scripts/validate-overrides.py +1 -10
- package/tooling/scripts/validate-overrides.sh +40 -40
- package/tooling/scripts/validate_loop.py +162 -0
- package/tooling/scripts/validate_setup.py +2 -30
- package/.claude/skills/init/SKILL.md +0 -496
- package/bin/devflow-init.js +0 -10
- package/tooling/scripts/init-project-workflow.ps1 +0 -651
- package/tooling/scripts/init-project-workflow.py +0 -70
- package/tooling/scripts/init-project-workflow.sh +0 -746
|
@@ -29,11 +29,15 @@ SCRIPT_DIR = Path(__file__).parent.resolve()
|
|
|
29
29
|
PROJECT_ROOT = SCRIPT_DIR.parent.parent
|
|
30
30
|
MEMORY_DIR = PROJECT_ROOT / ".automation" / "memory"
|
|
31
31
|
|
|
32
|
+
# Pre-compiled regex patterns for performance
|
|
33
|
+
_ENTRY_WITH_TIMESTAMP_RE = re.compile(r"^-\s*(\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}):\s*(.+)$")
|
|
34
|
+
_ENTRY_WITHOUT_TIMESTAMP_RE = re.compile(r"^-\s*(.+)$")
|
|
35
|
+
|
|
32
36
|
|
|
33
37
|
def parse_memory_entry(line: str) -> tuple[Optional[datetime], str]:
|
|
34
38
|
"""Parse a memory entry line into timestamp and content."""
|
|
35
39
|
# Format: - YYYY-MM-DD HH:MM: content
|
|
36
|
-
match =
|
|
40
|
+
match = _ENTRY_WITH_TIMESTAMP_RE.match(line.strip())
|
|
37
41
|
if match:
|
|
38
42
|
try:
|
|
39
43
|
timestamp = datetime.strptime(match.group(1), "%Y-%m-%d %H:%M")
|
|
@@ -42,7 +46,7 @@ def parse_memory_entry(line: str) -> tuple[Optional[datetime], str]:
|
|
|
42
46
|
pass
|
|
43
47
|
|
|
44
48
|
# Format without timestamp: - content
|
|
45
|
-
match =
|
|
49
|
+
match = _ENTRY_WITHOUT_TIMESTAMP_RE.match(line.strip())
|
|
46
50
|
if match:
|
|
47
51
|
return None, match.group(1).strip()
|
|
48
52
|
|
|
@@ -137,6 +141,9 @@ def find_duplicates(
|
|
|
137
141
|
|
|
138
142
|
def summarize_group(entries: list[tuple[Optional[datetime], str]]) -> str:
|
|
139
143
|
"""Create a summary for a group of similar entries."""
|
|
144
|
+
if not entries:
|
|
145
|
+
return ""
|
|
146
|
+
|
|
140
147
|
# Keep the most recent entry's content
|
|
141
148
|
sorted_entries = sorted(entries, key=lambda x: x[0] or datetime.min, reverse=True)
|
|
142
149
|
most_recent = sorted_entries[0][1]
|
|
@@ -19,16 +19,9 @@ import sys
|
|
|
19
19
|
from pathlib import Path
|
|
20
20
|
|
|
21
21
|
SCRIPT_DIR = Path(__file__).parent
|
|
22
|
+
sys.path.insert(0, str(SCRIPT_DIR / "lib"))
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
def get_platform():
|
|
25
|
-
"""Detect the current platform."""
|
|
26
|
-
if sys.platform == "win32":
|
|
27
|
-
return "windows"
|
|
28
|
-
elif sys.platform == "darwin":
|
|
29
|
-
return "macos"
|
|
30
|
-
else:
|
|
31
|
-
return "linux"
|
|
24
|
+
from platform import get_platform
|
|
32
25
|
|
|
33
26
|
|
|
34
27
|
def run_windows(args):
|
|
@@ -18,18 +18,7 @@ import sys
|
|
|
18
18
|
from pathlib import Path
|
|
19
19
|
from typing import Optional
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
# Colors for terminal output
|
|
23
|
-
class Colors:
|
|
24
|
-
HEADER = "\033[95m"
|
|
25
|
-
BLUE = "\033[94m"
|
|
26
|
-
CYAN = "\033[96m"
|
|
27
|
-
GREEN = "\033[92m"
|
|
28
|
-
YELLOW = "\033[93m"
|
|
29
|
-
RED = "\033[91m"
|
|
30
|
-
END = "\033[0m"
|
|
31
|
-
BOLD = "\033[1m"
|
|
32
|
-
|
|
21
|
+
from lib.colors import Colors
|
|
33
22
|
|
|
34
23
|
# Find project paths
|
|
35
24
|
SCRIPT_DIR = Path(__file__).parent.resolve()
|
|
@@ -82,16 +82,16 @@ create_rollback_point() {
|
|
|
82
82
|
local timestamp=$(date '+%Y%m%d_%H%M%S')
|
|
83
83
|
local rollback_name="${timestamp}_${name}"
|
|
84
84
|
local rollback_path="$ROLLBACK_DIR/$rollback_name"
|
|
85
|
-
|
|
85
|
+
|
|
86
86
|
mkdir -p "$rollback_path"
|
|
87
|
-
|
|
87
|
+
|
|
88
88
|
echo -e "${CYAN}Creating rollback point: $rollback_name${NC}"
|
|
89
|
-
|
|
89
|
+
|
|
90
90
|
# Save git state
|
|
91
91
|
local current_branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
|
|
92
92
|
local current_commit=$(git rev-parse HEAD 2>/dev/null || echo "unknown")
|
|
93
93
|
local has_changes=$(git status --porcelain 2>/dev/null | wc -l | tr -d ' ')
|
|
94
|
-
|
|
94
|
+
|
|
95
95
|
# Create manifest
|
|
96
96
|
cat > "$rollback_path/manifest.json" << EOF
|
|
97
97
|
{
|
|
@@ -103,7 +103,7 @@ create_rollback_point() {
|
|
|
103
103
|
"type": "migration-rollback"
|
|
104
104
|
}
|
|
105
105
|
EOF
|
|
106
|
-
|
|
106
|
+
|
|
107
107
|
# Save uncommitted changes if any
|
|
108
108
|
if [[ $has_changes -gt 0 ]]; then
|
|
109
109
|
info "Saving uncommitted changes..."
|
|
@@ -111,33 +111,33 @@ EOF
|
|
|
111
111
|
git stash show -p > "$rollback_path/uncommitted.patch" 2>/dev/null || true
|
|
112
112
|
git stash pop 2>/dev/null || true
|
|
113
113
|
fi
|
|
114
|
-
|
|
114
|
+
|
|
115
115
|
# Save package state
|
|
116
116
|
if [[ -f "$PROJECT_ROOT/package.json" ]]; then
|
|
117
117
|
cp "$PROJECT_ROOT/package.json" "$rollback_path/"
|
|
118
118
|
info "Saved package.json"
|
|
119
119
|
fi
|
|
120
|
-
|
|
120
|
+
|
|
121
121
|
if [[ -f "$PROJECT_ROOT/package-lock.json" ]]; then
|
|
122
122
|
cp "$PROJECT_ROOT/package-lock.json" "$rollback_path/"
|
|
123
123
|
info "Saved package-lock.json"
|
|
124
124
|
fi
|
|
125
|
-
|
|
125
|
+
|
|
126
126
|
if [[ -f "$PROJECT_ROOT/pubspec.yaml" ]]; then
|
|
127
127
|
cp "$PROJECT_ROOT/pubspec.yaml" "$rollback_path/"
|
|
128
128
|
info "Saved pubspec.yaml"
|
|
129
129
|
fi
|
|
130
|
-
|
|
130
|
+
|
|
131
131
|
if [[ -f "$PROJECT_ROOT/pubspec.lock" ]]; then
|
|
132
132
|
cp "$PROJECT_ROOT/pubspec.lock" "$rollback_path/"
|
|
133
133
|
info "Saved pubspec.lock"
|
|
134
134
|
fi
|
|
135
|
-
|
|
135
|
+
|
|
136
136
|
if [[ -f "$PROJECT_ROOT/requirements.txt" ]]; then
|
|
137
137
|
cp "$PROJECT_ROOT/requirements.txt" "$rollback_path/"
|
|
138
138
|
info "Saved requirements.txt"
|
|
139
139
|
fi
|
|
140
|
-
|
|
140
|
+
|
|
141
141
|
success "Rollback point created: $rollback_path"
|
|
142
142
|
echo "$rollback_name"
|
|
143
143
|
}
|
|
@@ -146,25 +146,25 @@ EOF
|
|
|
146
146
|
list_rollback_points() {
|
|
147
147
|
echo -e "${BOLD}Available Rollback Points:${NC}"
|
|
148
148
|
echo ""
|
|
149
|
-
|
|
149
|
+
|
|
150
150
|
if [[ ! -d "$ROLLBACK_DIR" ]] || [[ -z "$(ls -A "$ROLLBACK_DIR" 2>/dev/null)" ]]; then
|
|
151
151
|
info "No rollback points found."
|
|
152
152
|
return 0
|
|
153
153
|
fi
|
|
154
|
-
|
|
154
|
+
|
|
155
155
|
printf "%-25s %-20s %-15s %s\n" "NAME" "CREATED" "COMMIT" "BRANCH"
|
|
156
156
|
printf "%s\n" "$(printf '─%.0s' {1..80})"
|
|
157
|
-
|
|
157
|
+
|
|
158
158
|
for dir in "$ROLLBACK_DIR"/*/; do
|
|
159
159
|
if [[ -d "$dir" ]]; then
|
|
160
160
|
local name=$(basename "$dir")
|
|
161
161
|
local manifest="$dir/manifest.json"
|
|
162
|
-
|
|
162
|
+
|
|
163
163
|
if [[ -f "$manifest" ]]; then
|
|
164
164
|
local created=$(grep '"created"' "$manifest" | sed 's/.*: *"\([^"]*\)".*/\1/' | cut -c1-19)
|
|
165
165
|
local commit=$(grep '"commit"' "$manifest" | sed 's/.*: *"\([^"]*\)".*/\1/' | cut -c1-8)
|
|
166
166
|
local branch=$(grep '"branch"' "$manifest" | sed 's/.*: *"\([^"]*\)".*/\1/')
|
|
167
|
-
|
|
167
|
+
|
|
168
168
|
printf "%-25s %-20s %-15s %s\n" "$name" "$created" "$commit" "$branch"
|
|
169
169
|
fi
|
|
170
170
|
fi
|
|
@@ -175,17 +175,17 @@ list_rollback_points() {
|
|
|
175
175
|
# Delete old rollback points (keep last N)
|
|
176
176
|
cleanup_rollback_points() {
|
|
177
177
|
local keep="${1:-10}"
|
|
178
|
-
|
|
178
|
+
|
|
179
179
|
if [[ ! -d "$ROLLBACK_DIR" ]]; then
|
|
180
180
|
return 0
|
|
181
181
|
fi
|
|
182
|
-
|
|
182
|
+
|
|
183
183
|
local count=$(ls -d "$ROLLBACK_DIR"/*/ 2>/dev/null | wc -l | tr -d ' ')
|
|
184
|
-
|
|
184
|
+
|
|
185
185
|
if [[ $count -gt $keep ]]; then
|
|
186
186
|
local to_delete=$((count - keep))
|
|
187
187
|
info "Cleaning up $to_delete old rollback point(s)..."
|
|
188
|
-
|
|
188
|
+
|
|
189
189
|
ls -d "$ROLLBACK_DIR"/*/ 2>/dev/null | head -n "$to_delete" | while read dir; do
|
|
190
190
|
rm -rf "$dir"
|
|
191
191
|
success "Deleted: $(basename "$dir")"
|
|
@@ -200,35 +200,35 @@ cleanup_rollback_points() {
|
|
|
200
200
|
# Find migration spec file
|
|
201
201
|
find_migration_spec() {
|
|
202
202
|
local migration_id="$1"
|
|
203
|
-
|
|
203
|
+
|
|
204
204
|
# Search in common locations
|
|
205
205
|
local search_paths=(
|
|
206
206
|
"$MIGRATIONS_DIR/${migration_id}.md"
|
|
207
207
|
"$PROJECT_ROOT/docs/${migration_id}.md"
|
|
208
208
|
"$PROJECT_ROOT/tooling/docs/migrations/${migration_id}.md"
|
|
209
209
|
)
|
|
210
|
-
|
|
210
|
+
|
|
211
211
|
for path in "${search_paths[@]}"; do
|
|
212
212
|
if [[ -f "$path" ]]; then
|
|
213
213
|
echo "$path"
|
|
214
214
|
return 0
|
|
215
215
|
fi
|
|
216
216
|
done
|
|
217
|
-
|
|
217
|
+
|
|
218
218
|
# Search by pattern
|
|
219
219
|
local found=$(find "$PROJECT_ROOT" -name "*${migration_id}*.md" -path "*/migrations/*" 2>/dev/null | head -1)
|
|
220
220
|
if [[ -n "$found" ]]; then
|
|
221
221
|
echo "$found"
|
|
222
222
|
return 0
|
|
223
223
|
fi
|
|
224
|
-
|
|
224
|
+
|
|
225
225
|
return 1
|
|
226
226
|
}
|
|
227
227
|
|
|
228
228
|
# Parse rollback steps from migration spec
|
|
229
229
|
parse_rollback_steps() {
|
|
230
230
|
local spec_file="$1"
|
|
231
|
-
|
|
231
|
+
|
|
232
232
|
# Extract rollback steps section
|
|
233
233
|
awk '/^### Rollback Steps/,/^##[^#]/' "$spec_file" 2>/dev/null | \
|
|
234
234
|
grep -E '^\s*[0-9]+\.' | \
|
|
@@ -239,21 +239,21 @@ parse_rollback_steps() {
|
|
|
239
239
|
rollback_to_commit() {
|
|
240
240
|
local commit="$1"
|
|
241
241
|
local dry_run="$2"
|
|
242
|
-
|
|
242
|
+
|
|
243
243
|
if [[ "$dry_run" == "true" ]]; then
|
|
244
244
|
info "Would reset to commit: $commit"
|
|
245
245
|
git log --oneline -1 "$commit"
|
|
246
246
|
return 0
|
|
247
247
|
fi
|
|
248
|
-
|
|
248
|
+
|
|
249
249
|
info "Rolling back to commit: $commit"
|
|
250
|
-
|
|
250
|
+
|
|
251
251
|
# Check for uncommitted changes
|
|
252
252
|
if [[ -n "$(git status --porcelain)" ]]; then
|
|
253
253
|
warning "You have uncommitted changes. These will be stashed."
|
|
254
254
|
git stash push -m "pre-rollback-$(date +%s)"
|
|
255
255
|
fi
|
|
256
|
-
|
|
256
|
+
|
|
257
257
|
# Perform rollback
|
|
258
258
|
git checkout "$commit" -- .
|
|
259
259
|
success "Rolled back to commit: $commit"
|
|
@@ -264,73 +264,73 @@ rollback_from_point() {
|
|
|
264
264
|
local point_name="$1"
|
|
265
265
|
local dry_run="$2"
|
|
266
266
|
local point_path="$ROLLBACK_DIR/$point_name"
|
|
267
|
-
|
|
267
|
+
|
|
268
268
|
if [[ ! -d "$point_path" ]]; then
|
|
269
269
|
error "Rollback point not found: $point_name"
|
|
270
270
|
fi
|
|
271
|
-
|
|
271
|
+
|
|
272
272
|
local manifest="$point_path/manifest.json"
|
|
273
273
|
if [[ ! -f "$manifest" ]]; then
|
|
274
274
|
error "Invalid rollback point (no manifest): $point_name"
|
|
275
275
|
fi
|
|
276
|
-
|
|
276
|
+
|
|
277
277
|
local commit=$(grep '"commit"' "$manifest" | sed 's/.*: *"\([^"]*\)".*/\1/')
|
|
278
|
-
|
|
278
|
+
|
|
279
279
|
echo ""
|
|
280
280
|
info "Rollback Point Details:"
|
|
281
281
|
cat "$manifest" | grep -E '"(name|created|branch|commit)"' | sed 's/^/ /'
|
|
282
282
|
echo ""
|
|
283
|
-
|
|
283
|
+
|
|
284
284
|
if [[ "$dry_run" == "true" ]]; then
|
|
285
285
|
info "[DRY RUN] Would restore from rollback point: $point_name"
|
|
286
|
-
|
|
286
|
+
|
|
287
287
|
if [[ -f "$point_path/package.json" ]]; then
|
|
288
288
|
info "[DRY RUN] Would restore package.json"
|
|
289
289
|
fi
|
|
290
290
|
if [[ -f "$point_path/pubspec.yaml" ]]; then
|
|
291
291
|
info "[DRY RUN] Would restore pubspec.yaml"
|
|
292
292
|
fi
|
|
293
|
-
|
|
293
|
+
|
|
294
294
|
return 0
|
|
295
295
|
fi
|
|
296
|
-
|
|
296
|
+
|
|
297
297
|
if ! confirm "This will rollback to the saved state. Continue?"; then
|
|
298
298
|
info "Rollback cancelled."
|
|
299
299
|
return 0
|
|
300
300
|
fi
|
|
301
|
-
|
|
301
|
+
|
|
302
302
|
# Restore files
|
|
303
303
|
if [[ -f "$point_path/package.json" ]]; then
|
|
304
304
|
cp "$point_path/package.json" "$PROJECT_ROOT/"
|
|
305
305
|
success "Restored package.json"
|
|
306
306
|
fi
|
|
307
|
-
|
|
307
|
+
|
|
308
308
|
if [[ -f "$point_path/package-lock.json" ]]; then
|
|
309
309
|
cp "$point_path/package-lock.json" "$PROJECT_ROOT/"
|
|
310
310
|
success "Restored package-lock.json"
|
|
311
311
|
fi
|
|
312
|
-
|
|
312
|
+
|
|
313
313
|
if [[ -f "$point_path/pubspec.yaml" ]]; then
|
|
314
314
|
cp "$point_path/pubspec.yaml" "$PROJECT_ROOT/"
|
|
315
315
|
success "Restored pubspec.yaml"
|
|
316
316
|
fi
|
|
317
|
-
|
|
317
|
+
|
|
318
318
|
if [[ -f "$point_path/pubspec.lock" ]]; then
|
|
319
319
|
cp "$point_path/pubspec.lock" "$PROJECT_ROOT/"
|
|
320
320
|
success "Restored pubspec.lock"
|
|
321
321
|
fi
|
|
322
|
-
|
|
322
|
+
|
|
323
323
|
if [[ -f "$point_path/requirements.txt" ]]; then
|
|
324
324
|
cp "$point_path/requirements.txt" "$PROJECT_ROOT/"
|
|
325
325
|
success "Restored requirements.txt"
|
|
326
326
|
fi
|
|
327
|
-
|
|
327
|
+
|
|
328
328
|
# Rollback git if commit is available
|
|
329
329
|
if [[ -n "$commit" && "$commit" != "unknown" ]]; then
|
|
330
330
|
info "Rolling back git state..."
|
|
331
331
|
rollback_to_commit "$commit" "false"
|
|
332
332
|
fi
|
|
333
|
-
|
|
333
|
+
|
|
334
334
|
# Reinstall dependencies
|
|
335
335
|
echo ""
|
|
336
336
|
info "Dependencies may need to be reinstalled:"
|
|
@@ -343,7 +343,7 @@ rollback_from_point() {
|
|
|
343
343
|
if [[ -f "$PROJECT_ROOT/requirements.txt" ]]; then
|
|
344
344
|
echo " pip install -r requirements.txt"
|
|
345
345
|
fi
|
|
346
|
-
|
|
346
|
+
|
|
347
347
|
echo ""
|
|
348
348
|
success "Rollback complete!"
|
|
349
349
|
}
|
|
@@ -353,43 +353,43 @@ rollback_migration() {
|
|
|
353
353
|
local migration_id="$1"
|
|
354
354
|
local dry_run="$2"
|
|
355
355
|
local force="$3"
|
|
356
|
-
|
|
356
|
+
|
|
357
357
|
echo -e "${BOLD}Rolling back migration: $migration_id${NC}"
|
|
358
358
|
echo ""
|
|
359
|
-
|
|
359
|
+
|
|
360
360
|
# Look for a rollback point for this migration
|
|
361
361
|
local rollback_point=$(ls -d "$ROLLBACK_DIR"/*"$migration_id"* 2>/dev/null | tail -1)
|
|
362
|
-
|
|
362
|
+
|
|
363
363
|
if [[ -n "$rollback_point" && -d "$rollback_point" ]]; then
|
|
364
364
|
info "Found rollback point: $(basename "$rollback_point")"
|
|
365
365
|
rollback_from_point "$(basename "$rollback_point")" "$dry_run"
|
|
366
366
|
return 0
|
|
367
367
|
fi
|
|
368
|
-
|
|
368
|
+
|
|
369
369
|
# Look for migration spec with rollback instructions
|
|
370
370
|
local spec_file=$(find_migration_spec "$migration_id")
|
|
371
|
-
|
|
371
|
+
|
|
372
372
|
if [[ -n "$spec_file" ]]; then
|
|
373
373
|
info "Found migration spec: $spec_file"
|
|
374
|
-
|
|
374
|
+
|
|
375
375
|
local steps=$(parse_rollback_steps "$spec_file")
|
|
376
|
-
|
|
376
|
+
|
|
377
377
|
if [[ -n "$steps" ]]; then
|
|
378
378
|
echo ""
|
|
379
379
|
echo -e "${BOLD}Rollback Steps:${NC}"
|
|
380
380
|
echo "$steps" | nl
|
|
381
381
|
echo ""
|
|
382
|
-
|
|
382
|
+
|
|
383
383
|
if [[ "$dry_run" == "true" ]]; then
|
|
384
384
|
info "[DRY RUN] Would execute the above rollback steps"
|
|
385
385
|
return 0
|
|
386
386
|
fi
|
|
387
|
-
|
|
387
|
+
|
|
388
388
|
if ! confirm "Execute these rollback steps?"; then
|
|
389
389
|
info "Rollback cancelled."
|
|
390
390
|
return 0
|
|
391
391
|
fi
|
|
392
|
-
|
|
392
|
+
|
|
393
393
|
# Execute steps (basic implementation - just displays them)
|
|
394
394
|
info "Please execute the following steps manually:"
|
|
395
395
|
echo "$steps" | nl
|
|
@@ -399,7 +399,7 @@ rollback_migration() {
|
|
|
399
399
|
else
|
|
400
400
|
warning "No migration spec found for: $migration_id"
|
|
401
401
|
fi
|
|
402
|
-
|
|
402
|
+
|
|
403
403
|
# Offer git-based rollback
|
|
404
404
|
echo ""
|
|
405
405
|
info "You can also rollback using git:"
|
|
@@ -448,7 +448,7 @@ main() {
|
|
|
448
448
|
local create_name=""
|
|
449
449
|
local restore_point=""
|
|
450
450
|
local cleanup_keep=""
|
|
451
|
-
|
|
451
|
+
|
|
452
452
|
# Parse arguments
|
|
453
453
|
while [[ $# -gt 0 ]]; do
|
|
454
454
|
case "$1" in
|
|
@@ -498,12 +498,12 @@ main() {
|
|
|
498
498
|
esac
|
|
499
499
|
shift
|
|
500
500
|
done
|
|
501
|
-
|
|
501
|
+
|
|
502
502
|
print_header
|
|
503
|
-
|
|
503
|
+
|
|
504
504
|
# Ensure rollback directory exists
|
|
505
505
|
mkdir -p "$ROLLBACK_DIR"
|
|
506
|
-
|
|
506
|
+
|
|
507
507
|
case "$command" in
|
|
508
508
|
list)
|
|
509
509
|
list_rollback_points
|
|
@@ -68,20 +68,20 @@
|
|
|
68
68
|
param(
|
|
69
69
|
[Parameter(Position=0)]
|
|
70
70
|
[string]$StoryKey,
|
|
71
|
-
|
|
71
|
+
|
|
72
72
|
[switch]$Swarm,
|
|
73
73
|
[switch]$Pair,
|
|
74
74
|
[switch]$Auto,
|
|
75
75
|
[switch]$Sequential,
|
|
76
|
-
|
|
76
|
+
|
|
77
77
|
[string]$Agents,
|
|
78
78
|
[int]$MaxIterations = 3,
|
|
79
|
-
|
|
79
|
+
|
|
80
80
|
[ValidateSet("opus", "sonnet", "haiku")]
|
|
81
81
|
[string]$Model = "opus",
|
|
82
|
-
|
|
82
|
+
|
|
83
83
|
[double]$Budget = 20.0,
|
|
84
|
-
|
|
84
|
+
|
|
85
85
|
[switch]$Memory,
|
|
86
86
|
[string]$Query,
|
|
87
87
|
[switch]$RouteOnly,
|
|
@@ -140,11 +140,11 @@ function Show-Usage {
|
|
|
140
140
|
# Build Python command arguments
|
|
141
141
|
function Build-PythonArgs {
|
|
142
142
|
$args = @()
|
|
143
|
-
|
|
143
|
+
|
|
144
144
|
if ($StoryKey) {
|
|
145
145
|
$args += $StoryKey
|
|
146
146
|
}
|
|
147
|
-
|
|
147
|
+
|
|
148
148
|
if ($Swarm) {
|
|
149
149
|
$args += "--swarm"
|
|
150
150
|
} elseif ($Pair) {
|
|
@@ -154,44 +154,44 @@ function Build-PythonArgs {
|
|
|
154
154
|
} else {
|
|
155
155
|
$args += "--auto"
|
|
156
156
|
}
|
|
157
|
-
|
|
157
|
+
|
|
158
158
|
if ($Agents) {
|
|
159
159
|
$args += "--agents"
|
|
160
160
|
$args += $Agents
|
|
161
161
|
}
|
|
162
|
-
|
|
162
|
+
|
|
163
163
|
if ($MaxIterations -ne 3) {
|
|
164
164
|
$args += "--max-iterations"
|
|
165
165
|
$args += $MaxIterations.ToString()
|
|
166
166
|
}
|
|
167
|
-
|
|
167
|
+
|
|
168
168
|
if ($Model -ne "opus") {
|
|
169
169
|
$args += "--model"
|
|
170
170
|
$args += $Model
|
|
171
171
|
}
|
|
172
|
-
|
|
172
|
+
|
|
173
173
|
if ($Budget -ne 20.0) {
|
|
174
174
|
$args += "--budget"
|
|
175
175
|
$args += $Budget.ToString()
|
|
176
176
|
}
|
|
177
|
-
|
|
177
|
+
|
|
178
178
|
if ($Memory) {
|
|
179
179
|
$args += "--memory"
|
|
180
180
|
}
|
|
181
|
-
|
|
181
|
+
|
|
182
182
|
if ($Query) {
|
|
183
183
|
$args += "--query"
|
|
184
184
|
$args += $Query
|
|
185
185
|
}
|
|
186
|
-
|
|
186
|
+
|
|
187
187
|
if ($RouteOnly) {
|
|
188
188
|
$args += "--route-only"
|
|
189
189
|
}
|
|
190
|
-
|
|
190
|
+
|
|
191
191
|
if ($Quiet) {
|
|
192
192
|
$args += "--quiet"
|
|
193
193
|
}
|
|
194
|
-
|
|
194
|
+
|
|
195
195
|
return $args
|
|
196
196
|
}
|
|
197
197
|
|