wogiflow 1.0.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/.workflow/agents/reviewer.md +81 -0
- package/.workflow/agents/security.md +94 -0
- package/.workflow/agents/story-writer.md +58 -0
- package/.workflow/bridges/base-bridge.js +395 -0
- package/.workflow/bridges/claude-bridge.js +434 -0
- package/.workflow/bridges/index.js +130 -0
- package/.workflow/lib/assumption-detector.js +481 -0
- package/.workflow/lib/config-substitution.js +371 -0
- package/.workflow/lib/failure-categories.js +478 -0
- package/.workflow/state/app-map.md.template +15 -0
- package/.workflow/state/architecture.md.template +24 -0
- package/.workflow/state/component-index.json.template +5 -0
- package/.workflow/state/decisions.md.template +15 -0
- package/.workflow/state/feedback-patterns.md.template +9 -0
- package/.workflow/state/knowledge-sync.json.template +6 -0
- package/.workflow/state/progress.md.template +14 -0
- package/.workflow/state/ready.json.template +7 -0
- package/.workflow/state/request-log.md.template +14 -0
- package/.workflow/state/session-state.json.template +11 -0
- package/.workflow/state/stack.md.template +33 -0
- package/.workflow/state/testing.md.template +36 -0
- package/.workflow/templates/claude-md.hbs +257 -0
- package/.workflow/templates/correction-report.md +67 -0
- package/.workflow/templates/gemini-md.hbs +52 -0
- package/README.md +1802 -0
- package/bin/flow +205 -0
- package/lib/index.js +33 -0
- package/lib/installer.js +467 -0
- package/lib/release-channel.js +269 -0
- package/lib/skill-registry.js +526 -0
- package/lib/upgrader.js +401 -0
- package/lib/utils.js +305 -0
- package/package.json +64 -0
- package/scripts/flow +985 -0
- package/scripts/flow-adaptive-learning.js +1259 -0
- package/scripts/flow-aggregate.js +488 -0
- package/scripts/flow-archive +133 -0
- package/scripts/flow-auto-context.js +1015 -0
- package/scripts/flow-auto-learn.js +615 -0
- package/scripts/flow-bridge.js +223 -0
- package/scripts/flow-browser-suggest.js +316 -0
- package/scripts/flow-bug.js +247 -0
- package/scripts/flow-cascade.js +711 -0
- package/scripts/flow-changelog +85 -0
- package/scripts/flow-checkpoint.js +483 -0
- package/scripts/flow-cli.js +403 -0
- package/scripts/flow-code-intelligence.js +760 -0
- package/scripts/flow-complexity.js +502 -0
- package/scripts/flow-config-set.js +152 -0
- package/scripts/flow-constants.js +157 -0
- package/scripts/flow-context +152 -0
- package/scripts/flow-context-init.js +482 -0
- package/scripts/flow-context-monitor.js +384 -0
- package/scripts/flow-context-scoring.js +886 -0
- package/scripts/flow-correct.js +458 -0
- package/scripts/flow-damage-control.js +985 -0
- package/scripts/flow-deps +101 -0
- package/scripts/flow-diff.js +700 -0
- package/scripts/flow-done +151 -0
- package/scripts/flow-done.js +489 -0
- package/scripts/flow-durable-session.js +1541 -0
- package/scripts/flow-entropy-monitor.js +345 -0
- package/scripts/flow-export-profile +349 -0
- package/scripts/flow-export-scanner.js +1046 -0
- package/scripts/flow-figma-confirm.js +400 -0
- package/scripts/flow-figma-extract.js +496 -0
- package/scripts/flow-figma-generate.js +683 -0
- package/scripts/flow-figma-index.js +909 -0
- package/scripts/flow-figma-match.js +617 -0
- package/scripts/flow-figma-mcp-server.js +518 -0
- package/scripts/flow-figma-pipeline.js +414 -0
- package/scripts/flow-file-ops.js +301 -0
- package/scripts/flow-gate-confidence.js +825 -0
- package/scripts/flow-guided-edit.js +659 -0
- package/scripts/flow-health +185 -0
- package/scripts/flow-health.js +413 -0
- package/scripts/flow-hooks.js +556 -0
- package/scripts/flow-http-client.js +249 -0
- package/scripts/flow-hybrid-detect.js +167 -0
- package/scripts/flow-hybrid-interactive.js +591 -0
- package/scripts/flow-hybrid-test.js +152 -0
- package/scripts/flow-import-profile +439 -0
- package/scripts/flow-init +253 -0
- package/scripts/flow-instruction-richness.js +827 -0
- package/scripts/flow-jira-integration.js +579 -0
- package/scripts/flow-knowledge-router.js +522 -0
- package/scripts/flow-knowledge-sync.js +589 -0
- package/scripts/flow-linear-integration.js +631 -0
- package/scripts/flow-links.js +774 -0
- package/scripts/flow-log-manager.js +559 -0
- package/scripts/flow-loop-enforcer.js +1246 -0
- package/scripts/flow-loop-retry-learning.js +630 -0
- package/scripts/flow-lsp.js +923 -0
- package/scripts/flow-map-index +348 -0
- package/scripts/flow-map-sync +201 -0
- package/scripts/flow-memory-blocks.js +668 -0
- package/scripts/flow-memory-compactor.js +350 -0
- package/scripts/flow-memory-db.js +1110 -0
- package/scripts/flow-memory-sync.js +484 -0
- package/scripts/flow-metrics.js +353 -0
- package/scripts/flow-migrate-ids.js +370 -0
- package/scripts/flow-model-adapter.js +802 -0
- package/scripts/flow-model-router.js +884 -0
- package/scripts/flow-models.js +1231 -0
- package/scripts/flow-morning.js +517 -0
- package/scripts/flow-multi-approach.js +660 -0
- package/scripts/flow-new-feature +86 -0
- package/scripts/flow-onboard +1042 -0
- package/scripts/flow-orchestrate-llm.js +459 -0
- package/scripts/flow-orchestrate.js +3592 -0
- package/scripts/flow-output.js +123 -0
- package/scripts/flow-parallel-detector.js +399 -0
- package/scripts/flow-parallel-dispatch.js +987 -0
- package/scripts/flow-parallel.js +428 -0
- package/scripts/flow-pattern-enforcer.js +600 -0
- package/scripts/flow-prd-manager.js +282 -0
- package/scripts/flow-progress.js +323 -0
- package/scripts/flow-project-analyzer.js +975 -0
- package/scripts/flow-prompt-composer.js +487 -0
- package/scripts/flow-providers.js +1381 -0
- package/scripts/flow-queue.js +308 -0
- package/scripts/flow-ready +82 -0
- package/scripts/flow-ready.js +189 -0
- package/scripts/flow-regression.js +396 -0
- package/scripts/flow-response-parser.js +450 -0
- package/scripts/flow-resume.js +284 -0
- package/scripts/flow-rules-sync.js +439 -0
- package/scripts/flow-run-trace.js +718 -0
- package/scripts/flow-safety.js +587 -0
- package/scripts/flow-search +104 -0
- package/scripts/flow-security.js +481 -0
- package/scripts/flow-session-end +106 -0
- package/scripts/flow-session-end.js +437 -0
- package/scripts/flow-session-state.js +671 -0
- package/scripts/flow-setup-hooks +216 -0
- package/scripts/flow-setup-hooks.js +377 -0
- package/scripts/flow-skill-create.js +329 -0
- package/scripts/flow-skill-creator.js +572 -0
- package/scripts/flow-skill-generator.js +1046 -0
- package/scripts/flow-skill-learn.js +880 -0
- package/scripts/flow-skill-matcher.js +578 -0
- package/scripts/flow-spec-generator.js +820 -0
- package/scripts/flow-stack-wizard.js +895 -0
- package/scripts/flow-standup +162 -0
- package/scripts/flow-start +74 -0
- package/scripts/flow-start.js +235 -0
- package/scripts/flow-status +110 -0
- package/scripts/flow-status.js +301 -0
- package/scripts/flow-step-browser.js +83 -0
- package/scripts/flow-step-changelog.js +217 -0
- package/scripts/flow-step-comments.js +306 -0
- package/scripts/flow-step-complexity.js +234 -0
- package/scripts/flow-step-coverage.js +218 -0
- package/scripts/flow-step-knowledge.js +193 -0
- package/scripts/flow-step-pr-tests.js +364 -0
- package/scripts/flow-step-regression.js +89 -0
- package/scripts/flow-step-review.js +516 -0
- package/scripts/flow-step-security.js +162 -0
- package/scripts/flow-step-silent-failures.js +290 -0
- package/scripts/flow-step-simplifier.js +346 -0
- package/scripts/flow-story +105 -0
- package/scripts/flow-story.js +500 -0
- package/scripts/flow-suspend.js +252 -0
- package/scripts/flow-sync-daemon.js +654 -0
- package/scripts/flow-task-analyzer.js +606 -0
- package/scripts/flow-team-dashboard.js +748 -0
- package/scripts/flow-team-sync.js +752 -0
- package/scripts/flow-team.js +977 -0
- package/scripts/flow-tech-options.js +528 -0
- package/scripts/flow-templates.js +812 -0
- package/scripts/flow-tiered-learning.js +728 -0
- package/scripts/flow-trace +204 -0
- package/scripts/flow-transcript-chunking.js +1106 -0
- package/scripts/flow-transcript-digest.js +7918 -0
- package/scripts/flow-transcript-language.js +465 -0
- package/scripts/flow-transcript-parsing.js +1085 -0
- package/scripts/flow-transcript-stories.js +2194 -0
- package/scripts/flow-update-map +224 -0
- package/scripts/flow-utils.js +2242 -0
- package/scripts/flow-verification.js +644 -0
- package/scripts/flow-verify.js +1177 -0
- package/scripts/flow-voice-input.js +638 -0
- package/scripts/flow-watch +168 -0
- package/scripts/flow-workflow-steps.js +521 -0
- package/scripts/flow-workflow.js +1029 -0
- package/scripts/flow-worktree.js +489 -0
- package/scripts/hooks/adapters/base-adapter.js +102 -0
- package/scripts/hooks/adapters/claude-code.js +359 -0
- package/scripts/hooks/adapters/index.js +79 -0
- package/scripts/hooks/core/component-check.js +341 -0
- package/scripts/hooks/core/index.js +35 -0
- package/scripts/hooks/core/loop-check.js +241 -0
- package/scripts/hooks/core/session-context.js +294 -0
- package/scripts/hooks/core/task-gate.js +177 -0
- package/scripts/hooks/core/validation.js +230 -0
- package/scripts/hooks/entry/claude-code/post-tool-use.js +65 -0
- package/scripts/hooks/entry/claude-code/pre-tool-use.js +89 -0
- package/scripts/hooks/entry/claude-code/session-end.js +87 -0
- package/scripts/hooks/entry/claude-code/session-start.js +46 -0
- package/scripts/hooks/entry/claude-code/stop.js +43 -0
- package/scripts/postinstall.js +139 -0
- package/templates/browser-test-flow.json +56 -0
- package/templates/bug-report.md +43 -0
- package/templates/component-detail.md +42 -0
- package/templates/component.stories.tsx +49 -0
- package/templates/context/constraints.md +83 -0
- package/templates/context/conventions.md +177 -0
- package/templates/context/stack.md +60 -0
- package/templates/correction-report.md +90 -0
- package/templates/feature-proposal.md +35 -0
- package/templates/hybrid/_base.md +254 -0
- package/templates/hybrid/_patterns.md +45 -0
- package/templates/hybrid/create-component.md +127 -0
- package/templates/hybrid/create-file.md +56 -0
- package/templates/hybrid/create-hook.md +145 -0
- package/templates/hybrid/create-service.md +70 -0
- package/templates/hybrid/fix-bug.md +33 -0
- package/templates/hybrid/modify-file.md +55 -0
- package/templates/story.md +68 -0
- package/templates/task.json +56 -0
- package/templates/trace.md +69 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Wogi Flow - Standup Summary Generator
|
|
4
|
+
# Generates daily standup from request-log and task status
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
WORKFLOW_DIR=".workflow"
|
|
9
|
+
REQUEST_LOG="$WORKFLOW_DIR/state/request-log.md"
|
|
10
|
+
READY_JSON="$WORKFLOW_DIR/state/ready.json"
|
|
11
|
+
PROGRESS_MD="$WORKFLOW_DIR/state/progress.md"
|
|
12
|
+
|
|
13
|
+
# Colors
|
|
14
|
+
CYAN='\033[0;36m'
|
|
15
|
+
GREEN='\033[0;32m'
|
|
16
|
+
YELLOW='\033[1;33m'
|
|
17
|
+
NC='\033[0m'
|
|
18
|
+
|
|
19
|
+
# Get date range (default: last 24 hours)
|
|
20
|
+
DAYS=${1:-1}
|
|
21
|
+
SINCE=$(date -d "$DAYS days ago" +%Y-%m-%d 2>/dev/null || date -v-${DAYS}d +%Y-%m-%d)
|
|
22
|
+
|
|
23
|
+
echo -e "${CYAN}═══════════════════════════════════════${NC}"
|
|
24
|
+
echo -e "${CYAN} STANDUP SUMMARY${NC}"
|
|
25
|
+
echo -e "${CYAN}═══════════════════════════════════════${NC}"
|
|
26
|
+
echo ""
|
|
27
|
+
echo "Period: Last $DAYS day(s) (since $SINCE)"
|
|
28
|
+
echo ""
|
|
29
|
+
|
|
30
|
+
# What was done (from request-log)
|
|
31
|
+
echo -e "${GREEN}✅ COMPLETED${NC}"
|
|
32
|
+
echo "─────────────────────────────────────"
|
|
33
|
+
|
|
34
|
+
if [ -f "$REQUEST_LOG" ]; then
|
|
35
|
+
# Extract entries from the time period
|
|
36
|
+
recent_entries=$(grep -A5 "^### R-" "$REQUEST_LOG" | grep -A5 "$SINCE" 2>/dev/null || true)
|
|
37
|
+
|
|
38
|
+
if [ -n "$recent_entries" ]; then
|
|
39
|
+
# Parse and display
|
|
40
|
+
grep "^### R-" "$REQUEST_LOG" | while read -r line; do
|
|
41
|
+
date_in_entry=$(echo "$line" | grep -oE "[0-9]{4}-[0-9]{2}-[0-9]{2}" || true)
|
|
42
|
+
if [[ "$date_in_entry" > "$SINCE" ]] || [[ "$date_in_entry" == "$SINCE" ]]; then
|
|
43
|
+
entry_id=$(echo "$line" | grep -oE "R-[0-9]+")
|
|
44
|
+
echo " • $entry_id"
|
|
45
|
+
fi
|
|
46
|
+
done
|
|
47
|
+
|
|
48
|
+
# Count by type
|
|
49
|
+
echo ""
|
|
50
|
+
new_count=$(grep -c "Type.*: new" "$REQUEST_LOG" 2>/dev/null || echo 0)
|
|
51
|
+
fix_count=$(grep -c "Type.*: fix" "$REQUEST_LOG" 2>/dev/null || echo 0)
|
|
52
|
+
change_count=$(grep -c "Type.*: change" "$REQUEST_LOG" 2>/dev/null || echo 0)
|
|
53
|
+
|
|
54
|
+
echo " Summary: $new_count new, $fix_count fixes, $change_count changes"
|
|
55
|
+
else
|
|
56
|
+
echo " No logged work in this period"
|
|
57
|
+
fi
|
|
58
|
+
else
|
|
59
|
+
echo " No request-log found"
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
echo ""
|
|
63
|
+
|
|
64
|
+
# What's in progress (from ready.json)
|
|
65
|
+
echo -e "${YELLOW}🔄 IN PROGRESS${NC}"
|
|
66
|
+
echo "─────────────────────────────────────"
|
|
67
|
+
|
|
68
|
+
if [ -f "$READY_JSON" ]; then
|
|
69
|
+
in_progress=$(python3 -c "
|
|
70
|
+
import json
|
|
71
|
+
with open('$READY_JSON') as f:
|
|
72
|
+
data = json.load(f)
|
|
73
|
+
for task in data.get('inProgress', []):
|
|
74
|
+
if isinstance(task, dict):
|
|
75
|
+
print(f\" • {task.get('id', 'unknown')}: {task.get('title', 'No title')}\")
|
|
76
|
+
else:
|
|
77
|
+
print(f\" • {task}\")
|
|
78
|
+
" 2>/dev/null || echo " Unable to parse ready.json")
|
|
79
|
+
|
|
80
|
+
if [ -n "$in_progress" ]; then
|
|
81
|
+
echo "$in_progress"
|
|
82
|
+
else
|
|
83
|
+
echo " Nothing currently in progress"
|
|
84
|
+
fi
|
|
85
|
+
else
|
|
86
|
+
echo " No ready.json found"
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
echo ""
|
|
90
|
+
|
|
91
|
+
# What's next (from ready.json)
|
|
92
|
+
echo -e "${CYAN}📋 UP NEXT${NC}"
|
|
93
|
+
echo "─────────────────────────────────────"
|
|
94
|
+
|
|
95
|
+
if [ -f "$READY_JSON" ]; then
|
|
96
|
+
ready=$(python3 -c "
|
|
97
|
+
import json
|
|
98
|
+
with open('$READY_JSON') as f:
|
|
99
|
+
data = json.load(f)
|
|
100
|
+
ready_tasks = data.get('ready', [])[:3] # Top 3
|
|
101
|
+
for task in ready_tasks:
|
|
102
|
+
if isinstance(task, dict):
|
|
103
|
+
print(f\" • {task.get('id', 'unknown')}: {task.get('title', 'No title')}\")
|
|
104
|
+
else:
|
|
105
|
+
print(f\" • {task}\")
|
|
106
|
+
" 2>/dev/null || echo " Unable to parse ready.json")
|
|
107
|
+
|
|
108
|
+
if [ -n "$ready" ]; then
|
|
109
|
+
echo "$ready"
|
|
110
|
+
else
|
|
111
|
+
echo " No tasks ready"
|
|
112
|
+
fi
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
echo ""
|
|
116
|
+
|
|
117
|
+
# Blockers (from ready.json and progress.md)
|
|
118
|
+
echo -e "${YELLOW}🚧 BLOCKERS${NC}"
|
|
119
|
+
echo "─────────────────────────────────────"
|
|
120
|
+
|
|
121
|
+
has_blockers=false
|
|
122
|
+
|
|
123
|
+
if [ -f "$READY_JSON" ]; then
|
|
124
|
+
blocked=$(python3 -c "
|
|
125
|
+
import json
|
|
126
|
+
with open('$READY_JSON') as f:
|
|
127
|
+
data = json.load(f)
|
|
128
|
+
for task in data.get('blocked', []):
|
|
129
|
+
if isinstance(task, dict):
|
|
130
|
+
print(f\" • {task.get('id', 'unknown')}: {task.get('reason', 'No reason')}\")
|
|
131
|
+
else:
|
|
132
|
+
print(f\" • {task}\")
|
|
133
|
+
" 2>/dev/null || true)
|
|
134
|
+
|
|
135
|
+
if [ -n "$blocked" ]; then
|
|
136
|
+
echo "$blocked"
|
|
137
|
+
has_blockers=true
|
|
138
|
+
fi
|
|
139
|
+
fi
|
|
140
|
+
|
|
141
|
+
if [ "$has_blockers" = false ]; then
|
|
142
|
+
echo " None 🎉"
|
|
143
|
+
fi
|
|
144
|
+
|
|
145
|
+
echo ""
|
|
146
|
+
|
|
147
|
+
# Recent decisions (from feedback-patterns.md)
|
|
148
|
+
if [ -f "$WORKFLOW_DIR/state/feedback-patterns.md" ]; then
|
|
149
|
+
recent_patterns=$(grep "$SINCE" "$WORKFLOW_DIR/state/feedback-patterns.md" 2>/dev/null || true)
|
|
150
|
+
if [ -n "$recent_patterns" ]; then
|
|
151
|
+
echo -e "${CYAN}📝 RECENT DECISIONS${NC}"
|
|
152
|
+
echo "─────────────────────────────────────"
|
|
153
|
+
echo "$recent_patterns"
|
|
154
|
+
echo ""
|
|
155
|
+
fi
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
echo -e "${CYAN}═══════════════════════════════════════${NC}"
|
|
159
|
+
echo ""
|
|
160
|
+
echo "For full details:"
|
|
161
|
+
echo " • Request log: $REQUEST_LOG"
|
|
162
|
+
echo " • Progress: $PROGRESS_MD"
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Wogi Flow - Start Task
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
WORKFLOW_DIR=".workflow"
|
|
8
|
+
READY_JSON="$WORKFLOW_DIR/state/ready.json"
|
|
9
|
+
|
|
10
|
+
# Colors
|
|
11
|
+
GREEN='\033[0;32m'
|
|
12
|
+
RED='\033[0;31m'
|
|
13
|
+
NC='\033[0m'
|
|
14
|
+
|
|
15
|
+
if [ -z "$1" ]; then
|
|
16
|
+
echo "Usage: flow start <task-id>"
|
|
17
|
+
exit 1
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
TASK_ID="$1"
|
|
21
|
+
|
|
22
|
+
if [ ! -f "$READY_JSON" ]; then
|
|
23
|
+
echo -e "${RED}Error: No ready.json found${NC}"
|
|
24
|
+
exit 1
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
READY_FILE="$READY_JSON" TASK_ID_ARG="$TASK_ID" python3 << 'EOF'
|
|
28
|
+
import json, os
|
|
29
|
+
|
|
30
|
+
task_id = os.environ['TASK_ID_ARG']
|
|
31
|
+
ready_file = os.environ['READY_FILE']
|
|
32
|
+
|
|
33
|
+
with open(ready_file) as f:
|
|
34
|
+
data = json.load(f)
|
|
35
|
+
|
|
36
|
+
# Find task in ready
|
|
37
|
+
ready = data.get('ready', [])
|
|
38
|
+
found = None
|
|
39
|
+
found_idx = None
|
|
40
|
+
|
|
41
|
+
for i, task in enumerate(ready):
|
|
42
|
+
if isinstance(task, dict):
|
|
43
|
+
if task.get('id') == task_id:
|
|
44
|
+
found = task
|
|
45
|
+
found_idx = i
|
|
46
|
+
break
|
|
47
|
+
elif task == task_id:
|
|
48
|
+
found = {'id': task_id}
|
|
49
|
+
found_idx = i
|
|
50
|
+
break
|
|
51
|
+
|
|
52
|
+
if found is None:
|
|
53
|
+
print(f'\033[0;31mTask {task_id} not found in ready queue\033[0m')
|
|
54
|
+
exit(1)
|
|
55
|
+
|
|
56
|
+
# Move to in progress
|
|
57
|
+
ready.pop(found_idx)
|
|
58
|
+
data['ready'] = ready
|
|
59
|
+
|
|
60
|
+
in_progress = data.get('inProgress', [])
|
|
61
|
+
in_progress.append(found)
|
|
62
|
+
data['inProgress'] = in_progress
|
|
63
|
+
|
|
64
|
+
# Update timestamp
|
|
65
|
+
from datetime import datetime
|
|
66
|
+
data['lastUpdated'] = datetime.now().isoformat()
|
|
67
|
+
|
|
68
|
+
with open(ready_file, 'w') as f:
|
|
69
|
+
json.dump(data, f, indent=2)
|
|
70
|
+
|
|
71
|
+
print(f'\033[0;32m✓ Started: {task_id}\033[0m')
|
|
72
|
+
if isinstance(found, dict) and found.get('title'):
|
|
73
|
+
print(f' {found["title"]}')
|
|
74
|
+
EOF
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Wogi Flow - Start Task
|
|
5
|
+
*
|
|
6
|
+
* Moves a task from ready to inProgress queue.
|
|
7
|
+
* v2.0: Integrates with durable session for crash recovery and suspension support.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const {
|
|
11
|
+
PATHS,
|
|
12
|
+
fileExists,
|
|
13
|
+
moveTaskAsync,
|
|
14
|
+
findTask,
|
|
15
|
+
color,
|
|
16
|
+
error,
|
|
17
|
+
getConfig
|
|
18
|
+
} = require('./flow-utils');
|
|
19
|
+
const { getAutoContext, formatAutoContext } = require('./flow-auto-context');
|
|
20
|
+
const { shouldUseMultiApproach, analyzeForMultiApproach, formatAnalysis } = require('./flow-multi-approach');
|
|
21
|
+
const { assessTaskComplexity } = require('./flow-complexity');
|
|
22
|
+
|
|
23
|
+
// v1.7.0 context memory management
|
|
24
|
+
const { warnIfContextHigh, checkContextHealth } = require('./flow-context-monitor');
|
|
25
|
+
const { setCurrentTask } = require('./flow-memory-blocks');
|
|
26
|
+
const { trackTaskStart, checkAndDisplayResumeContext } = require('./flow-session-state');
|
|
27
|
+
|
|
28
|
+
// v2.0 durable session support
|
|
29
|
+
const {
|
|
30
|
+
loadDurableSession,
|
|
31
|
+
createDurableSession,
|
|
32
|
+
createDurableSessionAsync,
|
|
33
|
+
canResumeFromStep,
|
|
34
|
+
getResumeContext,
|
|
35
|
+
getSuspensionStatus,
|
|
36
|
+
resumeSession,
|
|
37
|
+
isSuspended,
|
|
38
|
+
STEP_STATUS
|
|
39
|
+
} = require('./flow-durable-session');
|
|
40
|
+
|
|
41
|
+
async function main() {
|
|
42
|
+
const taskId = process.argv[2];
|
|
43
|
+
const forceResume = process.argv.includes('--force-resume');
|
|
44
|
+
const skipSuspensionCheck = process.argv.includes('--skip-suspension');
|
|
45
|
+
|
|
46
|
+
if (!taskId) {
|
|
47
|
+
console.log('Usage: flow start <task-id> [--force-resume] [--skip-suspension]');
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// v1.7.0: Check for session resume context
|
|
52
|
+
const config = getConfig();
|
|
53
|
+
if (config.sessionState?.autoRestore !== false) {
|
|
54
|
+
checkAndDisplayResumeContext();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// v1.7.0: Check context health at task start
|
|
58
|
+
if (config.contextMonitor?.checkOnSessionStart !== false) {
|
|
59
|
+
warnIfContextHigh();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// v2.0: Check for existing durable session for this task
|
|
63
|
+
if (config.durableSteps?.enabled !== false) {
|
|
64
|
+
const existingSession = loadDurableSession();
|
|
65
|
+
|
|
66
|
+
if (existingSession && existingSession.taskId === taskId) {
|
|
67
|
+
// Found existing session for this task - handle resume
|
|
68
|
+
const resumeInfo = canResumeFromStep(existingSession);
|
|
69
|
+
const suspension = getSuspensionStatus();
|
|
70
|
+
|
|
71
|
+
if (suspension && !skipSuspensionCheck) {
|
|
72
|
+
// Task is suspended
|
|
73
|
+
console.log('');
|
|
74
|
+
console.log(color('yellow', '⏸️ Task is SUSPENDED'));
|
|
75
|
+
console.log(color('yellow', '─'.repeat(50)));
|
|
76
|
+
console.log(`Task: ${taskId}`);
|
|
77
|
+
console.log(`Type: ${suspension.type}`);
|
|
78
|
+
console.log(`Reason: ${suspension.reason}`);
|
|
79
|
+
console.log(`Suspended at: ${suspension.suspendedAt}`);
|
|
80
|
+
console.log('');
|
|
81
|
+
|
|
82
|
+
if (suspension.canResume) {
|
|
83
|
+
console.log(color('green', '✓ Resume condition is met!'));
|
|
84
|
+
if (forceResume) {
|
|
85
|
+
console.log('Resuming session...');
|
|
86
|
+
resumeSession({ force: true });
|
|
87
|
+
} else {
|
|
88
|
+
console.log(`Run: ${color('cyan', `flow start ${taskId} --force-resume`)} to continue`);
|
|
89
|
+
process.exit(0);
|
|
90
|
+
}
|
|
91
|
+
} else {
|
|
92
|
+
console.log(color('red', '✗ Resume condition not yet met'));
|
|
93
|
+
console.log(`Reason: ${suspension.resumeReason}`);
|
|
94
|
+
console.log('');
|
|
95
|
+
console.log(`To override: ${color('cyan', `flow start ${taskId} --skip-suspension`)}`);
|
|
96
|
+
process.exit(0);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (resumeInfo.canResume && resumeInfo.completedCount > 0) {
|
|
101
|
+
// Show resume context
|
|
102
|
+
console.log('');
|
|
103
|
+
console.log(color('cyan', '🔄 Resuming from durable session'));
|
|
104
|
+
console.log(color('cyan', '─'.repeat(50)));
|
|
105
|
+
console.log(`Task: ${taskId}`);
|
|
106
|
+
console.log(`Progress: ${resumeInfo.completedCount}/${resumeInfo.totalSteps} steps completed`);
|
|
107
|
+
console.log(`Resuming from: ${resumeInfo.fromStep?.description?.substring(0, 60) || resumeInfo.fromStep?.id}...`);
|
|
108
|
+
console.log(color('cyan', '─'.repeat(50)));
|
|
109
|
+
console.log('');
|
|
110
|
+
}
|
|
111
|
+
} else if (existingSession && existingSession.taskId !== taskId) {
|
|
112
|
+
// Different task in session - block starting new task
|
|
113
|
+
console.log('');
|
|
114
|
+
console.log(color('yellow', '⚠️ Another task is in a durable session'));
|
|
115
|
+
console.log(`Current session: ${existingSession.taskId}`);
|
|
116
|
+
console.log(`Attempting to start: ${taskId}`);
|
|
117
|
+
console.log('');
|
|
118
|
+
console.log(`Finish current task first, or run: ${color('cyan', 'flow session clear')}`);
|
|
119
|
+
console.log('');
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (!fileExists(PATHS.ready)) {
|
|
125
|
+
error('No ready.json found');
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Check if task exists and where it is
|
|
130
|
+
const found = findTask(taskId);
|
|
131
|
+
|
|
132
|
+
if (!found) {
|
|
133
|
+
console.log(color('red', `Task ${taskId} not found in any queue`));
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (found.list === 'inProgress') {
|
|
138
|
+
console.log(color('yellow', `Task ${taskId} is already in progress`));
|
|
139
|
+
process.exit(0);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (found.list !== 'ready') {
|
|
143
|
+
console.log(color('red', `Task ${taskId} is in ${found.list}, not ready`));
|
|
144
|
+
process.exit(1);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Move task from ready to inProgress (with file locking)
|
|
148
|
+
const result = await moveTaskAsync(taskId, 'ready', 'inProgress');
|
|
149
|
+
|
|
150
|
+
if (!result.success) {
|
|
151
|
+
error(result.error);
|
|
152
|
+
process.exit(1);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
console.log(color('green', `✓ Started: ${taskId}`));
|
|
156
|
+
|
|
157
|
+
const taskTitle = result.task && typeof result.task === 'object' && result.task.title
|
|
158
|
+
? result.task.title
|
|
159
|
+
: taskId;
|
|
160
|
+
|
|
161
|
+
if (result.task && typeof result.task === 'object' && result.task.title) {
|
|
162
|
+
console.log(` ${result.task.title}`);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// v1.7.0: Track task in session state and memory blocks
|
|
166
|
+
try {
|
|
167
|
+
trackTaskStart(taskId, taskTitle);
|
|
168
|
+
setCurrentTask(taskId, taskTitle);
|
|
169
|
+
} catch (err) {
|
|
170
|
+
if (process.env.DEBUG) console.error(`[DEBUG] Task tracking: ${err.message}`);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// v2.0: Initialize durable session for crash recovery (with file locking)
|
|
174
|
+
if (config.durableSteps?.enabled !== false) {
|
|
175
|
+
try {
|
|
176
|
+
// Extract acceptance criteria if available
|
|
177
|
+
const acceptanceCriteria = result.task?.acceptanceCriteria || result.task?.scenarios || [];
|
|
178
|
+
const steps = Array.isArray(acceptanceCriteria) ? acceptanceCriteria : [];
|
|
179
|
+
const sessionSteps = steps.length > 0 ? steps : [taskTitle || taskId];
|
|
180
|
+
|
|
181
|
+
// Use async version with file locking to prevent race conditions
|
|
182
|
+
const session = await createDurableSessionAsync(taskId, 'task', sessionSteps);
|
|
183
|
+
|
|
184
|
+
if (steps.length > 0) {
|
|
185
|
+
console.log(color('cyan', `📋 Durable session initialized with ${steps.length} steps`));
|
|
186
|
+
} else if (process.env.DEBUG) {
|
|
187
|
+
console.log(color('cyan', '📋 Durable session initialized (no acceptance criteria)'));
|
|
188
|
+
}
|
|
189
|
+
} catch (err) {
|
|
190
|
+
if (process.env.DEBUG) console.error(`[DEBUG] Durable session init: ${err.message}`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Auto-context: show relevant files for this task
|
|
195
|
+
const taskDescription = result.task?.title || result.task?.description || taskId;
|
|
196
|
+
|
|
197
|
+
if (config.autoContext?.enabled !== false) {
|
|
198
|
+
try {
|
|
199
|
+
const context = await getAutoContext(taskDescription);
|
|
200
|
+
if (context.files && context.files.length > 0) {
|
|
201
|
+
console.log('');
|
|
202
|
+
console.log(formatAutoContext(context));
|
|
203
|
+
}
|
|
204
|
+
} catch (err) {
|
|
205
|
+
// Auto-context is best-effort; don't block task start on failure
|
|
206
|
+
if (process.env.DEBUG) console.error(`[DEBUG] Auto-context: ${err.message}`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Multi-approach: suggest for complex tasks
|
|
211
|
+
if (config.multiApproach?.enabled !== false && config.multiApproach?.mode === 'suggest') {
|
|
212
|
+
try {
|
|
213
|
+
const complexity = assessTaskComplexity(taskDescription);
|
|
214
|
+
const decision = shouldUseMultiApproach(complexity.level);
|
|
215
|
+
|
|
216
|
+
if (decision.shouldUse) {
|
|
217
|
+
console.log('');
|
|
218
|
+
console.log(color('yellow', '━'.repeat(50)));
|
|
219
|
+
console.log(color('yellow', '💡 Multi-Approach Suggestion'));
|
|
220
|
+
console.log(color('yellow', '━'.repeat(50)));
|
|
221
|
+
console.log(`This task has "${complexity.level}" complexity.`);
|
|
222
|
+
console.log('Consider using multi-approach validation for better results.');
|
|
223
|
+
console.log(` Run: ${color('cyan', `flow multi-approach --analyze "${taskDescription}"`)}`);
|
|
224
|
+
console.log('');
|
|
225
|
+
}
|
|
226
|
+
} catch {
|
|
227
|
+
// Ignore multi-approach errors
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
main().catch(err => {
|
|
233
|
+
console.error(`Error: ${err.message}`);
|
|
234
|
+
process.exit(1);
|
|
235
|
+
});
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Wogi Flow - Project Status Overview
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
WORKFLOW_DIR=".workflow"
|
|
8
|
+
|
|
9
|
+
# Colors
|
|
10
|
+
GREEN='\033[0;32m'
|
|
11
|
+
YELLOW='\033[1;33m'
|
|
12
|
+
CYAN='\033[0;36m'
|
|
13
|
+
RED='\033[0;31m'
|
|
14
|
+
NC='\033[0m'
|
|
15
|
+
|
|
16
|
+
echo -e "${CYAN}═══════════════════════════════════════${NC}"
|
|
17
|
+
echo -e "${CYAN} PROJECT STATUS${NC}"
|
|
18
|
+
echo -e "${CYAN}═══════════════════════════════════════${NC}"
|
|
19
|
+
echo ""
|
|
20
|
+
|
|
21
|
+
# Task counts
|
|
22
|
+
if [ -f "$WORKFLOW_DIR/state/ready.json" ]; then
|
|
23
|
+
echo -e "${CYAN}Tasks${NC}"
|
|
24
|
+
READY_FILE="$WORKFLOW_DIR/state/ready.json" python3 << 'EOF'
|
|
25
|
+
import json, os
|
|
26
|
+
with open(os.environ['READY_FILE']) as f:
|
|
27
|
+
data = json.load(f)
|
|
28
|
+
ready = len(data.get('ready', []))
|
|
29
|
+
in_prog = len(data.get('inProgress', []))
|
|
30
|
+
blocked = len(data.get('blocked', []))
|
|
31
|
+
done = len(data.get('recentlyCompleted', []))
|
|
32
|
+
print(f" Ready: {ready}")
|
|
33
|
+
print(f" In Progress: {in_prog}")
|
|
34
|
+
print(f" Blocked: {blocked}")
|
|
35
|
+
print(f" Recently Done: {done}")
|
|
36
|
+
EOF
|
|
37
|
+
echo ""
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
# Features
|
|
41
|
+
if [ -d "$WORKFLOW_DIR/changes" ]; then
|
|
42
|
+
feature_count=$(find "$WORKFLOW_DIR/changes" -maxdepth 1 -type d | wc -l)
|
|
43
|
+
feature_count=$((feature_count - 1))
|
|
44
|
+
echo -e "${CYAN}Features${NC}"
|
|
45
|
+
echo " Active: $feature_count"
|
|
46
|
+
if [ $feature_count -gt 0 ]; then
|
|
47
|
+
for dir in "$WORKFLOW_DIR/changes"/*/; do
|
|
48
|
+
if [ -d "$dir" ]; then
|
|
49
|
+
name=$(basename "$dir")
|
|
50
|
+
echo " • $name"
|
|
51
|
+
fi
|
|
52
|
+
done
|
|
53
|
+
fi
|
|
54
|
+
echo ""
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
# Bugs
|
|
58
|
+
if [ -d "$WORKFLOW_DIR/bugs" ]; then
|
|
59
|
+
bug_count=$(ls "$WORKFLOW_DIR/bugs"/*.md 2>/dev/null | wc -l || echo 0)
|
|
60
|
+
echo -e "${CYAN}Bugs${NC}"
|
|
61
|
+
echo " Open: $bug_count"
|
|
62
|
+
echo ""
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
# Components (from app-map)
|
|
66
|
+
if [ -f "$WORKFLOW_DIR/state/app-map.md" ]; then
|
|
67
|
+
component_count=$(grep -c "^|" "$WORKFLOW_DIR/state/app-map.md" 2>/dev/null || echo 0)
|
|
68
|
+
component_count=$((component_count - 6)) # Subtract headers
|
|
69
|
+
if [ $component_count -lt 0 ]; then component_count=0; fi
|
|
70
|
+
echo -e "${CYAN}Components${NC}"
|
|
71
|
+
echo " Mapped: $component_count"
|
|
72
|
+
echo ""
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
# Request log entries
|
|
76
|
+
if [ -f "$WORKFLOW_DIR/state/request-log.md" ]; then
|
|
77
|
+
entry_count=$(grep -c "^### R-" "$WORKFLOW_DIR/state/request-log.md" 2>/dev/null || echo 0)
|
|
78
|
+
echo -e "${CYAN}Request Log${NC}"
|
|
79
|
+
echo " Entries: $entry_count"
|
|
80
|
+
echo ""
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
# Git status
|
|
84
|
+
if [ -d ".git" ]; then
|
|
85
|
+
echo -e "${CYAN}Git${NC}"
|
|
86
|
+
branch=$(git branch --show-current 2>/dev/null || echo "unknown")
|
|
87
|
+
uncommitted=$(git status --porcelain 2>/dev/null | wc -l)
|
|
88
|
+
echo " Branch: $branch"
|
|
89
|
+
echo " Uncommitted: $uncommitted files"
|
|
90
|
+
echo ""
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
# Config summary
|
|
94
|
+
if [ -f "$WORKFLOW_DIR/config.json" ]; then
|
|
95
|
+
echo -e "${CYAN}Config${NC}"
|
|
96
|
+
CONFIG_FILE="$WORKFLOW_DIR/config.json" python3 << 'EOF'
|
|
97
|
+
import json, os
|
|
98
|
+
with open(os.environ['CONFIG_FILE']) as f:
|
|
99
|
+
config = json.load(f)
|
|
100
|
+
steps = config.get('mandatorySteps', {})
|
|
101
|
+
after_task = steps.get('afterTask', [])
|
|
102
|
+
if after_task:
|
|
103
|
+
print(f" After task: {', '.join(after_task)}")
|
|
104
|
+
else:
|
|
105
|
+
print(" After task: (none)")
|
|
106
|
+
EOF
|
|
107
|
+
fi
|
|
108
|
+
|
|
109
|
+
echo ""
|
|
110
|
+
echo -e "${CYAN}═══════════════════════════════════════${NC}"
|