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,185 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Wogi Flow - Health Check
|
|
4
|
+
# Verifies workflow files are in sync and properly configured
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
WORKFLOW_DIR=".workflow"
|
|
9
|
+
|
|
10
|
+
# Colors
|
|
11
|
+
RED='\033[0;31m'
|
|
12
|
+
GREEN='\033[0;32m'
|
|
13
|
+
YELLOW='\033[1;33m'
|
|
14
|
+
CYAN='\033[0;36m'
|
|
15
|
+
NC='\033[0m'
|
|
16
|
+
|
|
17
|
+
echo -e "${CYAN}Wogi Flow Health Check${NC}"
|
|
18
|
+
echo "========================"
|
|
19
|
+
echo ""
|
|
20
|
+
|
|
21
|
+
issues=0
|
|
22
|
+
warnings=0
|
|
23
|
+
|
|
24
|
+
# Check required files exist
|
|
25
|
+
echo -e "${CYAN}Checking required files...${NC}"
|
|
26
|
+
|
|
27
|
+
required_files=(
|
|
28
|
+
"$WORKFLOW_DIR/config.json"
|
|
29
|
+
"$WORKFLOW_DIR/state/ready.json"
|
|
30
|
+
"$WORKFLOW_DIR/state/request-log.md"
|
|
31
|
+
"$WORKFLOW_DIR/state/app-map.md"
|
|
32
|
+
"$WORKFLOW_DIR/state/decisions.md"
|
|
33
|
+
"$WORKFLOW_DIR/state/progress.md"
|
|
34
|
+
"CLAUDE.md"
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
for file in "${required_files[@]}"; do
|
|
38
|
+
if [ -f "$file" ]; then
|
|
39
|
+
echo -e " ${GREEN}✓${NC} $file"
|
|
40
|
+
else
|
|
41
|
+
echo -e " ${RED}✗${NC} $file - MISSING"
|
|
42
|
+
issues=$((issues + 1))
|
|
43
|
+
fi
|
|
44
|
+
done
|
|
45
|
+
|
|
46
|
+
# Check required directories
|
|
47
|
+
echo ""
|
|
48
|
+
echo -e "${CYAN}Checking directories...${NC}"
|
|
49
|
+
|
|
50
|
+
required_dirs=(
|
|
51
|
+
"$WORKFLOW_DIR/state/components"
|
|
52
|
+
"$WORKFLOW_DIR/specs"
|
|
53
|
+
"$WORKFLOW_DIR/changes"
|
|
54
|
+
"$WORKFLOW_DIR/bugs"
|
|
55
|
+
"$WORKFLOW_DIR/archive"
|
|
56
|
+
"agents"
|
|
57
|
+
"scripts"
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
for dir in "${required_dirs[@]}"; do
|
|
61
|
+
if [ -d "$dir" ]; then
|
|
62
|
+
echo -e " ${GREEN}✓${NC} $dir/"
|
|
63
|
+
else
|
|
64
|
+
echo -e " ${RED}✗${NC} $dir/ - MISSING"
|
|
65
|
+
issues=$((issues + 1))
|
|
66
|
+
fi
|
|
67
|
+
done
|
|
68
|
+
|
|
69
|
+
# Check config.json is valid JSON
|
|
70
|
+
echo ""
|
|
71
|
+
echo -e "${CYAN}Validating config.json...${NC}"
|
|
72
|
+
|
|
73
|
+
if [ -f "$WORKFLOW_DIR/config.json" ]; then
|
|
74
|
+
if python3 -c "import json, sys; json.load(open(sys.argv[1]))" "$WORKFLOW_DIR/config.json" 2>/dev/null; then
|
|
75
|
+
echo -e " ${GREEN}✓${NC} Valid JSON"
|
|
76
|
+
else
|
|
77
|
+
echo -e " ${RED}✗${NC} Invalid JSON syntax"
|
|
78
|
+
issues=$((issues + 1))
|
|
79
|
+
fi
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
# Check ready.json is valid JSON
|
|
83
|
+
echo ""
|
|
84
|
+
echo -e "${CYAN}Validating ready.json...${NC}"
|
|
85
|
+
|
|
86
|
+
if [ -f "$WORKFLOW_DIR/state/ready.json" ]; then
|
|
87
|
+
if python3 -c "import json, sys; json.load(open(sys.argv[1]))" "$WORKFLOW_DIR/state/ready.json" 2>/dev/null; then
|
|
88
|
+
echo -e " ${GREEN}✓${NC} Valid JSON"
|
|
89
|
+
else
|
|
90
|
+
echo -e " ${RED}✗${NC} Invalid JSON syntax"
|
|
91
|
+
issues=$((issues + 1))
|
|
92
|
+
fi
|
|
93
|
+
fi
|
|
94
|
+
|
|
95
|
+
# Check app-map vs actual components
|
|
96
|
+
echo ""
|
|
97
|
+
echo -e "${CYAN}Checking app-map sync...${NC}"
|
|
98
|
+
|
|
99
|
+
if [ -d "src/components" ]; then
|
|
100
|
+
component_count=$(find src/components -name "*.tsx" -o -name "*.jsx" 2>/dev/null | wc -l)
|
|
101
|
+
mapped_count=$(grep -c "^|" "$WORKFLOW_DIR/state/app-map.md" 2>/dev/null || echo 0)
|
|
102
|
+
mapped_count=$((mapped_count - 3)) # Subtract header rows
|
|
103
|
+
|
|
104
|
+
if [ $mapped_count -lt 0 ]; then mapped_count=0; fi
|
|
105
|
+
|
|
106
|
+
echo -e " Components in src/: $component_count"
|
|
107
|
+
echo -e " Components in app-map: $mapped_count"
|
|
108
|
+
|
|
109
|
+
if [ $component_count -gt $((mapped_count + 5)) ]; then
|
|
110
|
+
echo -e " ${YELLOW}⚠${NC} App-map may be out of sync"
|
|
111
|
+
echo -e " Run: ./scripts/flow update-map scan src/components"
|
|
112
|
+
warnings=$((warnings + 1))
|
|
113
|
+
else
|
|
114
|
+
echo -e " ${GREEN}✓${NC} App-map appears in sync"
|
|
115
|
+
fi
|
|
116
|
+
else
|
|
117
|
+
echo -e " ${YELLOW}⚠${NC} src/components/ not found (may be OK for new projects)"
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
# Check git status
|
|
121
|
+
echo ""
|
|
122
|
+
echo -e "${CYAN}Checking git status...${NC}"
|
|
123
|
+
|
|
124
|
+
if [ -d ".git" ]; then
|
|
125
|
+
uncommitted=$(git status --porcelain 2>/dev/null | wc -l)
|
|
126
|
+
if [ $uncommitted -eq 0 ]; then
|
|
127
|
+
echo -e " ${GREEN}✓${NC} Working directory clean"
|
|
128
|
+
else
|
|
129
|
+
echo -e " ${YELLOW}⚠${NC} $uncommitted uncommitted changes"
|
|
130
|
+
warnings=$((warnings + 1))
|
|
131
|
+
fi
|
|
132
|
+
else
|
|
133
|
+
echo -e " ${YELLOW}⚠${NC} Not a git repository"
|
|
134
|
+
warnings=$((warnings + 1))
|
|
135
|
+
fi
|
|
136
|
+
|
|
137
|
+
# Check request-log recent activity
|
|
138
|
+
echo ""
|
|
139
|
+
echo -e "${CYAN}Checking request-log...${NC}"
|
|
140
|
+
|
|
141
|
+
if [ -f "$WORKFLOW_DIR/state/request-log.md" ]; then
|
|
142
|
+
entry_count=$(grep -c "^### R-" "$WORKFLOW_DIR/state/request-log.md" 2>/dev/null || echo 0)
|
|
143
|
+
echo -e " Total entries: $entry_count"
|
|
144
|
+
|
|
145
|
+
if [ $entry_count -gt 0 ]; then
|
|
146
|
+
last_entry=$(grep "^### R-" "$WORKFLOW_DIR/state/request-log.md" | tail -1)
|
|
147
|
+
echo -e " Last entry: $last_entry"
|
|
148
|
+
fi
|
|
149
|
+
fi
|
|
150
|
+
|
|
151
|
+
# Check agents exist
|
|
152
|
+
echo ""
|
|
153
|
+
echo -e "${CYAN}Checking agents...${NC}"
|
|
154
|
+
|
|
155
|
+
core_agents=("orchestrator" "developer" "reviewer" "tester")
|
|
156
|
+
optional_agents=("accessibility" "security" "performance" "docs" "design-system" "onboarding")
|
|
157
|
+
|
|
158
|
+
for agent in "${core_agents[@]}"; do
|
|
159
|
+
if [ -f "agents/$agent.md" ]; then
|
|
160
|
+
echo -e " ${GREEN}✓${NC} $agent.md"
|
|
161
|
+
else
|
|
162
|
+
echo -e " ${RED}✗${NC} $agent.md - MISSING (core agent)"
|
|
163
|
+
issues=$((issues + 1))
|
|
164
|
+
fi
|
|
165
|
+
done
|
|
166
|
+
|
|
167
|
+
for agent in "${optional_agents[@]}"; do
|
|
168
|
+
if [ -f "agents/$agent.md" ]; then
|
|
169
|
+
echo -e " ${GREEN}✓${NC} $agent.md (optional)"
|
|
170
|
+
fi
|
|
171
|
+
done
|
|
172
|
+
|
|
173
|
+
# Summary
|
|
174
|
+
echo ""
|
|
175
|
+
echo "========================"
|
|
176
|
+
|
|
177
|
+
if [ $issues -eq 0 ] && [ $warnings -eq 0 ]; then
|
|
178
|
+
echo -e "${GREEN}✓ Workflow is healthy!${NC}"
|
|
179
|
+
elif [ $issues -eq 0 ]; then
|
|
180
|
+
echo -e "${YELLOW}⚠ $warnings warning(s), but no critical issues${NC}"
|
|
181
|
+
else
|
|
182
|
+
echo -e "${RED}✗ $issues issue(s), $warnings warning(s)${NC}"
|
|
183
|
+
echo ""
|
|
184
|
+
echo "Run './scripts/flow init' to fix missing files"
|
|
185
|
+
fi
|
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Wogi Flow - Health Check
|
|
5
|
+
*
|
|
6
|
+
* Verifies workflow files are in sync and properly configured.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const {
|
|
11
|
+
PATHS,
|
|
12
|
+
PROJECT_ROOT,
|
|
13
|
+
fileExists,
|
|
14
|
+
dirExists,
|
|
15
|
+
validateJson,
|
|
16
|
+
countAppMapComponents,
|
|
17
|
+
countRequestLogEntries,
|
|
18
|
+
getLastRequestLogEntry,
|
|
19
|
+
getGitStatus,
|
|
20
|
+
countFiles,
|
|
21
|
+
color,
|
|
22
|
+
printSection,
|
|
23
|
+
success,
|
|
24
|
+
warn,
|
|
25
|
+
error,
|
|
26
|
+
validatePermissions
|
|
27
|
+
} = require('./flow-utils');
|
|
28
|
+
|
|
29
|
+
function main() {
|
|
30
|
+
console.log(color('cyan', 'Wogi Flow Health Check'));
|
|
31
|
+
console.log('========================');
|
|
32
|
+
console.log('');
|
|
33
|
+
|
|
34
|
+
let issues = 0;
|
|
35
|
+
let warnings = 0;
|
|
36
|
+
|
|
37
|
+
// Check required files
|
|
38
|
+
printSection('Checking required files...');
|
|
39
|
+
|
|
40
|
+
const requiredFiles = [
|
|
41
|
+
{ path: PATHS.config, name: '.workflow/config.json' },
|
|
42
|
+
{ path: PATHS.ready, name: '.workflow/state/ready.json' },
|
|
43
|
+
{ path: PATHS.requestLog, name: '.workflow/state/request-log.md' },
|
|
44
|
+
{ path: PATHS.appMap, name: '.workflow/state/app-map.md' },
|
|
45
|
+
{ path: PATHS.decisions, name: '.workflow/state/decisions.md' },
|
|
46
|
+
{ path: PATHS.progress, name: '.workflow/state/progress.md' },
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
for (const file of requiredFiles) {
|
|
50
|
+
if (fileExists(file.path)) {
|
|
51
|
+
console.log(` ${color('green', '✓')} ${file.name}`);
|
|
52
|
+
} else {
|
|
53
|
+
console.log(` ${color('red', '✗')} ${file.name} - MISSING`);
|
|
54
|
+
issues++;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Check CLI-specific rules file
|
|
59
|
+
let cliType = 'claude-code'; // default
|
|
60
|
+
if (fileExists(PATHS.config)) {
|
|
61
|
+
try {
|
|
62
|
+
const config = require(PATHS.config);
|
|
63
|
+
cliType = config.cli?.type || 'claude-code';
|
|
64
|
+
} catch {}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const rulesFiles = {
|
|
68
|
+
'claude-code': { path: path.join(PROJECT_ROOT, 'CLAUDE.md'), name: 'CLAUDE.md' },
|
|
69
|
+
'gemini-cli': { path: path.join(PROJECT_ROOT, 'GEMINI.md'), name: 'GEMINI.md' },
|
|
70
|
+
'opencode': { path: path.join(PROJECT_ROOT, '.opencode', 'config.json'), name: '.opencode/config.json' }
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const rulesFile = rulesFiles[cliType] || rulesFiles['claude-code'];
|
|
74
|
+
if (fileExists(rulesFile.path)) {
|
|
75
|
+
console.log(` ${color('green', '✓')} ${rulesFile.name} (${cliType})`);
|
|
76
|
+
} else {
|
|
77
|
+
console.log(` ${color('red', '✗')} ${rulesFile.name} - MISSING (${cliType})`);
|
|
78
|
+
issues++;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Check required directories
|
|
82
|
+
console.log('');
|
|
83
|
+
printSection('Checking directories...');
|
|
84
|
+
|
|
85
|
+
const requiredDirs = [
|
|
86
|
+
{ path: PATHS.components, name: '.workflow/state/components' },
|
|
87
|
+
{ path: PATHS.specs, name: '.workflow/specs' },
|
|
88
|
+
{ path: PATHS.changes, name: '.workflow/changes' },
|
|
89
|
+
{ path: PATHS.bugs, name: '.workflow/bugs' },
|
|
90
|
+
{ path: PATHS.archive, name: '.workflow/archive' },
|
|
91
|
+
{ path: path.join(PROJECT_ROOT, 'agents'), name: 'agents' },
|
|
92
|
+
{ path: path.join(PROJECT_ROOT, 'scripts'), name: 'scripts' },
|
|
93
|
+
];
|
|
94
|
+
|
|
95
|
+
for (const dir of requiredDirs) {
|
|
96
|
+
if (dirExists(dir.path)) {
|
|
97
|
+
console.log(` ${color('green', '✓')} ${dir.name}/`);
|
|
98
|
+
} else {
|
|
99
|
+
console.log(` ${color('red', '✗')} ${dir.name}/ - MISSING`);
|
|
100
|
+
issues++;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Check universal structure directories (optional but recommended)
|
|
105
|
+
console.log('');
|
|
106
|
+
printSection('Checking universal structure...');
|
|
107
|
+
|
|
108
|
+
const universalDirs = [
|
|
109
|
+
{ path: path.join(PROJECT_ROOT, '.workflow', 'models'), name: '.workflow/models' },
|
|
110
|
+
{ path: path.join(PROJECT_ROOT, '.workflow', 'bridges'), name: '.workflow/bridges' },
|
|
111
|
+
{ path: path.join(PROJECT_ROOT, '.workflow', 'templates'), name: '.workflow/templates' },
|
|
112
|
+
];
|
|
113
|
+
|
|
114
|
+
for (const dir of universalDirs) {
|
|
115
|
+
if (dirExists(dir.path)) {
|
|
116
|
+
console.log(` ${color('green', '✓')} ${dir.name}/`);
|
|
117
|
+
} else {
|
|
118
|
+
console.log(` ${color('yellow', '○')} ${dir.name}/ - not found (run 'flow migrate' to add)`);
|
|
119
|
+
warnings++;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Check model registry
|
|
124
|
+
const registryPath = path.join(PROJECT_ROOT, '.workflow', 'models', 'registry.json');
|
|
125
|
+
if (fileExists(registryPath)) {
|
|
126
|
+
const result = validateJson(registryPath);
|
|
127
|
+
if (result.valid) {
|
|
128
|
+
console.log(` ${color('green', '✓')} Model registry valid`);
|
|
129
|
+
} else {
|
|
130
|
+
console.log(` ${color('red', '✗')} Model registry invalid JSON`);
|
|
131
|
+
issues++;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Check knowledge files (optional - generated by onboard)
|
|
136
|
+
console.log('');
|
|
137
|
+
printSection('Checking knowledge files...');
|
|
138
|
+
|
|
139
|
+
// Use paths from PATHS constant (defined in flow-utils.js)
|
|
140
|
+
const knowledgeFiles = [
|
|
141
|
+
{ path: PATHS.stackMd, name: 'stack.md', category: 'stack' },
|
|
142
|
+
{ path: PATHS.architectureMd, name: 'architecture.md', category: 'architecture' },
|
|
143
|
+
{ path: PATHS.testingMd, name: 'testing.md', category: 'testing' },
|
|
144
|
+
];
|
|
145
|
+
|
|
146
|
+
// Try to load drift detection
|
|
147
|
+
let driftStatus = null;
|
|
148
|
+
try {
|
|
149
|
+
const { checkAllDrift } = require('./flow-knowledge-sync');
|
|
150
|
+
driftStatus = checkAllDrift();
|
|
151
|
+
} catch {
|
|
152
|
+
// Knowledge sync not available
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
for (const file of knowledgeFiles) {
|
|
156
|
+
if (fileExists(file.path)) {
|
|
157
|
+
// Check sync status if available
|
|
158
|
+
const categoryStatus = driftStatus?.categories?.[file.category];
|
|
159
|
+
if (categoryStatus?.status === 'drifted') {
|
|
160
|
+
console.log(` ${color('yellow', '⚠')} ${file.name} - out of sync (${categoryStatus.reason})`);
|
|
161
|
+
warnings++;
|
|
162
|
+
} else {
|
|
163
|
+
console.log(` ${color('green', '✓')} ${file.name}`);
|
|
164
|
+
}
|
|
165
|
+
} else {
|
|
166
|
+
console.log(` ${color('yellow', '○')} ${file.name} - not found (run 'flow onboard' to generate)`);
|
|
167
|
+
warnings++;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Show sync recommendation if drift detected
|
|
172
|
+
if (driftStatus?.anyDrift) {
|
|
173
|
+
console.log('');
|
|
174
|
+
console.log(` ${color('dim', "Run 'flow knowledge-sync regenerate' to update")}`);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Validate config.json
|
|
178
|
+
console.log('');
|
|
179
|
+
printSection('Validating config.json...');
|
|
180
|
+
|
|
181
|
+
if (fileExists(PATHS.config)) {
|
|
182
|
+
const result = validateJson(PATHS.config);
|
|
183
|
+
if (result.valid) {
|
|
184
|
+
console.log(` ${color('green', '✓')} Valid JSON`);
|
|
185
|
+
} else {
|
|
186
|
+
console.log(` ${color('red', '✗')} Invalid JSON syntax`);
|
|
187
|
+
issues++;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Validate ready.json
|
|
192
|
+
console.log('');
|
|
193
|
+
printSection('Validating ready.json...');
|
|
194
|
+
|
|
195
|
+
if (fileExists(PATHS.ready)) {
|
|
196
|
+
const result = validateJson(PATHS.ready);
|
|
197
|
+
if (result.valid) {
|
|
198
|
+
console.log(` ${color('green', '✓')} Valid JSON`);
|
|
199
|
+
} else {
|
|
200
|
+
console.log(` ${color('red', '✗')} Invalid JSON syntax`);
|
|
201
|
+
issues++;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Check enforcement settings
|
|
206
|
+
console.log('');
|
|
207
|
+
printSection('Checking enforcement...');
|
|
208
|
+
|
|
209
|
+
const claudeMdPath = path.join(PROJECT_ROOT, 'CLAUDE.md');
|
|
210
|
+
if (fileExists(claudeMdPath)) {
|
|
211
|
+
const fs = require('fs');
|
|
212
|
+
const claudeMdContent = fs.readFileSync(claudeMdPath, 'utf-8');
|
|
213
|
+
const claudeMdSize = fs.statSync(claudeMdPath).size;
|
|
214
|
+
const sizeKb = Math.round(claudeMdSize / 1024);
|
|
215
|
+
|
|
216
|
+
// Check CLAUDE.md size (should be under 20KB for reliable loading)
|
|
217
|
+
if (sizeKb <= 20) {
|
|
218
|
+
console.log(` ${color('green', '✓')} CLAUDE.md size: ${sizeKb}KB (under 20KB limit)`);
|
|
219
|
+
} else {
|
|
220
|
+
console.log(` ${color('yellow', '⚠')} CLAUDE.md size: ${sizeKb}KB (over 20KB - may get truncated)`);
|
|
221
|
+
warnings++;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Check if enforcement section is at top (within first 100 lines)
|
|
225
|
+
const lines = claudeMdContent.split('\n').slice(0, 100);
|
|
226
|
+
const hasEnforcementAtTop = lines.some(line =>
|
|
227
|
+
line.includes('MANDATORY') && line.includes('Task Gating')
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
if (hasEnforcementAtTop) {
|
|
231
|
+
console.log(` ${color('green', '✓')} Enforcement section: FOUND at top of CLAUDE.md`);
|
|
232
|
+
} else {
|
|
233
|
+
console.log(` ${color('yellow', '⚠')} Enforcement section not found at top of CLAUDE.md`);
|
|
234
|
+
warnings++;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Check strict mode in config
|
|
239
|
+
if (fileExists(PATHS.config)) {
|
|
240
|
+
const configResult = validateJson(PATHS.config);
|
|
241
|
+
if (configResult.valid) {
|
|
242
|
+
try {
|
|
243
|
+
const config = JSON.parse(require('fs').readFileSync(PATHS.config, 'utf-8'));
|
|
244
|
+
if (config.enforcement?.strictMode === true) {
|
|
245
|
+
console.log(` ${color('green', '✓')} Strict mode: ENABLED`);
|
|
246
|
+
} else if (config.enforcement?.strictMode === false) {
|
|
247
|
+
console.log(` ${color('yellow', '⚠')} Strict mode: DISABLED (Claude may skip task creation)`);
|
|
248
|
+
warnings++;
|
|
249
|
+
} else {
|
|
250
|
+
console.log(` ${color('yellow', '⚠')} Strict mode: NOT CONFIGURED (add enforcement section to config.json)`);
|
|
251
|
+
warnings++;
|
|
252
|
+
}
|
|
253
|
+
} catch (err) {
|
|
254
|
+
console.log(` ${color('yellow', '⚠')} Could not parse config.json for strict mode check`);
|
|
255
|
+
warnings++;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Check app-map sync
|
|
261
|
+
console.log('');
|
|
262
|
+
printSection('Checking app-map sync...');
|
|
263
|
+
|
|
264
|
+
const srcComponents = path.join(PROJECT_ROOT, 'src', 'components');
|
|
265
|
+
if (dirExists(srcComponents)) {
|
|
266
|
+
const componentCount = countFiles(srcComponents, ['.tsx', '.jsx']);
|
|
267
|
+
const mappedCount = countAppMapComponents();
|
|
268
|
+
|
|
269
|
+
console.log(` Components in src/: ${componentCount}`);
|
|
270
|
+
console.log(` Components in app-map: ${mappedCount}`);
|
|
271
|
+
|
|
272
|
+
if (componentCount > mappedCount + 5) {
|
|
273
|
+
console.log(` ${color('yellow', '⚠')} App-map may be out of sync`);
|
|
274
|
+
console.log(' Run: ./scripts/flow update-map scan src/components');
|
|
275
|
+
warnings++;
|
|
276
|
+
} else {
|
|
277
|
+
console.log(` ${color('green', '✓')} App-map appears in sync`);
|
|
278
|
+
}
|
|
279
|
+
} else {
|
|
280
|
+
console.log(` ${color('yellow', '⚠')} src/components/ not found (may be OK for new projects)`);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Check permission rules (Claude Code specific)
|
|
284
|
+
console.log('');
|
|
285
|
+
printSection('Checking permission rules...');
|
|
286
|
+
|
|
287
|
+
const settingsPath = path.join(PROJECT_ROOT, '.claude', 'settings.local.json');
|
|
288
|
+
if (fileExists(settingsPath)) {
|
|
289
|
+
try {
|
|
290
|
+
const settings = JSON.parse(require('fs').readFileSync(settingsPath, 'utf-8'));
|
|
291
|
+
const permissions = settings.permissions?.allow || [];
|
|
292
|
+
|
|
293
|
+
// Use shared validation function
|
|
294
|
+
const validation = validatePermissions(permissions);
|
|
295
|
+
|
|
296
|
+
console.log(` Total rules: ${validation.analysis.total}`);
|
|
297
|
+
|
|
298
|
+
// Show duplicates (warning)
|
|
299
|
+
if (validation.analysis.duplicates.length > 0) {
|
|
300
|
+
console.log(` ${color('yellow', '⚠')} ${validation.analysis.duplicates.length} duplicate rule(s) found`);
|
|
301
|
+
for (const dup of validation.analysis.duplicates.slice(0, 3)) {
|
|
302
|
+
console.log(` - ${dup}`);
|
|
303
|
+
}
|
|
304
|
+
warnings++;
|
|
305
|
+
} else {
|
|
306
|
+
console.log(` ${color('green', '✓')} No duplicate rules`);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Show overly broad rules (issue)
|
|
310
|
+
if (validation.analysis.overbroad.length > 0) {
|
|
311
|
+
console.log(` ${color('yellow', '⚠')} ${validation.analysis.overbroad.length} overly broad rule(s)`);
|
|
312
|
+
for (const ob of validation.analysis.overbroad) {
|
|
313
|
+
console.log(` - ${ob}`);
|
|
314
|
+
}
|
|
315
|
+
warnings++;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Show shadowed rules (info only)
|
|
319
|
+
if (validation.analysis.shadowed.length > 0) {
|
|
320
|
+
console.log(` ${color('dim', 'ℹ')} ${validation.analysis.shadowed.length} rule(s) shadowed by wildcards (OK but redundant)`);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Check for respectGitignore
|
|
324
|
+
if (settings.respectGitignore === true) {
|
|
325
|
+
console.log(` ${color('green', '✓')} respectGitignore: enabled`);
|
|
326
|
+
} else {
|
|
327
|
+
console.log(` ${color('yellow', '○')} respectGitignore: not set`);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
} catch (err) {
|
|
331
|
+
console.log(` ${color('yellow', '⚠')} Could not parse settings.local.json`);
|
|
332
|
+
warnings++;
|
|
333
|
+
}
|
|
334
|
+
} else {
|
|
335
|
+
console.log(` ${color('yellow', '○')} .claude/settings.local.json not found (run 'flow bridge sync')`);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Check git status
|
|
339
|
+
console.log('');
|
|
340
|
+
printSection('Checking git status...');
|
|
341
|
+
|
|
342
|
+
const git = getGitStatus();
|
|
343
|
+
if (git.isRepo) {
|
|
344
|
+
if (git.clean) {
|
|
345
|
+
console.log(` ${color('green', '✓')} Working directory clean`);
|
|
346
|
+
} else {
|
|
347
|
+
console.log(` ${color('yellow', '⚠')} ${git.uncommitted} uncommitted changes`);
|
|
348
|
+
warnings++;
|
|
349
|
+
}
|
|
350
|
+
} else {
|
|
351
|
+
console.log(` ${color('yellow', '⚠')} Not a git repository`);
|
|
352
|
+
warnings++;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// Check request-log
|
|
356
|
+
console.log('');
|
|
357
|
+
printSection('Checking request-log...');
|
|
358
|
+
|
|
359
|
+
if (fileExists(PATHS.requestLog)) {
|
|
360
|
+
const entryCount = countRequestLogEntries();
|
|
361
|
+
console.log(` Total entries: ${entryCount}`);
|
|
362
|
+
|
|
363
|
+
if (entryCount > 0) {
|
|
364
|
+
const lastEntry = getLastRequestLogEntry();
|
|
365
|
+
if (lastEntry) {
|
|
366
|
+
console.log(` Last entry: ${lastEntry}`);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// Check agents
|
|
372
|
+
console.log('');
|
|
373
|
+
printSection('Checking agents...');
|
|
374
|
+
|
|
375
|
+
const agentsDir = path.join(PROJECT_ROOT, 'agents');
|
|
376
|
+
const coreAgents = ['orchestrator', 'developer', 'reviewer', 'tester'];
|
|
377
|
+
const optionalAgents = ['accessibility', 'security', 'performance', 'docs', 'design-system', 'onboarding'];
|
|
378
|
+
|
|
379
|
+
for (const agent of coreAgents) {
|
|
380
|
+
const agentPath = path.join(agentsDir, `${agent}.md`);
|
|
381
|
+
if (fileExists(agentPath)) {
|
|
382
|
+
console.log(` ${color('green', '✓')} ${agent}.md`);
|
|
383
|
+
} else {
|
|
384
|
+
console.log(` ${color('red', '✗')} ${agent}.md - MISSING (core agent)`);
|
|
385
|
+
issues++;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
for (const agent of optionalAgents) {
|
|
390
|
+
const agentPath = path.join(agentsDir, `${agent}.md`);
|
|
391
|
+
if (fileExists(agentPath)) {
|
|
392
|
+
console.log(` ${color('green', '✓')} ${agent}.md (optional)`);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// Summary
|
|
397
|
+
console.log('');
|
|
398
|
+
console.log('========================');
|
|
399
|
+
|
|
400
|
+
if (issues === 0 && warnings === 0) {
|
|
401
|
+
console.log(color('green', '✓ Workflow is healthy!'));
|
|
402
|
+
} else if (issues === 0) {
|
|
403
|
+
console.log(color('yellow', `⚠ ${warnings} warning(s), but no critical issues`));
|
|
404
|
+
} else {
|
|
405
|
+
console.log(color('red', `✗ ${issues} issue(s), ${warnings} warning(s)`));
|
|
406
|
+
console.log('');
|
|
407
|
+
console.log("Run './scripts/flow init' to fix missing files");
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
process.exit(issues > 0 ? 1 : 0);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
main();
|