@sparkleideas/claude-flow-patch 3.1.0-alpha.44.patch.10
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/AGENTS.md +162 -0
- package/CLAUDE.md +506 -0
- package/README.md +351 -0
- package/bin/claude-flow-patch.mjs +148 -0
- package/check-patches.sh +195 -0
- package/lib/categories.json +15 -0
- package/lib/common.py +97 -0
- package/lib/discover.mjs +181 -0
- package/lib/discover.sh +160 -0
- package/package.json +86 -0
- package/patch/010-CF-001-doctor-yaml/README.md +11 -0
- package/patch/010-CF-001-doctor-yaml/fix.py +20 -0
- package/patch/010-CF-001-doctor-yaml/sentinel +1 -0
- package/patch/020-CF-002-config-export-yaml/README.md +11 -0
- package/patch/020-CF-002-config-export-yaml/fix.py +130 -0
- package/patch/020-CF-002-config-export-yaml/sentinel +1 -0
- package/patch/030-DM-001-daemon-log-zero/README.md +12 -0
- package/patch/030-DM-001-daemon-log-zero/fix.py +37 -0
- package/patch/030-DM-001-daemon-log-zero/sentinel +1 -0
- package/patch/040-DM-002-cpu-load-threshold/README.md +11 -0
- package/patch/040-DM-002-cpu-load-threshold/fix.py +6 -0
- package/patch/040-DM-002-cpu-load-threshold/sentinel +1 -0
- package/patch/050-DM-003-macos-freemem/README.md +11 -0
- package/patch/050-DM-003-macos-freemem/fix.py +7 -0
- package/patch/050-DM-003-macos-freemem/sentinel +1 -0
- package/patch/060-DM-004-preload-worker-stub/README.md +11 -0
- package/patch/060-DM-004-preload-worker-stub/fix.py +34 -0
- package/patch/060-DM-004-preload-worker-stub/sentinel +1 -0
- package/patch/070-DM-005-consolidation-worker-stub/README.md +11 -0
- package/patch/070-DM-005-consolidation-worker-stub/fix.py +46 -0
- package/patch/070-DM-005-consolidation-worker-stub/sentinel +1 -0
- package/patch/080-EM-001-embedding-ignores-config/README.md +11 -0
- package/patch/080-EM-001-embedding-ignores-config/fix.py +111 -0
- package/patch/080-EM-001-embedding-ignores-config/sentinel +1 -0
- package/patch/090-EM-002-transformers-cache-eacces/README.md +11 -0
- package/patch/090-EM-002-transformers-cache-eacces/fix.sh +12 -0
- package/patch/090-EM-002-transformers-cache-eacces/sentinel +1 -0
- package/patch/100-GV-001-hnsw-ghost-vectors/README.md +11 -0
- package/patch/100-GV-001-hnsw-ghost-vectors/fix.py +34 -0
- package/patch/100-GV-001-hnsw-ghost-vectors/sentinel +1 -0
- package/patch/110-HK-001-post-edit-file-path/README.md +44 -0
- package/patch/110-HK-001-post-edit-file-path/fix.py +23 -0
- package/patch/110-HK-001-post-edit-file-path/sentinel +1 -0
- package/patch/120-HK-002-hooks-tools-stub/README.md +36 -0
- package/patch/120-HK-002-hooks-tools-stub/fix.py +155 -0
- package/patch/120-HK-002-hooks-tools-stub/sentinel +1 -0
- package/patch/130-HK-003-metrics-hardcoded/README.md +30 -0
- package/patch/130-HK-003-metrics-hardcoded/fix.py +82 -0
- package/patch/130-HK-003-metrics-hardcoded/sentinel +1 -0
- package/patch/135-HK-004-respect-daemon-autostart/README.md +11 -0
- package/patch/135-HK-004-respect-daemon-autostart/fix.py +14 -0
- package/patch/135-HK-004-respect-daemon-autostart/sentinel +1 -0
- package/patch/137-HK-005-daemon-pid-guard/README.md +11 -0
- package/patch/137-HK-005-daemon-pid-guard/fix.py +53 -0
- package/patch/137-HK-005-daemon-pid-guard/sentinel +2 -0
- package/patch/140-HW-001-stdin-hang/README.md +11 -0
- package/patch/140-HW-001-stdin-hang/fix.py +6 -0
- package/patch/140-HW-001-stdin-hang/sentinel +1 -0
- package/patch/150-HW-002-failures-swallowed/README.md +11 -0
- package/patch/150-HW-002-failures-swallowed/fix.py +42 -0
- package/patch/150-HW-002-failures-swallowed/sentinel +1 -0
- package/patch/160-HW-003-aggressive-intervals/README.md +11 -0
- package/patch/160-HW-003-aggressive-intervals/fix.py +52 -0
- package/patch/160-HW-003-aggressive-intervals/sentinel +3 -0
- package/patch/170-IN-001-intelligence-stub/README.md +64 -0
- package/patch/170-IN-001-intelligence-stub/fix.py +63 -0
- package/patch/170-IN-001-intelligence-stub/sentinel +1 -0
- package/patch/180-MM-001-memory-persist-path/README.md +27 -0
- package/patch/180-MM-001-memory-persist-path/fix.py +54 -0
- package/patch/180-MM-001-memory-persist-path/sentinel +1 -0
- package/patch/190-NS-001-discovery-default-namespace/README.md +16 -0
- package/patch/190-NS-001-discovery-default-namespace/fix.py +68 -0
- package/patch/190-NS-001-discovery-default-namespace/sentinel +2 -0
- package/patch/200-NS-002-targeted-require-namespace/README.md +19 -0
- package/patch/200-NS-002-targeted-require-namespace/fix.py +158 -0
- package/patch/200-NS-002-targeted-require-namespace/sentinel +2 -0
- package/patch/210-NS-003-namespace-typo-pattern/README.md +15 -0
- package/patch/210-NS-003-namespace-typo-pattern/fix.py +23 -0
- package/patch/210-NS-003-namespace-typo-pattern/sentinel +1 -0
- package/patch/220-RS-001-better-sqlite3-node24/README.md +54 -0
- package/patch/220-RS-001-better-sqlite3-node24/fix.py +27 -0
- package/patch/220-RS-001-better-sqlite3-node24/rebuild.sh +31 -0
- package/patch/220-RS-001-better-sqlite3-node24/sentinel +2 -0
- package/patch/230-RV-001-force-learn-tick/README.md +31 -0
- package/patch/230-RV-001-force-learn-tick/fix.py +14 -0
- package/patch/230-RV-001-force-learn-tick/sentinel +2 -0
- package/patch/240-RV-002-trajectory-load/README.md +28 -0
- package/patch/240-RV-002-trajectory-load/fix.py +14 -0
- package/patch/240-RV-002-trajectory-load/sentinel +2 -0
- package/patch/250-RV-003-trajectory-stats-sync/README.md +31 -0
- package/patch/250-RV-003-trajectory-stats-sync/fix.py +18 -0
- package/patch/250-RV-003-trajectory-stats-sync/sentinel +2 -0
- package/patch/260-SG-001-init-settings/README.md +29 -0
- package/patch/260-SG-001-init-settings/fix.py +143 -0
- package/patch/260-SG-001-init-settings/sentinel +4 -0
- package/patch/270-SG-003-init-helpers-all-paths/README.md +60 -0
- package/patch/270-SG-003-init-helpers-all-paths/fix.py +165 -0
- package/patch/270-SG-003-init-helpers-all-paths/sentinel +3 -0
- package/patch/280-UI-001-intelligence-stats-crash/README.md +11 -0
- package/patch/280-UI-001-intelligence-stats-crash/fix.py +57 -0
- package/patch/280-UI-001-intelligence-stats-crash/sentinel +1 -0
- package/patch/290-UI-002-neural-status-not-loaded/README.md +11 -0
- package/patch/290-UI-002-neural-status-not-loaded/fix.py +19 -0
- package/patch/290-UI-002-neural-status-not-loaded/sentinel +1 -0
- package/patch/300-DM-006-log-rotation/README.md +12 -0
- package/patch/300-DM-006-log-rotation/fix.py +72 -0
- package/patch/300-DM-006-log-rotation/sentinel +2 -0
- package/patch/310-HW-004-runwithtimeout-orphan/README.md +11 -0
- package/patch/310-HW-004-runwithtimeout-orphan/fix.py +10 -0
- package/patch/310-HW-004-runwithtimeout-orphan/sentinel +1 -0
- package/patch/320-SG-004-wizard-parity/README.md +40 -0
- package/patch/320-SG-004-wizard-parity/fix.py +208 -0
- package/patch/320-SG-004-wizard-parity/sentinel +3 -0
- package/patch/330-SG-005-start-all-subcommand/README.md +32 -0
- package/patch/330-SG-005-start-all-subcommand/fix.py +58 -0
- package/patch/330-SG-005-start-all-subcommand/sentinel +1 -0
- package/patch-all.sh +199 -0
- package/repair-post-init.sh +263 -0
- package/scripts/preflight.mjs +249 -0
- package/scripts/upstream-log.mjs +257 -0
package/patch-all.sh
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# patch-all.sh — Orchestrator for folder-per-defect patches
|
|
3
|
+
# Safe to run multiple times. Each fix.py is idempotent via patch()/patch_all().
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# bash patch-all.sh [--global] [--target <dir>]
|
|
7
|
+
#
|
|
8
|
+
# Options:
|
|
9
|
+
# --global Patch all global installs (npx cache + npm global)
|
|
10
|
+
# --target <dir> Patch node_modules inside <dir>
|
|
11
|
+
#
|
|
12
|
+
# If neither flag is given, --global is assumed.
|
|
13
|
+
|
|
14
|
+
set -euo pipefail
|
|
15
|
+
|
|
16
|
+
# Parse arguments
|
|
17
|
+
DO_GLOBAL=0
|
|
18
|
+
TARGET_DIR=""
|
|
19
|
+
while [[ $# -gt 0 ]]; do
|
|
20
|
+
case $1 in
|
|
21
|
+
--global)
|
|
22
|
+
DO_GLOBAL=1
|
|
23
|
+
shift
|
|
24
|
+
;;
|
|
25
|
+
--target)
|
|
26
|
+
TARGET_DIR="${2:-}"
|
|
27
|
+
if [[ -z "$TARGET_DIR" ]]; then
|
|
28
|
+
echo "Error: --target requires a directory argument"
|
|
29
|
+
exit 1
|
|
30
|
+
fi
|
|
31
|
+
shift 2
|
|
32
|
+
;;
|
|
33
|
+
-h|--help)
|
|
34
|
+
echo "Usage: patch-all.sh [--global] [--target <dir>]"
|
|
35
|
+
echo ""
|
|
36
|
+
echo "Options:"
|
|
37
|
+
echo " --global Patch all global installs (npx cache + npm global)"
|
|
38
|
+
echo " --target <dir> Patch node_modules inside <dir>"
|
|
39
|
+
echo ""
|
|
40
|
+
echo "If neither flag is given, --global is assumed."
|
|
41
|
+
exit 0
|
|
42
|
+
;;
|
|
43
|
+
*)
|
|
44
|
+
echo "Unknown option: $1"
|
|
45
|
+
exit 1
|
|
46
|
+
;;
|
|
47
|
+
esac
|
|
48
|
+
done
|
|
49
|
+
|
|
50
|
+
# Default: --global when nothing specified
|
|
51
|
+
if [[ $DO_GLOBAL -eq 0 && -z "$TARGET_DIR" ]]; then
|
|
52
|
+
DO_GLOBAL=1
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
56
|
+
|
|
57
|
+
# ── Shared discovery ──
|
|
58
|
+
. "$SCRIPT_DIR/lib/discover.sh"
|
|
59
|
+
|
|
60
|
+
# ── Collect installs ──
|
|
61
|
+
# Each entry: "SCOPE\tdist_src\tversion\truvector_cli\truv_swarm_root\twritable"
|
|
62
|
+
|
|
63
|
+
INSTALLS=()
|
|
64
|
+
|
|
65
|
+
if [[ $DO_GLOBAL -eq 1 ]]; then
|
|
66
|
+
while IFS= read -r line; do
|
|
67
|
+
[ -n "$line" ] && INSTALLS+=("GLOBAL $line")
|
|
68
|
+
done < <(discover_all_cf_installs)
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
if [[ -n "$TARGET_DIR" ]]; then
|
|
72
|
+
if [[ ! -d "$TARGET_DIR" ]]; then
|
|
73
|
+
echo "Error: target directory does not exist: $TARGET_DIR"
|
|
74
|
+
exit 1
|
|
75
|
+
fi
|
|
76
|
+
TARGET_DIR="$(cd "$TARGET_DIR" && pwd)"
|
|
77
|
+
while IFS= read -r line; do
|
|
78
|
+
[ -n "$line" ] && INSTALLS+=("TARGET $line")
|
|
79
|
+
done < <(discover_target_installs "$TARGET_DIR")
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
# ── Report what we found ──
|
|
83
|
+
|
|
84
|
+
TARGETS=()
|
|
85
|
+
if [[ $DO_GLOBAL -eq 1 ]]; then TARGETS+=(global); fi
|
|
86
|
+
if [[ -n "$TARGET_DIR" ]]; then TARGETS+=("$TARGET_DIR"); fi
|
|
87
|
+
echo "[PATCHES] Targets: ${TARGETS[*]}"
|
|
88
|
+
echo ""
|
|
89
|
+
|
|
90
|
+
if [[ ${#INSTALLS[@]} -eq 0 ]]; then
|
|
91
|
+
if [[ $DO_GLOBAL -eq 1 ]]; then
|
|
92
|
+
echo " Global @claude-flow/cli: not found"
|
|
93
|
+
echo " Global ruvector: not found"
|
|
94
|
+
fi
|
|
95
|
+
if [[ -n "$TARGET_DIR" ]]; then
|
|
96
|
+
echo " Target @claude-flow/cli: not found in $TARGET_DIR"
|
|
97
|
+
echo " Target ruvector: not found in $TARGET_DIR"
|
|
98
|
+
fi
|
|
99
|
+
echo ""
|
|
100
|
+
echo "[PATCHES] Complete"
|
|
101
|
+
exit 0
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
for entry in "${INSTALLS[@]}"; do
|
|
105
|
+
IFS=$'\t' read -r scope dist_src version rv_cli rs_root writable <<< "$entry"
|
|
106
|
+
# "-" is the placeholder for empty fields (bash IFS collapses consecutive tabs)
|
|
107
|
+
[ "$rv_cli" = "-" ] && rv_cli=""
|
|
108
|
+
[ "$rs_root" = "-" ] && rs_root=""
|
|
109
|
+
echo " [$scope] @claude-flow/cli v$version at $dist_src"
|
|
110
|
+
[ -n "$rv_cli" ] && echo " [$scope] ruvector: $rv_cli"
|
|
111
|
+
[ -n "$rs_root" ] && echo " [$scope] ruv-swarm: $rs_root"
|
|
112
|
+
if [ "$writable" = "no" ]; then
|
|
113
|
+
echo " [$scope] WARNING: not writable (re-run with sudo)"
|
|
114
|
+
fi
|
|
115
|
+
done
|
|
116
|
+
|
|
117
|
+
echo ""
|
|
118
|
+
|
|
119
|
+
# ── Apply patches function ──
|
|
120
|
+
|
|
121
|
+
apply_patches() {
|
|
122
|
+
local base="$1"
|
|
123
|
+
local ruvector_cli="$2"
|
|
124
|
+
local ruv_swarm_root="$3"
|
|
125
|
+
local label="$4"
|
|
126
|
+
|
|
127
|
+
if [ -z "$base" ] && [ -z "$ruvector_cli" ]; then
|
|
128
|
+
echo "[$label] No packages found, skipping"
|
|
129
|
+
return
|
|
130
|
+
fi
|
|
131
|
+
|
|
132
|
+
if [ -n "$base" ]; then
|
|
133
|
+
echo "[$label] Patching @claude-flow/cli at: $base"
|
|
134
|
+
fi
|
|
135
|
+
if [ -n "$ruvector_cli" ]; then
|
|
136
|
+
echo "[$label] Patching ruvector at: $ruvector_cli"
|
|
137
|
+
fi
|
|
138
|
+
|
|
139
|
+
export BASE="${base:-/dev/null}"
|
|
140
|
+
export RUVECTOR_CLI="$ruvector_cli"
|
|
141
|
+
export RUV_SWARM_ROOT="$ruv_swarm_root"
|
|
142
|
+
|
|
143
|
+
# Dynamic discovery: concatenate common.py + all fix.py files sorted alphabetically.
|
|
144
|
+
# Alphabetical order preserves dependencies (e.g. NS-001 < NS-002 < NS-003).
|
|
145
|
+
#
|
|
146
|
+
# PATCH_INCLUDE / PATCH_EXCLUDE env vars filter by directory name regex.
|
|
147
|
+
python3 <(
|
|
148
|
+
cat "$SCRIPT_DIR/lib/common.py"
|
|
149
|
+
|
|
150
|
+
for fix in "$SCRIPT_DIR"/patch/*/fix.py; do
|
|
151
|
+
[ -f "$fix" ] || continue
|
|
152
|
+
dirname=$(basename "$(dirname "$fix")")
|
|
153
|
+
matchname="${dirname#[0-9][0-9][0-9]-}" # strip NNN- prefix for pattern matching
|
|
154
|
+
if [ -n "${PATCH_INCLUDE:-}" ] && ! echo "$matchname" | grep -qE "$PATCH_INCLUDE"; then
|
|
155
|
+
continue
|
|
156
|
+
fi
|
|
157
|
+
if [ -n "${PATCH_EXCLUDE:-}" ] && echo "$matchname" | grep -qE "$PATCH_EXCLUDE"; then
|
|
158
|
+
continue
|
|
159
|
+
fi
|
|
160
|
+
cat "$fix"
|
|
161
|
+
done
|
|
162
|
+
|
|
163
|
+
echo "print(f\"[$label] Done: {applied} applied, {skipped} already present\")"
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
# Shell-based patches (e.g. EM-002: transformers cache permissions)
|
|
167
|
+
for fix in "$SCRIPT_DIR"/patch/*/fix.sh; do
|
|
168
|
+
[ -f "$fix" ] || continue
|
|
169
|
+
dirname=$(basename "$(dirname "$fix")")
|
|
170
|
+
matchname="${dirname#[0-9][0-9][0-9]-}" # strip NNN- prefix for pattern matching
|
|
171
|
+
if [ -n "${PATCH_INCLUDE:-}" ] && ! echo "$matchname" | grep -qE "$PATCH_INCLUDE"; then
|
|
172
|
+
continue
|
|
173
|
+
fi
|
|
174
|
+
if [ -n "${PATCH_EXCLUDE:-}" ] && echo "$matchname" | grep -qE "$PATCH_EXCLUDE"; then
|
|
175
|
+
continue
|
|
176
|
+
fi
|
|
177
|
+
bash "$fix" 2>/dev/null || true
|
|
178
|
+
done
|
|
179
|
+
|
|
180
|
+
echo ""
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
# ── Apply to each discovered install ──
|
|
184
|
+
|
|
185
|
+
for entry in "${INSTALLS[@]}"; do
|
|
186
|
+
IFS=$'\t' read -r scope dist_src version rv_cli rs_root writable <<< "$entry"
|
|
187
|
+
[ "$rv_cli" = "-" ] && rv_cli=""
|
|
188
|
+
[ "$rs_root" = "-" ] && rs_root=""
|
|
189
|
+
|
|
190
|
+
if [ "$writable" = "no" ]; then
|
|
191
|
+
echo "[$scope] SKIP: $dist_src not writable (re-run with sudo)"
|
|
192
|
+
echo ""
|
|
193
|
+
continue
|
|
194
|
+
fi
|
|
195
|
+
|
|
196
|
+
apply_patches "$dist_src" "$rv_cli" "$rs_root" "$scope"
|
|
197
|
+
done
|
|
198
|
+
|
|
199
|
+
echo "[PATCHES] Complete"
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# repair-post-init.sh
|
|
3
|
+
# Post-init remediation for projects initialized before patch-all.sh.
|
|
4
|
+
#
|
|
5
|
+
# What it does:
|
|
6
|
+
# 1) Finds a patched @claude-flow/cli helper source (local or global npx cache)
|
|
7
|
+
# 2) Backs up target .claude/helpers (default)
|
|
8
|
+
# 3) Rehydrates helper files into target project
|
|
9
|
+
# 4) Preserves/installs a guidance-aware hook-handler when available
|
|
10
|
+
|
|
11
|
+
set -euo pipefail
|
|
12
|
+
|
|
13
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
14
|
+
TARGET_DIR="$(pwd)"
|
|
15
|
+
SOURCE_SCOPE="auto" # auto|local|global
|
|
16
|
+
DO_BACKUP=1
|
|
17
|
+
DRY_RUN=0
|
|
18
|
+
RUN_CHECK=1
|
|
19
|
+
|
|
20
|
+
usage() {
|
|
21
|
+
cat <<'EOF'
|
|
22
|
+
Usage:
|
|
23
|
+
bash repair-post-init.sh [options]
|
|
24
|
+
|
|
25
|
+
Options:
|
|
26
|
+
--target <dir> Target project directory (default: current working directory)
|
|
27
|
+
--source <mode> Source mode: auto|local|global (default: auto)
|
|
28
|
+
--no-backup Skip .claude/helpers backup
|
|
29
|
+
--dry-run Print actions without writing files
|
|
30
|
+
--skip-check Skip check-patches.sh preflight
|
|
31
|
+
-h, --help Show help
|
|
32
|
+
|
|
33
|
+
Examples:
|
|
34
|
+
bash repair-post-init.sh --target ~/src/my-project
|
|
35
|
+
bash repair-post-init.sh --target ~/src/my-project --source global
|
|
36
|
+
bash repair-post-init.sh --target ~/src/my-project --dry-run
|
|
37
|
+
EOF
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
fail() {
|
|
41
|
+
echo "[repair-post-init] ERROR: $*" >&2
|
|
42
|
+
exit 1
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
log() {
|
|
46
|
+
echo "[repair-post-init] $*"
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
run_cmd() {
|
|
50
|
+
if [ "$DRY_RUN" -eq 1 ]; then
|
|
51
|
+
echo "[dry-run] $*"
|
|
52
|
+
return 0
|
|
53
|
+
fi
|
|
54
|
+
"$@"
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
while [[ $# -gt 0 ]]; do
|
|
58
|
+
case "$1" in
|
|
59
|
+
--target)
|
|
60
|
+
TARGET_DIR="${2:-}"
|
|
61
|
+
shift 2
|
|
62
|
+
;;
|
|
63
|
+
--source)
|
|
64
|
+
SOURCE_SCOPE="${2:-}"
|
|
65
|
+
shift 2
|
|
66
|
+
;;
|
|
67
|
+
--no-backup)
|
|
68
|
+
DO_BACKUP=0
|
|
69
|
+
shift
|
|
70
|
+
;;
|
|
71
|
+
--dry-run)
|
|
72
|
+
DRY_RUN=1
|
|
73
|
+
shift
|
|
74
|
+
;;
|
|
75
|
+
--skip-check)
|
|
76
|
+
RUN_CHECK=0
|
|
77
|
+
shift
|
|
78
|
+
;;
|
|
79
|
+
-h|--help)
|
|
80
|
+
usage
|
|
81
|
+
exit 0
|
|
82
|
+
;;
|
|
83
|
+
*)
|
|
84
|
+
fail "Unknown option: $1"
|
|
85
|
+
;;
|
|
86
|
+
esac
|
|
87
|
+
done
|
|
88
|
+
|
|
89
|
+
if [[ ! "$SOURCE_SCOPE" =~ ^(auto|local|global)$ ]]; then
|
|
90
|
+
fail "Invalid --source value: $SOURCE_SCOPE (expected auto|local|global)"
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
TARGET_DIR="$(cd "$TARGET_DIR" && pwd)"
|
|
94
|
+
[ -d "$TARGET_DIR" ] || fail "Target directory not found: $TARGET_DIR"
|
|
95
|
+
|
|
96
|
+
if [ "$RUN_CHECK" -eq 1 ]; then
|
|
97
|
+
if [ -x "$SCRIPT_DIR/check-patches.sh" ]; then
|
|
98
|
+
log "Running preflight patch check..."
|
|
99
|
+
bash "$SCRIPT_DIR/check-patches.sh" >/dev/null || {
|
|
100
|
+
log "Patch check failed; applying patches..."
|
|
101
|
+
bash "$SCRIPT_DIR/patch-all.sh" --global >/dev/null
|
|
102
|
+
bash "$SCRIPT_DIR/check-patches.sh" >/dev/null || fail "Patch verification failed"
|
|
103
|
+
}
|
|
104
|
+
else
|
|
105
|
+
log "check-patches.sh not found; skipping preflight"
|
|
106
|
+
fi
|
|
107
|
+
fi
|
|
108
|
+
|
|
109
|
+
find_local_helpers() {
|
|
110
|
+
local base="$1"
|
|
111
|
+
for d in "$base" "$base/.." "$base/../.." "$base/../../.."; do
|
|
112
|
+
if [ -d "$d/node_modules/@claude-flow/cli/.claude/helpers" ]; then
|
|
113
|
+
(cd "$d/node_modules/@claude-flow/cli/.claude/helpers" && pwd)
|
|
114
|
+
return 0
|
|
115
|
+
fi
|
|
116
|
+
done
|
|
117
|
+
return 1
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
find_global_helpers() {
|
|
121
|
+
# Use shared discovery to find all installs, then derive helpers path
|
|
122
|
+
. "$SCRIPT_DIR/lib/discover.sh"
|
|
123
|
+
local first_dist_src=""
|
|
124
|
+
while IFS= read -r line; do
|
|
125
|
+
[ -n "$line" ] || continue
|
|
126
|
+
first_dist_src="${line%% *}"
|
|
127
|
+
break
|
|
128
|
+
done < <(discover_all_cf_installs)
|
|
129
|
+
if [ -n "$first_dist_src" ]; then
|
|
130
|
+
# dist/src -> package root -> .claude/helpers
|
|
131
|
+
local pkg_root
|
|
132
|
+
pkg_root="$(cd "$first_dist_src/../.." 2>/dev/null && pwd)"
|
|
133
|
+
if [ -d "$pkg_root/.claude/helpers" ]; then
|
|
134
|
+
echo "$pkg_root/.claude/helpers"
|
|
135
|
+
return 0
|
|
136
|
+
fi
|
|
137
|
+
fi
|
|
138
|
+
# Fallback: legacy direct glob
|
|
139
|
+
ls -td ~/.npm/_npx/*/node_modules/@claude-flow/cli/.claude/helpers 2>/dev/null | head -1 || true
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
SRC_HELPERS=""
|
|
143
|
+
case "$SOURCE_SCOPE" in
|
|
144
|
+
local)
|
|
145
|
+
SRC_HELPERS="$(find_local_helpers "$TARGET_DIR" || true)"
|
|
146
|
+
;;
|
|
147
|
+
global)
|
|
148
|
+
SRC_HELPERS="$(find_global_helpers)"
|
|
149
|
+
;;
|
|
150
|
+
auto)
|
|
151
|
+
SRC_HELPERS="$(find_local_helpers "$TARGET_DIR" || true)"
|
|
152
|
+
if [ -z "$SRC_HELPERS" ]; then
|
|
153
|
+
SRC_HELPERS="$(find_global_helpers)"
|
|
154
|
+
fi
|
|
155
|
+
;;
|
|
156
|
+
esac
|
|
157
|
+
|
|
158
|
+
[ -n "$SRC_HELPERS" ] || fail "Could not locate @claude-flow/cli/.claude/helpers (source=$SOURCE_SCOPE)"
|
|
159
|
+
[ -d "$SRC_HELPERS" ] || fail "Source helpers directory does not exist: $SRC_HELPERS"
|
|
160
|
+
[ -f "$SRC_HELPERS/intelligence.cjs" ] || fail "Source missing intelligence.cjs: $SRC_HELPERS"
|
|
161
|
+
|
|
162
|
+
TARGET_HELPERS="$TARGET_DIR/.claude/helpers"
|
|
163
|
+
BACKUP_PATH="$TARGET_DIR/.claude/helpers.backup.$(date +%Y%m%d-%H%M%S)"
|
|
164
|
+
|
|
165
|
+
log "Target: $TARGET_DIR"
|
|
166
|
+
log "Source helpers: $SRC_HELPERS"
|
|
167
|
+
log "Target helpers: $TARGET_HELPERS"
|
|
168
|
+
|
|
169
|
+
run_cmd mkdir -p "$TARGET_HELPERS"
|
|
170
|
+
|
|
171
|
+
if [ "$DO_BACKUP" -eq 1 ] && [ -d "$TARGET_HELPERS" ]; then
|
|
172
|
+
if [ "$(ls -A "$TARGET_HELPERS" 2>/dev/null || true)" ]; then
|
|
173
|
+
log "Backing up existing helpers -> $BACKUP_PATH"
|
|
174
|
+
run_cmd cp -a "$TARGET_HELPERS" "$BACKUP_PATH"
|
|
175
|
+
fi
|
|
176
|
+
fi
|
|
177
|
+
|
|
178
|
+
# Copy all helpers except hook-handler.cjs first.
|
|
179
|
+
copied=0
|
|
180
|
+
for src in "$SRC_HELPERS"/*; do
|
|
181
|
+
[ -e "$src" ] || continue
|
|
182
|
+
base="$(basename "$src")"
|
|
183
|
+
if [ "$base" = "hook-handler.cjs" ]; then
|
|
184
|
+
continue
|
|
185
|
+
fi
|
|
186
|
+
run_cmd cp -a "$src" "$TARGET_HELPERS/$base"
|
|
187
|
+
copied=$((copied + 1))
|
|
188
|
+
done
|
|
189
|
+
|
|
190
|
+
# Prefer guidance-aware hook-handler when installed in target project.
|
|
191
|
+
GUIDANCE_HANDLER="$TARGET_DIR/node_modules/claude-flow-guidance-implementation/scaffold/.claude/helpers/hook-handler.cjs"
|
|
192
|
+
HOOK_SRC="$SRC_HELPERS/hook-handler.cjs"
|
|
193
|
+
HOOK_REASON="@claude-flow/cli helper template"
|
|
194
|
+
if [ -f "$GUIDANCE_HANDLER" ]; then
|
|
195
|
+
HOOK_SRC="$GUIDANCE_HANDLER"
|
|
196
|
+
HOOK_REASON="guidance implementation hook-handler"
|
|
197
|
+
fi
|
|
198
|
+
|
|
199
|
+
if [ -f "$HOOK_SRC" ]; then
|
|
200
|
+
log "Installing hook-handler from: $HOOK_REASON"
|
|
201
|
+
run_cmd cp -a "$HOOK_SRC" "$TARGET_HELPERS/hook-handler.cjs"
|
|
202
|
+
copied=$((copied + 1))
|
|
203
|
+
fi
|
|
204
|
+
|
|
205
|
+
# Make guidance hook-handler path resolution work when copied into project .claude/helpers.
|
|
206
|
+
if [ "$DRY_RUN" -eq 0 ] && [ -f "$TARGET_HELPERS/hook-handler.cjs" ]; then
|
|
207
|
+
python3 - "$TARGET_HELPERS/hook-handler.cjs" <<'PY'
|
|
208
|
+
import pathlib
|
|
209
|
+
import sys
|
|
210
|
+
|
|
211
|
+
path = pathlib.Path(sys.argv[1])
|
|
212
|
+
text = path.read_text()
|
|
213
|
+
|
|
214
|
+
start = text.find("function getBundledScriptPath(scriptName)")
|
|
215
|
+
end = text.find("function getGuidanceScriptPath()", start if start >= 0 else 0)
|
|
216
|
+
|
|
217
|
+
if start >= 0 and end > start and "claude-flow-guidance-implementation" not in text:
|
|
218
|
+
replacement = """function getBundledScriptPath(scriptName) {
|
|
219
|
+
return path.join(
|
|
220
|
+
getProjectDir(),
|
|
221
|
+
'node_modules',
|
|
222
|
+
'claude-flow-guidance-implementation',
|
|
223
|
+
'scaffold',
|
|
224
|
+
'scripts',
|
|
225
|
+
scriptName
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function resolveGuidanceScriptPath(scriptName) {
|
|
230
|
+
const localPath = path.join(getProjectDir(), 'scripts', scriptName);
|
|
231
|
+
if (fs.existsSync(localPath)) return localPath;
|
|
232
|
+
|
|
233
|
+
const bundledPath = getBundledScriptPath(scriptName);
|
|
234
|
+
if (fs.existsSync(bundledPath)) return bundledPath;
|
|
235
|
+
|
|
236
|
+
// Keep compatibility for handler copies that live under scaffold/.claude/helpers.
|
|
237
|
+
const relativeBundledPath = path.resolve(__dirname, '..', '..', 'scripts', scriptName);
|
|
238
|
+
if (fs.existsSync(relativeBundledPath)) return relativeBundledPath;
|
|
239
|
+
|
|
240
|
+
return localPath;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
"""
|
|
244
|
+
text = text[:start] + replacement + text[end:]
|
|
245
|
+
path.write_text(text)
|
|
246
|
+
PY
|
|
247
|
+
fi
|
|
248
|
+
|
|
249
|
+
if [ "$DRY_RUN" -eq 0 ] && [ -f "$TARGET_HELPERS/hook-handler.cjs" ]; then
|
|
250
|
+
chmod +x "$TARGET_HELPERS/hook-handler.cjs" || true
|
|
251
|
+
fi
|
|
252
|
+
|
|
253
|
+
log "Copied/updated helper files: $copied"
|
|
254
|
+
|
|
255
|
+
if [ "$DRY_RUN" -eq 0 ] && [ -f "$TARGET_HELPERS/hook-handler.cjs" ]; then
|
|
256
|
+
if node "$TARGET_HELPERS/hook-handler.cjs" status >/dev/null 2>&1; then
|
|
257
|
+
log "Smoke check: hook-handler status OK"
|
|
258
|
+
else
|
|
259
|
+
log "WARN: hook-handler status returned non-zero"
|
|
260
|
+
fi
|
|
261
|
+
fi
|
|
262
|
+
|
|
263
|
+
log "Done."
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// scripts/preflight.mjs — Pre-commit/pre-publish consistency check.
|
|
3
|
+
// Syncs: doc tables, defect counts, version strings across all files.
|
|
4
|
+
// Source of truth: package.json (version), npm/config.json (targets), patch/*/ (defects).
|
|
5
|
+
//
|
|
6
|
+
// Usage: node scripts/preflight.mjs [--check]
|
|
7
|
+
// --check Exit 1 if anything is out of date (for hooks/CI), don't write.
|
|
8
|
+
|
|
9
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
10
|
+
import { resolve, dirname } from 'node:path';
|
|
11
|
+
import { fileURLToPath } from 'node:url';
|
|
12
|
+
import { discover } from '../lib/discover.mjs';
|
|
13
|
+
|
|
14
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
const ROOT = resolve(__dirname, '..');
|
|
16
|
+
const checkOnly = process.argv.includes('--check');
|
|
17
|
+
|
|
18
|
+
const data = discover();
|
|
19
|
+
const { patches, categories, stats } = data;
|
|
20
|
+
|
|
21
|
+
// ── Sources of truth ──
|
|
22
|
+
|
|
23
|
+
const pkgJson = JSON.parse(readFileSync(resolve(ROOT, 'package.json'), 'utf-8'));
|
|
24
|
+
const configJson = JSON.parse(readFileSync(resolve(ROOT, 'npm', 'config.json'), 'utf-8'));
|
|
25
|
+
const pkgVersion = pkgJson.version;
|
|
26
|
+
const cliTarget = configJson.targets['@claude-flow/cli'];
|
|
27
|
+
const swarmTarget = configJson.targets['ruv-swarm'];
|
|
28
|
+
|
|
29
|
+
// ── Helpers ──
|
|
30
|
+
|
|
31
|
+
/** Group patches by prefix, preserving sort order. */
|
|
32
|
+
function groupByPrefix(patches) {
|
|
33
|
+
const groups = new Map();
|
|
34
|
+
for (const p of patches) {
|
|
35
|
+
if (!groups.has(p.prefix)) groups.set(p.prefix, []);
|
|
36
|
+
groups.get(p.prefix).push(p);
|
|
37
|
+
}
|
|
38
|
+
return groups;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Replace content between marker comments in a file.
|
|
43
|
+
* Returns true if content changed.
|
|
44
|
+
*/
|
|
45
|
+
function replaceMarkerSection(filePath, markerName, newContent) {
|
|
46
|
+
const beginMarker = `<!-- GENERATED:${markerName}:begin -->`;
|
|
47
|
+
const endMarker = `<!-- GENERATED:${markerName}:end -->`;
|
|
48
|
+
|
|
49
|
+
const text = readFileSync(filePath, 'utf-8');
|
|
50
|
+
const beginIdx = text.indexOf(beginMarker);
|
|
51
|
+
const endIdx = text.indexOf(endMarker);
|
|
52
|
+
|
|
53
|
+
if (beginIdx < 0 || endIdx < 0) {
|
|
54
|
+
console.error(`ERROR: Markers ${beginMarker} / ${endMarker} not found in ${filePath}`);
|
|
55
|
+
console.error(' Add them around the section that should be auto-generated.');
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const before = text.slice(0, beginIdx + beginMarker.length);
|
|
60
|
+
const after = text.slice(endIdx);
|
|
61
|
+
const updated = `${before}\n${newContent}\n${after}`;
|
|
62
|
+
|
|
63
|
+
if (updated === text) return false;
|
|
64
|
+
|
|
65
|
+
if (!checkOnly) writeFileSync(filePath, updated);
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Replace all occurrences of a version string in a file.
|
|
71
|
+
* Returns true if content changed.
|
|
72
|
+
*/
|
|
73
|
+
function syncVersionInFile(filePath, oldVersion, newVersion, label) {
|
|
74
|
+
if (oldVersion === newVersion) return false;
|
|
75
|
+
const text = readFileSync(filePath, 'utf-8');
|
|
76
|
+
if (!text.includes(oldVersion)) return false;
|
|
77
|
+
const updated = text.replaceAll(oldVersion, newVersion);
|
|
78
|
+
if (updated === text) return false;
|
|
79
|
+
if (!checkOnly) writeFileSync(filePath, updated);
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// ── Generate README.md defect index ──
|
|
84
|
+
|
|
85
|
+
function generateReadmeIndex() {
|
|
86
|
+
const groups = groupByPrefix(patches);
|
|
87
|
+
const lines = [`${stats.total} defects across ${stats.categories} categories.`];
|
|
88
|
+
|
|
89
|
+
for (const [prefix, items] of groups) {
|
|
90
|
+
const catLabel = categories[prefix] ?? prefix;
|
|
91
|
+
lines.push('');
|
|
92
|
+
lines.push(`### ${prefix} -- ${catLabel}`);
|
|
93
|
+
lines.push('');
|
|
94
|
+
lines.push('| ID | Description <img width="500" height="1" /> | Severity | GitHub Issue |');
|
|
95
|
+
lines.push('|----|-------------|----------|--------------|');
|
|
96
|
+
|
|
97
|
+
for (const p of items) {
|
|
98
|
+
const idLink = `[${p.id.replace('-', '‑')}](patch/${p.dir}/)`;
|
|
99
|
+
const ghLink = p.githubUrl ? `[${p.github}](${p.githubUrl})` : p.github;
|
|
100
|
+
lines.push(`| ${idLink} | ${p.title} | ${p.severity} | ${ghLink} |`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return lines.join('\n');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// ── Generate CLAUDE.md defect tables ──
|
|
108
|
+
|
|
109
|
+
function generateClaudeTables() {
|
|
110
|
+
const groups = groupByPrefix(patches);
|
|
111
|
+
const lines = [];
|
|
112
|
+
|
|
113
|
+
// Category summary table
|
|
114
|
+
lines.push('| Prefix | Category | Count |');
|
|
115
|
+
lines.push('|--------|----------|-------|');
|
|
116
|
+
for (const [prefix, items] of groups) {
|
|
117
|
+
const catLabel = categories[prefix] ?? prefix;
|
|
118
|
+
lines.push(`| ${prefix} | ${catLabel} | ${items.length} |`);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Full defect list
|
|
122
|
+
lines.push('');
|
|
123
|
+
lines.push(`## All ${stats.total} Defects`);
|
|
124
|
+
lines.push('');
|
|
125
|
+
lines.push('| ID | GitHub Issue | Severity |');
|
|
126
|
+
lines.push('|----|-------------|----------|');
|
|
127
|
+
for (const p of patches) {
|
|
128
|
+
const ghText = p.github ? `${p.github} ${p.title}` : p.title;
|
|
129
|
+
const ghLink = p.githubUrl ? `[${ghText}](${p.githubUrl})` : ghText;
|
|
130
|
+
lines.push(`| ${p.id} | ${ghLink} | ${p.severity} |`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return lines.join('\n');
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// ── Generate npm/README.md defect list ──
|
|
137
|
+
|
|
138
|
+
const REPO_URL = 'https://github.com/sparkling/claude-flow-patch';
|
|
139
|
+
|
|
140
|
+
function generateNpmDefectList() {
|
|
141
|
+
const groups = groupByPrefix(patches);
|
|
142
|
+
const lines = [
|
|
143
|
+
`${stats.total} tracked defects across ${stats.categories} categories.`,
|
|
144
|
+
'',
|
|
145
|
+
'| Defect | Description | GitHub Issue |',
|
|
146
|
+
'|--------|-------------|-------------|',
|
|
147
|
+
];
|
|
148
|
+
|
|
149
|
+
for (const [, items] of groups) {
|
|
150
|
+
for (const p of items) {
|
|
151
|
+
const defectLink = `[${p.id}](${REPO_URL}/tree/master/patch/${p.dir})`;
|
|
152
|
+
const ghLink = p.githubUrl ? `[${p.github}](${p.githubUrl})` : p.github;
|
|
153
|
+
lines.push(`| ${defectLink} | ${p.title} | ${ghLink} |`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return lines.join('\n');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function updateNpmReadme() {
|
|
161
|
+
return replaceMarkerSection(
|
|
162
|
+
resolve(ROOT, 'npm', 'README.md'),
|
|
163
|
+
'npm-defects',
|
|
164
|
+
generateNpmDefectList()
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// ── Sync npm/config.json (version + defect counts) ──
|
|
169
|
+
|
|
170
|
+
function updateNpmConfig() {
|
|
171
|
+
const filePath = resolve(ROOT, 'npm', 'config.json');
|
|
172
|
+
const config = JSON.parse(readFileSync(filePath, 'utf-8'));
|
|
173
|
+
|
|
174
|
+
let changed = false;
|
|
175
|
+
|
|
176
|
+
// Sync version.current from package.json
|
|
177
|
+
if (config.version?.current !== pkgVersion) {
|
|
178
|
+
config.version.current = pkgVersion;
|
|
179
|
+
changed = true;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Sync defect counts from discovery
|
|
183
|
+
if (config.defects?.total !== stats.total) {
|
|
184
|
+
config.defects.total = stats.total;
|
|
185
|
+
changed = true;
|
|
186
|
+
}
|
|
187
|
+
if (config.defects?.categories !== stats.categories) {
|
|
188
|
+
config.defects.categories = stats.categories;
|
|
189
|
+
changed = true;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (changed && !checkOnly) {
|
|
193
|
+
writeFileSync(filePath, JSON.stringify(config, null, 2) + '\n');
|
|
194
|
+
}
|
|
195
|
+
return changed;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// ── Main ──
|
|
199
|
+
|
|
200
|
+
let anyChanged = false;
|
|
201
|
+
|
|
202
|
+
function report(changed, label) {
|
|
203
|
+
if (!changed) return;
|
|
204
|
+
anyChanged = true;
|
|
205
|
+
console.log(checkOnly ? `STALE: ${label}` : `Updated: ${label}`);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// 1. Doc tables (marker-based sections)
|
|
209
|
+
report(
|
|
210
|
+
replaceMarkerSection(resolve(ROOT, 'README.md'), 'defect-index', generateReadmeIndex()),
|
|
211
|
+
'README.md (defect index)'
|
|
212
|
+
);
|
|
213
|
+
report(
|
|
214
|
+
replaceMarkerSection(resolve(ROOT, 'CLAUDE.md'), 'defect-tables', generateClaudeTables()),
|
|
215
|
+
'CLAUDE.md (defect tables)'
|
|
216
|
+
);
|
|
217
|
+
report(updateNpmReadme(), 'npm/README.md (defect list)');
|
|
218
|
+
|
|
219
|
+
// 2. Config sync (version + counts)
|
|
220
|
+
report(updateNpmConfig(), 'npm/config.json (version/counts)');
|
|
221
|
+
|
|
222
|
+
// 3. Upstream baseline version in prose (sync from npm/config.json targets)
|
|
223
|
+
// Find any stale version strings and replace with current targets.
|
|
224
|
+
// We scan for the pattern v?X.Y.Z-alpha.N and replace if it doesn't match config.
|
|
225
|
+
const versionFiles = ['README.md', 'CLAUDE.md', 'npm/README.md', 'AGENTS.md'];
|
|
226
|
+
for (const file of versionFiles) {
|
|
227
|
+
const filePath = resolve(ROOT, file);
|
|
228
|
+
let text;
|
|
229
|
+
try { text = readFileSync(filePath, 'utf-8'); } catch { continue; }
|
|
230
|
+
|
|
231
|
+
let updated = text;
|
|
232
|
+
|
|
233
|
+
// Sync @claude-flow/cli version references
|
|
234
|
+
// Match patterns like **v3.1.0-alpha.NN** or `3.1.0-alpha.NN` or @3.1.0-alpha.NN
|
|
235
|
+
const cliRe = /(?<=[@`*v])3\.1\.0-alpha\.\d+/g;
|
|
236
|
+
updated = updated.replace(cliRe, cliTarget);
|
|
237
|
+
|
|
238
|
+
if (updated !== text) {
|
|
239
|
+
if (!checkOnly) writeFileSync(filePath, updated);
|
|
240
|
+
report(true, `${file} (upstream baseline)`);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (!anyChanged) {
|
|
245
|
+
console.log('All files are up to date.');
|
|
246
|
+
} else if (checkOnly) {
|
|
247
|
+
console.log('\nFiles are out of date. Run: npm run preflight');
|
|
248
|
+
process.exit(1);
|
|
249
|
+
}
|