crewforth 3.0.0-rc.3 → 3.0.1-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +94 -1
- package/VERSION +1 -1
- package/adopt.sh +186 -19
- package/kit/CLAUDE.md +5 -4
- package/kit/README.md +1 -1
- package/kit/agents/crew-frontend-expert.md +6 -6
- package/kit/agents/crew-session-manager.md +1 -1
- package/kit/eval/doctor.sh +72 -18
- package/kit/eval/golden-routing.txt +15 -0
- package/kit/eval/preflight.sh +2 -2
- package/kit/eval/smoke-test.sh +625 -29
- package/kit/hooks/board-sync.sh +1 -1
- package/kit/hooks/board.sh +4 -3
- package/kit/hooks/guard-bash.sh +195 -21
- package/kit/hooks/guard-commit-scan.sh +2 -2
- package/kit/hooks/guard-powershell.sh +328 -0
- package/kit/hooks/guard-write.sh +28 -3
- package/kit/hooks/route-hint.sh +5 -1
- package/kit/hooks/session-update-check.sh +2 -2
- package/kit/hooks/skill-trust.sh +22 -11
- package/kit/legacy-blobs.tsv +208 -0
- package/kit/settings.json +10 -0
- package/kit/skills/automode-policy/SKILL.md +1 -1
- package/kit/skills/automode-policy/scripts/check.sh +2 -2
- package/kit/skills/crew-board/SKILL.md +1 -1
- package/kit/skills/crew-doctor/SKILL.md +3 -3
- package/kit/skills/crew-gates/SKILL.md +2 -1
- package/kit/skills/crew-handoff/SKILL.md +1 -1
- package/kit/skills/crew-skill/SKILL.md +2 -2
- package/kit/skills/crew-studio/SKILL.md +3 -2
- package/kit/skills/crew-update/SKILL.md +3 -3
- package/kit/skills/frontend/SKILL.md +26 -2
- package/kit/skills/frontend-rn-expo/SKILL.md +3 -0
- package/kit/skills/handoff/SKILL.md +2 -2
- package/kit/skills/reflect/SKILL.md +2 -2
- package/kit/skills/teamboard/SKILL.md +1 -1
- package/kit/skills/token-budget/SKILL.md +2 -2
- package/kit/skills/trace-scan/SKILL.md +4 -3
- package/kit/studio/README.md +1 -1
- package/package.json +1 -1
- package/start.sh +15 -8
package/kit/eval/doctor.sh
CHANGED
|
@@ -59,6 +59,9 @@ _mt() {
|
|
|
59
59
|
"no .claude/ in '%s' — is Crewforth installed here?") s="'%s' içinde .claude/ yok — Crewforth burada kurulu mu?" ;;
|
|
60
60
|
'VERSION present (%s)') s='VERSION var (%s)' ;;
|
|
61
61
|
'VERSION missing') s='VERSION yok' ;;
|
|
62
|
+
"no install trace: VERSION is here but .claude/kit-manifest.txt is not — the last update did not finish, or .claude/ was copied; run: npx crewforth update --here (information only — nothing was changed)") s="kurulum izi yok: VERSION var ama .claude/kit-manifest.txt yok — son güncelleme bitmemiş ya da .claude/ kopyalanmış; çalıştırın: npx crewforth update --here (yalnız bilgi — hiçbir şey değiştirilmedi)" ;;
|
|
63
|
+
'no install trace: components the install manifest lists are not here (%s) — the last update did not finish, or .claude/ was copied; run: npx crewforth update --here (information only — nothing was changed; if you removed a component on purpose, ignore this line)') s='kurulum izi yok: kurulum manifestinin listelediği bileşenler burada yok (%s) — son güncelleme bitmemiş ya da .claude/ kopyalanmış; çalıştırın: npx crewforth update --here (yalnız bilgi — hiçbir şey değiştirilmedi; bir bileşeni bilerek sildiyseniz bu satırı yok sayın)' ;;
|
|
64
|
+
'install trace: the components on disk match the install manifest') s='kurulum izi: diskteki bileşenler kurulum manifestiyle uyuşuyor' ;;
|
|
62
65
|
'reinstall or update Crewforth (npx crewforth update)') s="Crewforth'u yeniden kurun ya da güncelleyin (npx crewforth update)" ;;
|
|
63
66
|
'Crewforth v%s installed, v%s published — update with /crew-update') s='Crewforth v%s kurulu, v%s yayında — /crew-update ile güncelleyin' ;;
|
|
64
67
|
'required git hooks present (pre-commit, commit-msg)') s="gerekli git hook'ları yerinde (pre-commit, commit-msg)" ;;
|
|
@@ -96,9 +99,9 @@ _mt() {
|
|
|
96
99
|
'skill listing: %s skill(s) use when_to_use or a folded description — a shape the count was not measured on') s='skill listesi: %s skill when_to_use ya da katlanmış açıklama kullanıyor — sayımın ölçülmediği bir biçim' ;;
|
|
97
100
|
'skill listing %s chars for %s skills fits the %s-char budget (fraction %s from %s, %s-token window%s)') s="skill listesi %s karakter, %s skill; %s karakterlik bütçeye sığıyor (kesir %s, kaynak %s; %s token'lık pencere%s)" ;;
|
|
98
101
|
'skill listing %s chars for %s skills EXCEEDS the %s-char budget (fraction %s from %s, %s-token window%s)') s="skill listesi %s karakter, %s skill; %s karakterlik bütçeyi AŞIYOR (kesir %s, kaynak %s; %s token'lık pencere%s)" ;;
|
|
99
|
-
' — Claude Code drops the descriptions of the least-used skills, and those
|
|
102
|
+
' — Claude Code drops the descriptions of the least-used skills, and those are less likely to be picked on their own.') s=" — Claude Code en az kullanılan skill'lerin açıklamalarını düşürür; o skill'lerin kendiliğinden seçilmesi zorlaşır." ;;
|
|
100
103
|
' Fixes: raise %s in settings, or set rarely-used skills to %s in %s.') s=" Çözüm: ayarlarda %s değerini yükseltin ya da nadir kullanılan skill'leri %s olarak %s içine yazın." ;;
|
|
101
|
-
' Which skills? bash .claude/eval/utilization.sh — it reports the ones nothing in this project reached.') s=" Hangileri? bash .claude/eval/utilization.sh — bu projede hiçbir şeyin ulaşmadığı skill'leri listeler." ;;
|
|
104
|
+
' Which skills? bash .claude/eval/utilization.sh (Bash tool, not PowerShell) — it reports the ones nothing in this project reached.') s=" Hangileri? bash .claude/eval/utilization.sh (PowerShell değil, Bash aracıyla) — bu projede hiçbir şeyin ulaşmadığı skill'leri listeler." ;;
|
|
102
105
|
"on a 200,000-token model the whole listing would be ~%s chars (Crewforth %s + your personal skills %s + Claude Code's own ~%s, measured) against %s at fraction %s — the least-used skills there lose their descriptions.") s="200 000 token'lık bir modelde listenin tamamı ~%s karakter olur (Crewforth %s + kişisel skill'leriniz %s + Claude Code'un kendi ~%s, ölçüldü); bütçe ise %s karakter (kesir %s). Orada en az kullanılan skill'ler açıklamalarını kaybeder." ;;
|
|
103
106
|
' If you use such a model, one line in %s/settings.json fixes it: %s') s=' Böyle bir model kullanıyorsanız %s/settings.json dosyasına tek satır yeter: %s' ;;
|
|
104
107
|
' What it costs: the listing is sent every turn. At 0.04 it stays whole — ~%s chars, about %s tokens,') s=" Bedeli: liste her turda gönderilir. 0.04'te bütün kalır — ~%s karakter, yaklaşık %s token," ;;
|
|
@@ -126,6 +129,9 @@ _mt() {
|
|
|
126
129
|
'DOCTOR: %s issue(s) ❌ — apply the fixes above%s') s='DOCTOR: %s sorun ❌ — yukarıdaki çözümleri uygulayın%s' ;;
|
|
127
130
|
'shell gates watch both Bash and PowerShell') s="kabuk kapıları hem Bash'i hem PowerShell'i izliyor" ;;
|
|
128
131
|
'shell gates watch only Bash — PowerShell commands bypass every §4.5 rule') s="kabuk kapıları yalnız Bash'i izliyor — PowerShell komutları her §4.5 kuralını atlıyor" ;;
|
|
132
|
+
'shell gates watch only PowerShell — Bash commands bypass every §4.5 rule') s="kabuk kapıları yalnız PowerShell'i izliyor — Bash komutları her §4.5 kuralını atlıyor" ;;
|
|
133
|
+
'guard-bash.sh is not wired in PreToolUse — every shell command bypasses §4.4/§4.5') s="guard-bash.sh PreToolUse'a bağlı değil — her kabuk komutu §4.4/§4.5'i atlıyor" ;;
|
|
134
|
+
'update Crewforth (npx crewforth update), which rewires it') s="Crewforth'u güncelleyin (npx crewforth update); bağlantıyı yeniden kurar" ;;
|
|
129
135
|
'update Crewforth (npx crewforth update), or set the PreToolUse matcher to') s="Crewforth'u güncelleyin (npx crewforth update) ya da PreToolUse matcher'ını şuna ayarlayın:" ;;
|
|
130
136
|
'auto-mode classifier config: built-ins intact, Crewforth rules present (config, not a gate)') s='auto-mode sınıflandırıcı ayarı: yerleşik kurallar sağlam, Crewforth kuralları var (ayar, kapı değil)' ;;
|
|
131
137
|
'auto-mode classifier BUILT-INS DROPPED — an autoMode array lacks %s') s='auto-mode sınıflandırıcının YERLEŞİK KURALLARI DÜŞMÜŞ — bir autoMode dizisinde %s yok' ;;
|
|
@@ -191,6 +197,31 @@ if [ -f .claude/VERSION ] && [ -f .claude/.state/update-check ]; then
|
|
|
191
197
|
fi
|
|
192
198
|
fi
|
|
193
199
|
|
|
200
|
+
# 1c) Install trace. An update leaves VERSION, the install manifest and the components on disk agreeing; when they do
|
|
201
|
+
# not, the last update did not finish or .claude/ came from somewhere else (a copy from another project), and the
|
|
202
|
+
# update's own steps — the legacy sweep, the pattern skill's trust — never ran here. Information only: nothing is
|
|
203
|
+
# changed, the fix is the update. Measured case: a project whose trust record was missing after a 3.0 update.
|
|
204
|
+
if [ -f .claude/VERSION ]; then
|
|
205
|
+
if [ ! -f .claude/kit-manifest.txt ]; then
|
|
206
|
+
warn "no install trace: VERSION is here but .claude/kit-manifest.txt is not — the last update did not finish, or .claude/ was copied; run: npx crewforth update --here (information only — nothing was changed)"
|
|
207
|
+
else
|
|
208
|
+
DTMISS=""
|
|
209
|
+
while IFS= read -r e || [ -n "$e" ]; do
|
|
210
|
+
e="${e%$'\r'}"; case "$e" in ''|'#'*) continue ;; esac
|
|
211
|
+
[ -e ".claude/$e" ] || DTMISS="$DTMISS $e"
|
|
212
|
+
done < .claude/kit-manifest.txt
|
|
213
|
+
# Only "listed but absent" is a signal. A crew-* component on disk that the manifest does not list may be the user's
|
|
214
|
+
# own (review: a user's skills/crew-mine read as a broken install), so it is not reported.
|
|
215
|
+
# A component the user deleted on purpose looks exactly like one an interrupted update never wrote: nothing on disk
|
|
216
|
+
# tells the two apart, and recording deletions would be a new file to keep in step. So the line says it instead.
|
|
217
|
+
if [ -n "$DTMISS" ]; then
|
|
218
|
+
warn "no install trace: components the install manifest lists are not here (%s) — the last update did not finish, or .claude/ was copied; run: npx crewforth update --here (information only — nothing was changed; if you removed a component on purpose, ignore this line)" "${DTMISS# }"
|
|
219
|
+
else
|
|
220
|
+
ok "install trace: the components on disk match the install manifest"
|
|
221
|
+
fi
|
|
222
|
+
fi
|
|
223
|
+
fi
|
|
224
|
+
|
|
194
225
|
# 2) Hooks present + executable. The .sh set is a glob (extras ok); pre-commit + commit-msg are REQUIRED — they
|
|
195
226
|
# ARE the §4.1/§4.2 trace/secret gate, so a MISSING one is a failure, not a silent skip.
|
|
196
227
|
NX=""; GONE=""
|
|
@@ -318,9 +349,9 @@ EOF_SLA
|
|
|
318
349
|
ok "skill listing %s chars for %s skills fits the %s-char budget (fraction %s from %s, %s-token window%s)" "$LISTING" "$NLISTED" "$BUDGET" "$FRAC" "$FROM" "$CW" "$EST"
|
|
319
350
|
else
|
|
320
351
|
warn "skill listing %s chars for %s skills EXCEEDS the %s-char budget (fraction %s from %s, %s-token window%s)" "$LISTING" "$NLISTED" "$BUDGET" "$FRAC" "$FROM" "$CW" "$EST"
|
|
321
|
-
warn " — Claude Code drops the descriptions of the least-used skills, and those
|
|
352
|
+
warn " — Claude Code drops the descriptions of the least-used skills, and those are less likely to be picked on their own."
|
|
322
353
|
warn " Fixes: raise %s in settings, or set rarely-used skills to %s in %s." '"skillListingBudgetFraction"' '"name-only"' '"skillOverrides"'
|
|
323
|
-
warn " Which skills? bash .claude/eval/utilization.sh — it reports the ones nothing in this project reached."
|
|
354
|
+
warn " Which skills? bash .claude/eval/utilization.sh (Bash tool, not PowerShell) — it reports the ones nothing in this project reached."
|
|
324
355
|
fi
|
|
325
356
|
# The whole listing, not only Crewforth's share: the user's personal skills and Claude Code's own bundled skills
|
|
326
357
|
# sit in the same budget. The bundled ones were measured once (14 skills, 5898 chars, Claude Code v2.1.282, an
|
|
@@ -465,6 +496,43 @@ if [ -f .claude/DISCIPLINE.md ]; then
|
|
|
465
496
|
fi
|
|
466
497
|
fi
|
|
467
498
|
|
|
499
|
+
# 8b) The shell matcher. Claude Code's hooks reference is explicit: inspect shell commands with
|
|
500
|
+
# `Bash|PowerShell`, because wherever the PowerShell tool is enabled it IS the shell — and it is on by
|
|
501
|
+
# default for claude.ai and Console accounts on Windows. An install from before 2.5.0 watches only `Bash`,
|
|
502
|
+
# so every PowerShell command walks past the §4.5 rules with nothing firing. Nothing about the session
|
|
503
|
+
# looks wrong, which is why this is a check and not a release note.
|
|
504
|
+
# The matcher read is the one of the PreToolUse entry that runs guard-bash.sh, through the one JSON reader.
|
|
505
|
+
# Any matcher naming PowerShell used to pass — and 3.0.1 wires guard-powershell.sh on a PowerShell-only entry, so
|
|
506
|
+
# an install whose guard-bash watched only Bash read as healthy (measured). A line-by-line read also answered
|
|
507
|
+
# wrong on another key order or on one-line JSON. Placed BEFORE the verdict, so a failure here counts in it.
|
|
508
|
+
# An entry with no matcher applies to every tool.
|
|
509
|
+
SJ8="${SJ:-.claude/eval/lib/settings-json.awk}"
|
|
510
|
+
if [ -f .claude/settings.json ] && [ -f "$SJ8" ] && awk -v op=validate -f "$SJ8" .claude/settings.json 2>/dev/null; then
|
|
511
|
+
_n8="$(awk -v op=len -v path=hooks.PreToolUse -f "$SJ8" .claude/settings.json 2>/dev/null)" || _n8=0
|
|
512
|
+
_gbm="none"; _i8=0
|
|
513
|
+
while [ "$_i8" -lt "${_n8:-0}" ] 2>/dev/null; do
|
|
514
|
+
case "$(awk -v op=get -v path="hooks.PreToolUse.$_i8.hooks" -f "$SJ8" .claude/settings.json 2>/dev/null)" in
|
|
515
|
+
*guard-bash.sh*) _gbm="$(awk -v op=get -v path="hooks.PreToolUse.$_i8.matcher" -f "$SJ8" .claude/settings.json 2>/dev/null)" || _gbm='"*"'
|
|
516
|
+
_gbm="${_gbm#\"}"; _gbm="${_gbm%\"}"; break ;;
|
|
517
|
+
esac
|
|
518
|
+
_i8=$((_i8+1))
|
|
519
|
+
done
|
|
520
|
+
case "|$_gbm|" in
|
|
521
|
+
"|none|") BAD_TAIL=''
|
|
522
|
+
bad "guard-bash.sh is not wired in PreToolUse — every shell command bypasses §4.4/§4.5" \
|
|
523
|
+
"update Crewforth (npx crewforth update), which rewires it" ;;
|
|
524
|
+
"|*|"|"||"|*"|PowerShell|"*) case "|$_gbm|" in *"|Bash|"*|"|*|"|"||") ok "shell gates watch both Bash and PowerShell" ;;
|
|
525
|
+
*) BAD_TAIL=' "Bash|PowerShell"'
|
|
526
|
+
bad "shell gates watch only PowerShell — Bash commands bypass every §4.5 rule" \
|
|
527
|
+
"update Crewforth (npx crewforth update), or set the PreToolUse matcher to" ;; esac ;;
|
|
528
|
+
*"|Bash|"*) BAD_TAIL=' "Bash|PowerShell"'
|
|
529
|
+
bad "shell gates watch only Bash — PowerShell commands bypass every §4.5 rule" \
|
|
530
|
+
"update Crewforth (npx crewforth update), or set the PreToolUse matcher to" ;;
|
|
531
|
+
*) BAD_TAIL=''
|
|
532
|
+
bad "guard-bash.sh is not wired in PreToolUse — every shell command bypasses §4.4/§4.5" \
|
|
533
|
+
"update Crewforth (npx crewforth update), which rewires it" ;;
|
|
534
|
+
esac
|
|
535
|
+
fi
|
|
468
536
|
echo "---"
|
|
469
537
|
# The verdict is the line people read, and some read only it. The preflight block
|
|
470
538
|
# below reports a missing node, but it prints AFTER this — so on a machine that
|
|
@@ -494,20 +562,6 @@ if [ "$FAIL" -eq 0 ]; then _mt "DOCTOR: healthy ✅%s" "$PANEL_NOTE"; echo "$_M"
|
|
|
494
562
|
[ -f "$(dirname "$0")/lib/star.sh" ] && bash "$(dirname "$0")/lib/star.sh" --once .
|
|
495
563
|
else _mt "DOCTOR: %s issue(s) ❌ — apply the fixes above%s" "$FAIL" "$PANEL_NOTE"; echo "$_M"; fi
|
|
496
564
|
|
|
497
|
-
# 8b) The shell matcher. Claude Code's hooks reference is explicit: inspect shell commands with
|
|
498
|
-
# `Bash|PowerShell`, because wherever the PowerShell tool is enabled it IS the shell — and it is on by
|
|
499
|
-
# default for claude.ai and Console accounts on Windows. An install from before 2.5.0 watches only `Bash`,
|
|
500
|
-
# so every PowerShell command walks past the §4.5 rules with nothing firing. Nothing about the session
|
|
501
|
-
# looks wrong, which is why this is a check and not a release note.
|
|
502
|
-
if [ -f .claude/settings.json ]; then
|
|
503
|
-
if grep -q '"matcher"[[:space:]]*:[[:space:]]*"[^"]*PowerShell' .claude/settings.json; then
|
|
504
|
-
ok "shell gates watch both Bash and PowerShell"
|
|
505
|
-
elif grep -q '"matcher"[[:space:]]*:[[:space:]]*"Bash"' .claude/settings.json; then
|
|
506
|
-
BAD_TAIL=' "Bash|PowerShell"'
|
|
507
|
-
bad "shell gates watch only Bash — PowerShell commands bypass every §4.5 rule" \
|
|
508
|
-
"update Crewforth (npx crewforth update), or set the PreToolUse matcher to"
|
|
509
|
-
fi
|
|
510
|
-
fi
|
|
511
565
|
# 9) The auto-mode classifier. Since 2026-08-14 auto mode is the default permission mode on Pro/Max/Team, so a
|
|
512
566
|
# classifier answers permission prompts the user used to answer. Two things can be wrong and neither shows
|
|
513
567
|
# up in a session. Only ONE of them is a real gate finding: a custom autoMode block that dropped the
|
|
@@ -14,12 +14,20 @@ add a new handler for the order endpoint|crew-backend-expert
|
|
|
14
14
|
write a migration for this table|crew-database-expert
|
|
15
15
|
build a responsive component for the login screen|crew-frontend-expert
|
|
16
16
|
# Positive twins of the seven over-broad-word rows below: the replacement phrase must still route.
|
|
17
|
+
add a settings screen in the frontend|frontend
|
|
18
|
+
frontend'de bir ekran ekle|frontend
|
|
19
|
+
the UI component re-renders on every keystroke|frontend
|
|
17
20
|
cut a release and tag it|release
|
|
18
21
|
review the code in this PR|crew-code-review
|
|
19
22
|
the page layout is broken on mobile|frontend-design
|
|
20
23
|
requests are timing out under load|crew-performance-expert
|
|
21
24
|
add client routing to the app|crew-frontend-expert
|
|
22
25
|
add a new rn screen with expo router|frontend-rn-expo
|
|
26
|
+
# The client side is stack-neutral (3.0.1): a mobile request on another stack goes to the frontend owner, never to
|
|
27
|
+
# the React Native layer. Turkish as typed in the field, and English.
|
|
28
|
+
flutter ekranı ekle|crew-frontend-expert
|
|
29
|
+
add a SwiftUI view for the profile|crew-frontend-expert
|
|
30
|
+
build a Jetpack Compose screen for settings|crew-frontend-expert
|
|
23
31
|
run an OWASP check and a full security scan|crew-security-expert
|
|
24
32
|
we need a kvkk privacy audit|crew-privacy-agent
|
|
25
33
|
commit the changes|crew-commit-agent
|
|
@@ -92,6 +100,13 @@ set up the project structure for a new API|backend-architecture
|
|
|
92
100
|
choose a database for this service|backend-architecture
|
|
93
101
|
|
|
94
102
|
# --- Negative: prompt must NOT route to target (over-broad-trigger guard) ---
|
|
103
|
+
flutter ekranı ekle|!frontend-rn-expo
|
|
104
|
+
add a SwiftUI view for the profile|!frontend-rn-expo
|
|
105
|
+
build a Jetpack Compose screen for settings|!frontend-rn-expo
|
|
106
|
+
# Field case (3.0.1, P2 case A): a user handing work over to another team named the area in passing — the bare word
|
|
107
|
+
# "frontend" and a project called <x>_ui each routed it to the frontend skill. Turkish as it was typed, and in English.
|
|
108
|
+
acme_ui için yapılacak iş varsa aktarır mısın? frontend tarafından o sorumlu|!frontend
|
|
109
|
+
if there is work for acme_ui, pass it over — the frontend team owns that|!frontend
|
|
95
110
|
#
|
|
96
111
|
# The seven rows below are the ones that were REPORTED FROM LIVE USE, not invented. Each generic English word
|
|
97
112
|
# was a standalone trigger, and a single trigger of six characters or more clears the score floor on its own —
|
package/kit/eval/preflight.sh
CHANGED
|
@@ -108,7 +108,7 @@ _mt() {
|
|
|
108
108
|
"Optional gaps above are safe but worth closing.") s='Yukarıdaki isteğe bağlı eksikler sorun çıkarmaz ama gidermeye değer.' ;;
|
|
109
109
|
"Everything Crewforth needs is here.") s="Crewforth'un ihtiyaç duyduğu her şey kurulu." ;;
|
|
110
110
|
"is the panel only — every gate still holds without it.") s='yalnızca panel için gerekli — o olmadan da tüm kapılar çalışır.' ;;
|
|
111
|
-
"Or let Crewforth get one: %s") s='İsterseniz Crewforth sizin için indirebilir: %s' ;;
|
|
111
|
+
"Or let Crewforth get one (Bash tool, not PowerShell): %s") s='İsterseniz Crewforth sizin için indirebilir (PowerShell değil, Bash aracıyla): %s' ;;
|
|
112
112
|
"fix: ") s='çözüm: ' ;;
|
|
113
113
|
"node 18+") s='node 18+' ;;
|
|
114
114
|
"sha256 tool") s='sha256 aracı' ;;
|
|
@@ -171,7 +171,7 @@ if [ -n "$MISSING_REQ" ]; then
|
|
|
171
171
|
*node*) _mt 'is the panel only — every gate still holds without it.'; printf ' %snode%s %s\n' "$B" "$R" "$_M"
|
|
172
172
|
# And it is not a dead end: Crewforth fetches a runtime for the panel itself, into one
|
|
173
173
|
# directory under $HOME, verified against the published checksum. It asks first.
|
|
174
|
-
printf ' %s\n' "$(m 'Or let Crewforth get one: %s' "${B}bash .claude/studio/ensure-node.sh --plan${R}")" ;;
|
|
174
|
+
printf ' %s\n' "$(m 'Or let Crewforth get one (Bash tool, not PowerShell): %s' "${B}bash .claude/studio/ensure-node.sh --plan${R}")" ;;
|
|
175
175
|
esac
|
|
176
176
|
elif [ -n "$MISSING_OPT" ]; then
|
|
177
177
|
[ "$QUIET" = 1 ] || { _mt 'All required tools present.'; _a="$_M"; _mt 'Optional gaps above are safe but worth closing.'
|