crewforth 0.0.1 → 3.0.0-rc.2
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 +3805 -0
- package/LICENSE +21 -0
- package/README.md +37 -7
- package/VERSION +1 -0
- package/adopt.sh +1739 -0
- package/bin/cli.js +497 -0
- package/kit/AGENT_TEMPLATE.md +92 -0
- package/kit/CLAUDE.md +228 -0
- package/kit/README.md +107 -0
- package/kit/agents/crew-backend-expert.md +95 -0
- package/kit/agents/crew-commit-agent.md +96 -0
- package/kit/agents/crew-database-expert.md +84 -0
- package/kit/agents/crew-devops-expert.md +82 -0
- package/kit/agents/crew-frontend-expert.md +85 -0
- package/kit/agents/crew-performance-expert.md +78 -0
- package/kit/agents/crew-planner.md +60 -0
- package/kit/agents/crew-privacy-agent.md +71 -0
- package/kit/agents/crew-review-agent.md +95 -0
- package/kit/agents/crew-security-expert.md +73 -0
- package/kit/agents/crew-session-manager.md +77 -0
- package/kit/agents/crew-test-expert.md +64 -0
- package/kit/eval/doctor.sh +639 -0
- package/kit/eval/gate-report.sh +137 -0
- package/kit/eval/golden-holdout.txt +53 -0
- package/kit/eval/golden-routing.txt +199 -0
- package/kit/eval/lib/crew-env.sh +14 -0
- package/kit/eval/lib/settings-json.awk +154 -0
- package/kit/eval/lib/skill-listing.awk +43 -0
- package/kit/eval/lib/star.sh +70 -0
- package/kit/eval/parser-conformance.sh +612 -0
- package/kit/eval/preflight.sh +186 -0
- package/kit/eval/routing-eval.sh +209 -0
- package/kit/eval/scan-skill.sh +162 -0
- package/kit/eval/smoke-test.sh +6736 -0
- package/kit/eval/update-guard.sh +81 -0
- package/kit/eval/utilization.sh +130 -0
- package/kit/hooks/board-sync.sh +106 -0
- package/kit/hooks/board.sh +962 -0
- package/kit/hooks/commit-msg +49 -0
- package/kit/hooks/context-usage.sh +353 -0
- package/kit/hooks/floor-blocklist.txt +124 -0
- package/kit/hooks/guard-bash.sh +1433 -0
- package/kit/hooks/guard-commit-scan.sh +511 -0
- package/kit/hooks/guard-write.sh +513 -0
- package/kit/hooks/pre-commit +577 -0
- package/kit/hooks/route-hint.sh +185 -0
- package/kit/hooks/secret-blocklist.txt +82 -0
- package/kit/hooks/session-guard.sh +149 -0
- package/kit/hooks/session-rehydrate.sh +41 -0
- package/kit/hooks/session-stats.sh +252 -0
- package/kit/hooks/session-update-check.sh +236 -0
- package/kit/hooks/skill-trust.sh +163 -0
- package/kit/hooks/trace-blocklist.txt +53 -0
- package/kit/settings.json +132 -0
- package/kit/skills/a11y/SKILL.md +44 -0
- package/kit/skills/adr/SKILL.md +74 -0
- package/kit/skills/api-design/SKILL.md +50 -0
- package/kit/skills/automode-policy/SKILL.md +91 -0
- package/kit/skills/automode-policy/references/policy.json +13 -0
- package/kit/skills/automode-policy/scripts/apply.sh +84 -0
- package/kit/skills/automode-policy/scripts/check.sh +102 -0
- package/kit/skills/backend-architecture/SKILL.md +103 -0
- package/kit/skills/brainstorm/SKILL.md +47 -0
- package/kit/skills/ci-pipeline/SKILL.md +38 -0
- package/kit/skills/commit-message/SKILL.md +82 -0
- package/kit/skills/commit-message/references/examples.md +8 -0
- package/kit/skills/confidence-check/SKILL.md +86 -0
- package/kit/skills/crew-board/SKILL.md +55 -0
- package/kit/skills/crew-brainstorm/SKILL.md +19 -0
- package/kit/skills/crew-code-review/SKILL.md +151 -0
- package/kit/skills/crew-code-review/references/history-search.md +19 -0
- package/kit/skills/crew-code-review/references/panel-mode.md +32 -0
- package/kit/skills/crew-code-review/references/receiving.md +23 -0
- package/kit/skills/crew-doctor/SKILL.md +46 -0
- package/kit/skills/crew-gates/SKILL.md +25 -0
- package/kit/skills/crew-handoff/SKILL.md +14 -0
- package/kit/skills/crew-plan/SKILL.md +18 -0
- package/kit/skills/crew-review/SKILL.md +26 -0
- package/kit/skills/crew-ship/SKILL.md +19 -0
- package/kit/skills/crew-skill/SKILL.md +62 -0
- package/kit/skills/crew-studio/SKILL.md +129 -0
- package/kit/skills/crew-update/SKILL.md +43 -0
- package/kit/skills/db-migration/SKILL.md +120 -0
- package/kit/skills/db-migration/references/backup-restore.md +33 -0
- package/kit/skills/db-migration/references/raw-sql.md +30 -0
- package/kit/skills/db-migration/references/tool-matrix.md +35 -0
- package/kit/skills/dependency-audit/SKILL.md +61 -0
- package/kit/skills/dependency-upgrade/SKILL.md +82 -0
- package/kit/skills/deploy/SKILL.md +100 -0
- package/kit/skills/deploy/references/proxy-ssl.md +56 -0
- package/kit/skills/deploy/references/rollback.md +18 -0
- package/kit/skills/deploy/references/scripts.md +9 -0
- package/kit/skills/deploy/references/topology-a.md +128 -0
- package/kit/skills/deploy/references/topology-b.md +44 -0
- package/kit/skills/docs-writer/SKILL.md +53 -0
- package/kit/skills/docs-writer/references/coauthoring.md +34 -0
- package/kit/skills/eval-grader/SKILL.md +75 -0
- package/kit/skills/eval-grader/references/method.md +51 -0
- package/kit/skills/frontend/SKILL.md +56 -0
- package/kit/skills/frontend/references/verify-contract.md +41 -0
- package/kit/skills/frontend-design/SKILL.md +71 -0
- package/kit/skills/frontend-design/references/design-review.md +34 -0
- package/kit/skills/frontend-rn-expo/SKILL.md +25 -0
- package/kit/skills/handoff/SKILL.md +71 -0
- package/kit/skills/handoff/references/cold-reader.md +51 -0
- package/kit/skills/i18n-integrity/SKILL.md +31 -0
- package/kit/skills/incident-runbook/SKILL.md +40 -0
- package/kit/skills/incident-runbook/references/postmortem.md +16 -0
- package/kit/skills/iterate/SKILL.md +40 -0
- package/kit/skills/mcp-builder/SKILL.md +54 -0
- package/kit/skills/mcp-builder/references/building.md +71 -0
- package/kit/skills/observability/SKILL.md +50 -0
- package/kit/skills/performance/SKILL.md +38 -0
- package/kit/skills/performance/references/bottlenecks.md +10 -0
- package/kit/skills/privacy-compliance/SKILL.md +75 -0
- package/kit/skills/red-team/SKILL.md +48 -0
- package/kit/skills/reflect/SKILL.md +57 -0
- package/kit/skills/release/SKILL.md +44 -0
- package/kit/skills/security-scan/SKILL.md +99 -0
- package/kit/skills/security-scan/references/ai-agents.md +107 -0
- package/kit/skills/security-scan/references/fronts.md +99 -0
- package/kit/skills/security-scan/references/prompting.md +23 -0
- package/kit/skills/security-scan/references/reporting.md +75 -0
- package/kit/skills/security-scan/references/verify.md +131 -0
- package/kit/skills/sonarqube-check/SKILL.md +108 -0
- package/kit/skills/sonarqube-check/references/local-engines.md +32 -0
- package/kit/skills/sonarqube-check/references/stand-up-server.md +25 -0
- package/kit/skills/spec-planning/SKILL.md +92 -0
- package/kit/skills/systematic-debugging/SKILL.md +57 -0
- package/kit/skills/systematic-debugging/references/techniques.md +44 -0
- package/kit/skills/teamboard/SKILL.md +88 -0
- package/kit/skills/teamboard/references/setup.md +37 -0
- package/kit/skills/testing/SKILL.md +49 -0
- package/kit/skills/testing/references/flaky-triage.md +51 -0
- package/kit/skills/threat-model/SKILL.md +57 -0
- package/kit/skills/threat-model/references/interview.md +51 -0
- package/kit/skills/threat-model/references/schema.md +42 -0
- package/kit/skills/token-budget/SKILL.md +51 -0
- package/kit/skills/trace-scan/SKILL.md +43 -0
- package/kit/skills/worktree/SKILL.md +40 -0
- package/kit/studio/README.md +266 -0
- package/kit/studio/ensure-node.sh +471 -0
- package/kit/studio/package.json +14 -0
- package/kit/studio/server/hooks/studio-gate.sh +169 -0
- package/kit/studio/server/index.js +902 -0
- package/kit/studio/server/lib/crew-env.js +11 -0
- package/kit/studio/server/lib/fleet.js +146 -0
- package/kit/studio/server/lib/graph.js +533 -0
- package/kit/studio/server/lib/instance.js +135 -0
- package/kit/studio/server/lib/kit-telemetry.js +182 -0
- package/kit/studio/server/lib/kit.js +158 -0
- package/kit/studio/server/lib/palette.js +118 -0
- package/kit/studio/server/lib/peers.js +72 -0
- package/kit/studio/server/lib/permissions.js +150 -0
- package/kit/studio/server/lib/projects.js +294 -0
- package/kit/studio/server/lib/roster.js +191 -0
- package/kit/studio/server/lib/session.js +309 -0
- package/kit/studio/server/lib/terminal.js +91 -0
- package/kit/studio/server/lib/transcript.js +100 -0
- package/kit/studio/web/app.js +1098 -0
- package/kit/studio/web/canvas.js +1179 -0
- package/kit/studio/web/chat.js +543 -0
- package/kit/studio/web/index.html +86 -0
- package/kit/studio/web/md.js +110 -0
- package/kit/studio/web/storage-migrate.js +23 -0
- package/kit/studio/web/style.css +1453 -0
- package/package.json +46 -8
- package/start.sh +764 -0
- package/bin/crewforth.js +0 -10
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Install Crewforth's auto-mode classifier policy into USER settings — the one part of Crewforth that lives
|
|
3
|
+
# outside the project, because the classifier deliberately ignores `autoMode` in .claude/settings.json
|
|
4
|
+
# (a repo could otherwise ship its own allow rules). Writing outside the project is exactly the kind of
|
|
5
|
+
# action §4.4 says needs the user's word, so this script asks, backs up, and verifies — in that order.
|
|
6
|
+
#
|
|
7
|
+
# Usage:
|
|
8
|
+
# apply.sh propose the change, show the diff, ask, install, verify
|
|
9
|
+
# apply.sh --yes same without the prompt (for a scripted setup the user drives)
|
|
10
|
+
# apply.sh --strict also set autoMode.classifyAllShell — every shell command reaches the classifier
|
|
11
|
+
# apply.sh --print print the policy fragment and exit (paste it yourself; no writes, no tooling)
|
|
12
|
+
set -u
|
|
13
|
+
|
|
14
|
+
HERE="$(cd "$(dirname "$0")" && pwd)"
|
|
15
|
+
POLICY="$HERE/../references/policy.json"
|
|
16
|
+
CHECK="$HERE/check.sh"
|
|
17
|
+
TARGET="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/settings.json"
|
|
18
|
+
YES=0; STRICT=0
|
|
19
|
+
for a in "$@"; do case "$a" in
|
|
20
|
+
--yes) YES=1 ;; --strict) STRICT=1 ;;
|
|
21
|
+
--print) cat "$POLICY"; exit 0 ;;
|
|
22
|
+
*) echo "apply.sh: unknown argument '$a'"; exit 64 ;;
|
|
23
|
+
esac; done
|
|
24
|
+
|
|
25
|
+
[ -f "$POLICY" ] || { echo "❌ policy.json not found next to this script"; exit 1; }
|
|
26
|
+
|
|
27
|
+
# A JSON merge into the user's own settings file is not a job for sed. It goes through Crewforth's one JSON reader
|
|
28
|
+
# (eval/lib/settings-json.awk, the same file adopt.sh merges with) — the same code on every OS. This used to pick
|
|
29
|
+
# jq, then python3, and on a stock Windows box with neither it printed the fragment and stopped, so the one
|
|
30
|
+
# platform with no JSON tool could not install the policy at all. The reader sits three levels up in both
|
|
31
|
+
# editions: .claude/skills/<s>/scripts -> .claude/eval/lib, and <plugin>/skills/<s>/scripts -> <plugin>/eval/lib.
|
|
32
|
+
SJ="$HERE/../../../eval/lib/settings-json.awk"
|
|
33
|
+
if [ ! -f "$SJ" ]; then
|
|
34
|
+
echo "⚠️ Crewforth's JSON reader is missing ($SJ) — not merging your settings file by hand."
|
|
35
|
+
echo " Add this block to $TARGET yourself (keep the \"\$defaults\" entries verbatim):"
|
|
36
|
+
echo; cat "$POLICY"; exit 3
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
mkdir -p "$(dirname "$TARGET")"
|
|
40
|
+
[ -f "$TARGET" ] || printf '{}\n' > "$TARGET"
|
|
41
|
+
|
|
42
|
+
TMP="$TARGET.crew-new"; BAK="$TARGET.crew-bak-$(date +%Y%m%d-%H%M%S)"
|
|
43
|
+
# autoMode takes every member of the policy's autoMode (the policy wins), the user's other members and every other
|
|
44
|
+
# key untouched. rc 10 = the target is not a JSON object: nothing is written.
|
|
45
|
+
if [ "$STRICT" = 1 ]; then set -- -v setk=classifyAllShell -v setv=true; else set --; fi
|
|
46
|
+
awk -v op=overlay -v key=autoMode "$@" -f "$SJ" "$TARGET" "$POLICY" > "$TMP" && [ -s "$TMP" ] \
|
|
47
|
+
|| { echo "❌ merge failed (invalid JSON in $TARGET?)"; rm -f "$TMP"; exit 1; }
|
|
48
|
+
|
|
49
|
+
# Verify the CANDIDATE before it is anyone's real configuration. `claude --settings <file>` runs the
|
|
50
|
+
# classifier config resolution against the file, so a policy that would silently drop the 66 built-in
|
|
51
|
+
# soft blocks is caught here — while the only file on disk is still a temp file.
|
|
52
|
+
echo "== verifying the candidate (nothing installed yet) =="
|
|
53
|
+
bash "$CHECK" --settings "$TMP"; RC=$?
|
|
54
|
+
if [ "$RC" != 0 ]; then
|
|
55
|
+
echo "❌ candidate did not verify (rc=$RC) — nothing was written."
|
|
56
|
+
rm -f "$TMP"; exit "$RC"
|
|
57
|
+
fi
|
|
58
|
+
|
|
59
|
+
echo
|
|
60
|
+
echo "== what changes in $TARGET =="
|
|
61
|
+
if command -v diff >/dev/null 2>&1; then diff -u "$TARGET" "$TMP" | sed -n '1,60p'; else echo "(no diff tool; new file written to $TMP)"; fi
|
|
62
|
+
echo
|
|
63
|
+
if [ "$YES" != 1 ]; then
|
|
64
|
+
# No terminal means no one can consent. Asking anyway is worse than useless: with a tty present but nobody
|
|
65
|
+
# reading it — a CI runner, a background job, a test harness — `read </dev/tty` blocks forever. Measured:
|
|
66
|
+
# this hung Crewforth's own smoke test. No consent possible -> abort, and say how to do it deliberately.
|
|
67
|
+
if [ ! -t 0 ] && [ ! -t 1 ]; then
|
|
68
|
+
echo "not an interactive session — nothing written. Re-run with --yes if this is a setup you are driving."
|
|
69
|
+
rm -f "$TMP"; exit 0
|
|
70
|
+
fi
|
|
71
|
+
printf "Install this policy into your USER settings? [y/N] "
|
|
72
|
+
read -r ans </dev/tty 2>/dev/null || ans=""
|
|
73
|
+
case "$ans" in y|Y|yes|YES) : ;; *) echo "aborted — nothing written."; rm -f "$TMP"; exit 0 ;; esac
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
cp "$TARGET" "$BAK" && mv "$TMP" "$TARGET" || { echo "❌ could not write $TARGET"; exit 1; }
|
|
77
|
+
echo "✅ installed. backup: $BAK"
|
|
78
|
+
echo "== verifying what the classifier now actually uses =="
|
|
79
|
+
bash "$CHECK"; RC=$?
|
|
80
|
+
if [ "$RC" != 0 ]; then
|
|
81
|
+
echo "❌ post-install verification failed (rc=$RC) — restoring the backup."
|
|
82
|
+
cp "$BAK" "$TARGET"; exit "$RC"
|
|
83
|
+
fi
|
|
84
|
+
echo " Undo any time: cp \"$BAK\" \"$TARGET\""
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Report what the auto-mode classifier is CONFIGURED with — and be exact about what that does and does not prove.
|
|
3
|
+
#
|
|
4
|
+
# MEASURED, 2026-08-24, Claude Code 2.1.238, interactive session, permissionMode=auto, this policy installed in
|
|
5
|
+
# USER settings and shown as present by `claude auto-mode config`:
|
|
6
|
+
# `git reset --hard && git clean -fd` ran with no prompt and no block, destroying uncommitted work — the exact
|
|
7
|
+
# action Crewforth's hard_deny rule names verbatim and calls unconditional.
|
|
8
|
+
# A control run with NO policy and NO explicit user intent behaved identically.
|
|
9
|
+
# Two headless probes agreed, including an absolute "never write any file" rule, and a protected-path write
|
|
10
|
+
# (.git/config) that the docs say auto mode routes to the classifier went through untouched.
|
|
11
|
+
# Reading: the classifier did not gate this class of action at all, with or without custom rules. So this script
|
|
12
|
+
# reports CONFIGURATION, never enforcement. Crewforth's enforcement lives in its PreToolUse hooks and git hooks,
|
|
13
|
+
# which are measured firing in smoke-test; nothing here replaces them.
|
|
14
|
+
#
|
|
15
|
+
# Auto mode is the default permission mode on Pro/Max/Team since 2026-08-14: a classifier, not the user,
|
|
16
|
+
# answers most permission prompts. It reads its rules from `autoMode` in USER or MANAGED settings only
|
|
17
|
+
# (never from .claude/settings.json — a repo could otherwise ship its own allow rules), so this policy is
|
|
18
|
+
# the one part of Crewforth that lives outside the project. That is why it is installed explicitly and
|
|
19
|
+
# verified here rather than assumed.
|
|
20
|
+
#
|
|
21
|
+
# The failure this guards against is silent: setting an autoMode array WITHOUT the literal "$defaults"
|
|
22
|
+
# replaces the built-in list for that section — 66 soft-block rules and the single built-in hard block
|
|
23
|
+
# disappear with no error, and the session looks healthy. So this script does not read the policy file;
|
|
24
|
+
# it reads what the classifier ACTUALLY uses (`claude auto-mode config`) and checks the built-ins are
|
|
25
|
+
# still there. A policy file that parses is not a policy that applies.
|
|
26
|
+
#
|
|
27
|
+
# Side effect, measured — this script writes nothing itself, but `claude auto-mode config` does: reading the
|
|
28
|
+
# effective config makes Claude Code rewrite its own settings.json (reformatted, values normalised such as
|
|
29
|
+
# `opus` -> `opus[1m]`, a backups/ directory created). That is Claude Code maintaining its own file, and it
|
|
30
|
+
# keeps a backup, but "verifying costs nothing" would be a false claim.
|
|
31
|
+
#
|
|
32
|
+
# What it still catches, and why it is worth running: setting an autoMode array without the literal "$defaults"
|
|
33
|
+
# silently replaces the built-in list for that section (measured: soft_deny 66 -> 2, no error, no warning). That
|
|
34
|
+
# footgun is real whatever the enforcement story is, and nothing else in the toolchain reports it.
|
|
35
|
+
#
|
|
36
|
+
# Usage: check.sh [--settings <file>] # --settings inspects a CANDIDATE policy without installing it
|
|
37
|
+
# Exit: 0 config as expected · 2 built-ins DROPPED · 3 kit rules absent/partial · 4 cannot read the config
|
|
38
|
+
set -u
|
|
39
|
+
|
|
40
|
+
SETTINGS=""
|
|
41
|
+
[ "${1:-}" = "--settings" ] && { SETTINGS="${2:-}"; [ -z "$SETTINGS" ] && { echo "check.sh: --settings needs a file"; exit 4; }; }
|
|
42
|
+
|
|
43
|
+
command -v claude >/dev/null 2>&1 || { echo " ⚠️ claude CLI not on PATH — auto-mode policy cannot be verified"; exit 4; }
|
|
44
|
+
|
|
45
|
+
if [ -n "$SETTINGS" ]; then CFG="$(claude --settings "$SETTINGS" auto-mode config 2>/dev/null)"
|
|
46
|
+
else CFG="$(claude auto-mode config 2>/dev/null)"; fi
|
|
47
|
+
|
|
48
|
+
# `auto-mode` is v2.1.19x+; an older CLI prints usage/error instead of the four rule lists.
|
|
49
|
+
case "$CFG" in *'"soft_deny"'*) : ;; *)
|
|
50
|
+
echo " ⚠️ 'claude auto-mode config' did not return a rule set — CLI too old, or auto mode unavailable on this account"
|
|
51
|
+
exit 4 ;;
|
|
52
|
+
esac
|
|
53
|
+
|
|
54
|
+
# Built-ins, checked PER SECTION and anchored to the rule's label.
|
|
55
|
+
#
|
|
56
|
+
# A whole-blob substring search is NOT enough and this was measured, not assumed: "Data Exfiltration" and
|
|
57
|
+
# "Auto-Mode Bypass" also occur inside the prose of `allow` rules, so a config with those built-ins dropped
|
|
58
|
+
# still contains both strings somewhere. That check reports a false PASS — the worst kind for a policy gate.
|
|
59
|
+
# `claude auto-mode config` prints one rule per line inside `"<section>": [ ... ]`, and every rule begins
|
|
60
|
+
# with its label, so slice the section first and anchor the match to the start of the string.
|
|
61
|
+
section(){ printf '%s\n' "$CFG" | awk -v s="$1" '
|
|
62
|
+
$0 ~ "^[[:space:]]*\""s"\"[[:space:]]*:[[:space:]]*\\[" { inb=1; next }
|
|
63
|
+
inb && /^[[:space:]]*\]/ { inb=0 }
|
|
64
|
+
inb { print }'; }
|
|
65
|
+
|
|
66
|
+
has_rule(){ printf '%s\n' "$2" | grep -q "^[[:space:]]*\"$1"; }
|
|
67
|
+
|
|
68
|
+
HD="$(section hard_deny)"; SD="$(section soft_deny)"
|
|
69
|
+
MISSING=""
|
|
70
|
+
has_rule 'Data Exfiltration' "$HD" || MISSING="$MISSING hard_deny/Data-Exfiltration"
|
|
71
|
+
has_rule 'Git Destructive' "$SD" || MISSING="$MISSING soft_deny/Git-Destructive"
|
|
72
|
+
has_rule 'Auto-Mode Bypass' "$SD" || MISSING="$MISSING soft_deny/Auto-Mode-Bypass"
|
|
73
|
+
|
|
74
|
+
# Each kit rule counts under its 3.0 name or its pre-3.0 one ("CSK …"): a config applied by 2.x keeps passing
|
|
75
|
+
# until the user re-applies, which overlays autoMode and so replaces the old names rather than adding beside them.
|
|
76
|
+
KITR=0
|
|
77
|
+
kit_rule(){ has_rule "Crewforth $1" "$2" || has_rule "CSK $1" "$2"; }
|
|
78
|
+
kit_rule 'Uncommitted Work Destruction' "$HD" && KITR=$((KITR+1))
|
|
79
|
+
kit_rule 'Gate Tampering' "$SD" && KITR=$((KITR+1))
|
|
80
|
+
kit_rule 'Internal Docs Publication' "$SD" && KITR=$((KITR+1))
|
|
81
|
+
|
|
82
|
+
if [ -n "$MISSING" ]; then
|
|
83
|
+
echo " ❌ classifier built-ins DROPPED:$MISSING"
|
|
84
|
+
echo " ↳ an autoMode array was set without the literal \"\$defaults\" — restore it in ~/.claude/settings.json"
|
|
85
|
+
echo " ↳ inspect with: claude auto-mode config · built-ins: claude auto-mode defaults"
|
|
86
|
+
exit 2
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
if [ "$KITR" -eq 0 ]; then
|
|
90
|
+
echo " · Crewforth auto-mode rules not in the classifier config (built-ins only) — not a gate either way"
|
|
91
|
+
echo " ↳ optional: bash .claude/skills/automode-policy/scripts/apply.sh"
|
|
92
|
+
exit 3
|
|
93
|
+
fi
|
|
94
|
+
|
|
95
|
+
if [ "$KITR" -lt 3 ]; then
|
|
96
|
+
echo " · Crewforth auto-mode rules PARTIAL ($KITR/3 present) — built-ins intact"
|
|
97
|
+
echo " ↳ re-apply: bash .claude/skills/automode-policy/scripts/apply.sh"
|
|
98
|
+
exit 3
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
echo " ✅ classifier config: built-ins intact, 3/3 Crewforth rules present (CONFIGURED, not proven to enforce)"
|
|
102
|
+
exit 0
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backend-architecture
|
|
3
|
+
description: |
|
|
4
|
+
Decide, record and apply the backend stack and architecture pattern.
|
|
5
|
+
Use when backend work starts with no recorded stack, or a framework/DB/pattern must be chosen.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Backend Architecture (stack resolution + pattern)
|
|
9
|
+
|
|
10
|
+
<!-- routing-eval reads the next line; why it sits in the body: AGENT_TEMPLATE.md -->
|
|
11
|
+
Trigger phrases: "tech stack", "which framework", "choose a database", "backend pattern", "project structure", "new api", "new handler", "write a command", "add a query", "validator", "which stack should", "set up the project structure", "language or framework", "layered or", "vertical slice", "hexagonal", "clean architecture"
|
|
12
|
+
|
|
13
|
+
The "how" behind `crew-backend-expert`, and the stack step `crew-planner` and `crew-database-expert` rely on.
|
|
14
|
+
**Model discipline, not a gate:** no hook checks that the stack was resolved before code was written.
|
|
15
|
+
|
|
16
|
+
## When
|
|
17
|
+
- A backend task starts and `CLAUDE.md ## Stack` is empty or silent on the part the task needs.
|
|
18
|
+
- Someone asks which language, framework, database or pattern to use.
|
|
19
|
+
- A new service, API, module or handler is being shaped and the pattern is not obvious from neighbouring code.
|
|
20
|
+
|
|
21
|
+
## 1 · Stack resolution — in this order, stop at the first answer
|
|
22
|
+
1. **The request says it.** "Add a Go service…" is an answer. Use it; record it if the section was empty.
|
|
23
|
+
2. **`CLAUDE.md ## Stack` says it.** The project's own section (below Crewforth's `@.claude/DISCIPLINE.md` import),
|
|
24
|
+
not `DISCIPLINE.md`. A filled section is a decision: follow it.
|
|
25
|
+
3. **The repo says it.** Look for manifests at the root and one level down (`backend/`, `server/`, `src/`, `apps/*`):
|
|
26
|
+
|
|
27
|
+
| Manifest | Runtime |
|
|
28
|
+
|:--|:--|
|
|
29
|
+
| `package.json` | Node (TypeScript if `tsconfig.json`) |
|
|
30
|
+
| `go.mod` | Go |
|
|
31
|
+
| `pyproject.toml` / `requirements.txt` | Python |
|
|
32
|
+
| `*.csproj` / `*.sln` | .NET |
|
|
33
|
+
| `pom.xml` / `build.gradle*` | JVM (Java/Kotlin) |
|
|
34
|
+
| `Cargo.toml` | Rust |
|
|
35
|
+
| `composer.json` | PHP |
|
|
36
|
+
| `Gemfile` | Ruby |
|
|
37
|
+
|
|
38
|
+
The framework and database usually follow from the same manifest's dependencies and from config files
|
|
39
|
+
(`docker-compose*.yml`, connection-string env names, migration folders). Two backends in one repo is a
|
|
40
|
+
monorepo, not an ambiguity: record each with its path.
|
|
41
|
+
4. **Still open (a greenfield repo) → ask, once.** Use `AskUserQuestion` with **at most four** questions, only for
|
|
42
|
+
what is still unknown: runtime/language · web framework · database · architecture pattern. **Every question has
|
|
43
|
+
exactly one option whose label ends with `(Recommended)`** (its description gives the one-line reason) **and
|
|
44
|
+
exactly one option labelled `Decide for me`, verbatim** — the user's way to hand the choice back to you.
|
|
45
|
+
No `AskUserQuestion` in this session (headless, or the tool is off)? Write the same questions as text, with the
|
|
46
|
+
same two labels on every question, and stop there.
|
|
47
|
+
|
|
48
|
+
**Record it.** Write the answer into the `## Stack` section of the project's `CLAUDE.md` (Runtime · Web framework ·
|
|
49
|
+
Database + migration tool · Architecture pattern), then record the choice with the `adr` skill (and `board.sh decide`
|
|
50
|
+
when the team board is in use). If "Decide for me" was picked, the ADR says so: *chosen by the agent at the user's
|
|
51
|
+
request*, with the reason for each pick.
|
|
52
|
+
|
|
53
|
+
**Never ask twice.** A recorded stack is followed, not re-litigated. It changes only when the user explicitly asks;
|
|
54
|
+
then update the section and supersede the ADR. Headless / non-interactive and nobody to ask → stop and report the
|
|
55
|
+
open question; do not guess a stack and start writing code.
|
|
56
|
+
|
|
57
|
+
## 2 · Pattern menu — default to the simplest one that fits (YAGNI)
|
|
58
|
+
| Pattern | Fits | Too much when |
|
|
59
|
+
|:--|:--|:--|
|
|
60
|
+
| **Layered** (controller → service → repository) | CRUD-heavy services, small teams, most first versions | rules sprawl across services and every change touches every layer |
|
|
61
|
+
| **Clean / hexagonal** (domain core, ports, adapters) | rich domain rules, several delivery channels or swappable infrastructure | the "domain" is mostly forms over tables |
|
|
62
|
+
| **Vertical slice** (one folder per feature, request → handler → response) | many independent features, teams owning features end to end | features share most of their logic |
|
|
63
|
+
| **CQRS** (separate command and query paths) | reads and writes that differ sharply in shape, load or consistency | reads and writes look the same — it doubles the code for no gain |
|
|
64
|
+
|
|
65
|
+
Existing code wins over this table: a repo already on a pattern keeps it, even where the table would pick another.
|
|
66
|
+
A change of pattern is an architecture decision → design summary + ADR, never a side effect of a feature.
|
|
67
|
+
|
|
68
|
+
## 3 · Rules that hold in any language
|
|
69
|
+
- **One error contract.** Every endpoint returns failures in the same envelope (e.g. RFC 9457 problem details or the
|
|
70
|
+
project's own shape) with the correct status: 400 invalid input · 401 unauthenticated · 403 forbidden · 404 not
|
|
71
|
+
found (also for another tenant's resource — do not leak existence) · 409 conflict · 422 rule violated · 5xx only for
|
|
72
|
+
the server's own fault. No raw exceptions or stack traces in responses.
|
|
73
|
+
- **Validate at the edge.** Parse and validate input where it enters (request DTO + schema/validator), so the core
|
|
74
|
+
only sees valid values. Business rules stay out of controllers/routes.
|
|
75
|
+
- **Cross-cutting concerns in one place** — logging, auth, transactions, caching, rate limits live in
|
|
76
|
+
middleware / decorators / pipeline behaviours, not copied into each handler.
|
|
77
|
+
- **Dependencies are injected**, not constructed inside handlers; the composition root is the only place that knows
|
|
78
|
+
concrete types.
|
|
79
|
+
- **Transaction boundaries are explicit**: one use case, one unit of work. No remote call inside an open DB transaction.
|
|
80
|
+
- **Idempotency** for anything a client may retry (payments, webhooks, create-with-client-id): an idempotency key or a
|
|
81
|
+
natural unique constraint.
|
|
82
|
+
- **Secrets and personal data are never logged** — see `observability` for what to log and `privacy-compliance` for
|
|
83
|
+
personal data.
|
|
84
|
+
|
|
85
|
+
## 4 · Ecosystem map — common choices, not requirements
|
|
86
|
+
| Runtime | Web | Validation | Data / migrations |
|
|
87
|
+
|:--|:--|:--|:--|
|
|
88
|
+
| .NET | ASP.NET Core (MediatR optional) | FluentValidation | EF Core |
|
|
89
|
+
| Node | NestJS / Fastify | zod | Prisma / Drizzle |
|
|
90
|
+
| Go | chi / echo | go-playground/validator | sqlc / GORM |
|
|
91
|
+
| Python | FastAPI | pydantic | SQLAlchemy / Alembic |
|
|
92
|
+
| JVM | Spring Boot | Bean Validation | JPA / Flyway |
|
|
93
|
+
|
|
94
|
+
The project's recorded choices beat this table. Adding a dependency that is not already in the repo → `dependency-audit`.
|
|
95
|
+
|
|
96
|
+
## 5 · Project override
|
|
97
|
+
A pattern skill the project ships under `.claude/skills/` wins over sections 2-4 — for example a `cqrs-aop-module`
|
|
98
|
+
kept from an older install, or one the team wrote (format: `.claude/AGENT_TEMPLATE.md`). Section 1 still applies:
|
|
99
|
+
the stack is resolved and recorded the same way.
|
|
100
|
+
|
|
101
|
+
## Not here — the single source is elsewhere
|
|
102
|
+
Schema and migrations → `db-migration` · tests → `testing` · review → `crew-code-review` · contracts and
|
|
103
|
+
versioning → `api-design` · logs/traces → `observability`.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: brainstorm
|
|
3
|
+
description: |
|
|
4
|
+
Divergent discovery BEFORE planning: turn a fuzzy ask into 2–4 scoped options + named unknowns, pick a
|
|
5
|
+
direction, hand to spec-planning. Bounded; converges to explicit choices, never guesses.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Brainstorm — diverge before you converge
|
|
9
|
+
|
|
10
|
+
<!-- routing-eval reads the next line; why it sits in the body: AGENT_TEMPLATE.md -->
|
|
11
|
+
Trigger phrases: "brainstorm", "explore options", "not sure what we want", "help me scope", "ideate"
|
|
12
|
+
|
|
13
|
+
## When
|
|
14
|
+
The ask is **under-defined**: the goal, the users, or the shape of the solution aren't clear yet, so jumping
|
|
15
|
+
straight to `spec-planning` would just plan the wrong thing. This is the front-end of planning, not a
|
|
16
|
+
replacement — brainstorm *diverges* (widens the option space), spec-planning *converges* (breaks the chosen
|
|
17
|
+
option into tasks). If scope is already clear, skip this and go straight to [[spec-planning]].
|
|
18
|
+
|
|
19
|
+
## The loop
|
|
20
|
+
1. **Frame the real problem** — restate the request as the underlying need in one sentence ("the user wants
|
|
21
|
+
X so that Y"). Separate the stated solution from the goal; often the solution is negotiable, the goal isn't.
|
|
22
|
+
2. **Diverge — generate distinct directions.** Produce **2–4 genuinely different** approaches, not variations
|
|
23
|
+
of one. For each: the core idea, who it serves, the main trade-off. Include a deliberately cheap/minimal
|
|
24
|
+
option (fight gold-plating early).
|
|
25
|
+
3. **Surface the unknowns** — list assumptions and open questions that would change the answer. Mark which are
|
|
26
|
+
**blocking** (must resolve before planning) vs. deferrable.
|
|
27
|
+
4. **Converge — ask, don't guess.** Present the directions as **explicit numbered options** and let the user
|
|
28
|
+
choose (CLAUDE.md discipline: a decision point = multiple choice, never a prose either/or). Record the
|
|
29
|
+
chosen direction + the rejected ones with the one-line reason they lost.
|
|
30
|
+
5. **Hand off.** The chosen direction + resolved constraints flow into `spec-planning`; a lasting
|
|
31
|
+
architectural choice made here is recorded with [[adr]].
|
|
32
|
+
|
|
33
|
+
## Guardrails
|
|
34
|
+
- **Bounded, not open-ended.** Divergence has a stop: 2–4 options, then converge. Endless ideation with no
|
|
35
|
+
decision is the failure mode, not thoroughness.
|
|
36
|
+
- **No premature convergence either.** Don't collapse to the first idea to look decisive — the point is that
|
|
37
|
+
the option space was actually explored before a direction was picked.
|
|
38
|
+
- **Evidence over invention.** Read the existing code/data and state assumptions explicitly; a plausible guess
|
|
39
|
+
presented as fact is worse than a named unknown.
|
|
40
|
+
- **Token discipline** ([[token-budget]]): the options + the decision are a short summary to the main thread;
|
|
41
|
+
push a long exploration to `docs/DISCOVERY.md` and return the option headings + the choice.
|
|
42
|
+
|
|
43
|
+
## DoD (this skill's contribution)
|
|
44
|
+
- The real goal is stated separately from the requested solution.
|
|
45
|
+
- 2–4 distinct directions exist, each with its trade-off, including a minimal option.
|
|
46
|
+
- Blocking unknowns are named and were asked as explicit options — nothing ambiguous was filled by guessing.
|
|
47
|
+
- A direction is chosen and ready to enter [[spec-planning]] (rejected options logged with their reason).
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ci-pipeline
|
|
3
|
+
description: |
|
|
4
|
+
CI pipeline discipline: lint→build→test→quality→security, fail-fast, deterministic build, secret handling, PR gates.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# CI Pipeline
|
|
8
|
+
|
|
9
|
+
<!-- routing-eval reads the next line; why it sits in the body: AGENT_TEMPLATE.md -->
|
|
10
|
+
Trigger phrases: "ci", "pipeline", "github actions", "jenkins", "build pipeline", "pr gate", "pr check", "build fail", "build broke", "ci is failing", "workflow"
|
|
11
|
+
|
|
12
|
+
## Stages (fail-fast — stop if it breaks early)
|
|
13
|
+
1. **Lint / format** — style and static analysis
|
|
14
|
+
2. **Build** — 0 warnings / 0 errors
|
|
15
|
+
3. **Test** — unit + integration, coverage collected
|
|
16
|
+
4. **Quality** — `sonarqube-check` quality gate
|
|
17
|
+
5. **Security** — `dependency-audit` + `security-scan` (where applicable)
|
|
18
|
+
6. **Artifact / packaging** — (deployment is separate, `deploy`)
|
|
19
|
+
|
|
20
|
+
## Principles
|
|
21
|
+
- **Deterministic:** dependencies pinned, cache keyed correctly; no "it worked on my machine".
|
|
22
|
+
- **Secret management:** CI secret store; NO plaintext secrets in the repo/logs (overlaps with trace scan).
|
|
23
|
+
- **PR gate:** quality gate + tests must pass; a red build is not merged.
|
|
24
|
+
- **Branch protection:** direct push to main is disabled; PR + review required.
|
|
25
|
+
|
|
26
|
+
## When a stage fails
|
|
27
|
+
1. **Fetch the failing job's log first** — `gh run view --log-failed`, `glab ci trace`, `jenkins-cli console <job>`,
|
|
28
|
+
whichever this project's host provides — and quote the failing lines: a status icon names which job broke, never why.
|
|
29
|
+
Log unreachable (no access, retention expired, the job never started) → report exactly that; never infer the cause.
|
|
30
|
+
2. **Reproduce with the exact command the pipeline runs**, copied out of the CI config — same flags, same env, same
|
|
31
|
+
versions. Green locally is not a pass: the environment difference is now the defect, so take it to `systematic-debugging`.
|
|
32
|
+
3. **A re-run is not a fix.** Re-running until it passes hides the cause; re-run only to establish that a failure is
|
|
33
|
+
intermittent — and an intermittent failure in this repo's own suite is a bug (`testing`), not a retry.
|
|
34
|
+
4. **Say which failures aren't yours.** A required check owned by another change, or an external service that was
|
|
35
|
+
down, is reported out of scope with the job named — silence about it reads as a clean run.
|
|
36
|
+
|
|
37
|
+
## DoD
|
|
38
|
+
- All stages green; PR gates enforced; no secret leakage; build reproducible.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: commit-message
|
|
3
|
+
description: |
|
|
4
|
+
Conventional Commits: reads the staged diff and proposes `type(scope): summary`, with body/footer when needed.
|
|
5
|
+
One logical change = one commit. crew-commit-agent applies it.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Commit Message (Conventional Commits v1.0.0)
|
|
9
|
+
|
|
10
|
+
<!-- routing-eval reads the next line; why it sits in the body: AGENT_TEMPLATE.md -->
|
|
11
|
+
Trigger phrases: "commit message", "make a commit", "conventional commit", "write a commit", "git commit"
|
|
12
|
+
|
|
13
|
+
Format: `type(scope): summary` + (optional blank line + body) + (optional footer).
|
|
14
|
+
|
|
15
|
+
## The project decides the format and the language — read that FIRST
|
|
16
|
+
Conventional Commits below is the **default**, not a law. Before writing anything, read `./CLAUDE.md` for a
|
|
17
|
+
`## Conventions` section (`Commit language:` / `Commit format:`). A declared format REPLACES the shape below —
|
|
18
|
+
ticket-prefixed subjects, smart-commit trailers (`#comment`, `#time`), gitmoji, whatever the team runs on. A
|
|
19
|
+
declared language replaces "the project's established language" guess. Nothing declared → the defaults here.
|
|
20
|
+
|
|
21
|
+
**Whatever the request hands you verbatim — a ticket id, a `#time 1d`, a required prefix — goes into the
|
|
22
|
+
message EXACTLY as given.** Rewriting a literal someone typed is the worst failure this skill has: it looks
|
|
23
|
+
correct and books the wrong number. If a literal contradicts the format, say so and ask; never silently adjust
|
|
24
|
+
it. Same rule for the rest of the message: everything else is yours to word, the literals are not.
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
## Type (required)
|
|
28
|
+
- `feat` — new feature · `fix` — bug fix
|
|
29
|
+
- `docs` — docs only · `refactor` — restructure with no behavior change
|
|
30
|
+
- `perf` — performance · `test` — add/fix tests
|
|
31
|
+
- `build` — build/dependency · `ci` — CI configuration
|
|
32
|
+
- `chore` — maintenance/automated · `revert` — revert a previous commit
|
|
33
|
+
- `style` — formatting (no logic)
|
|
34
|
+
|
|
35
|
+
### Which type? (deciding when ambiguous)
|
|
36
|
+
- A new capability for the user? → `feat`. Fixing an existing wrong behavior? → `fix`.
|
|
37
|
+
- Behavior the same, only the structure changed? → `refactor` (if behavior changed it's `feat`/`fix`, not refactor).
|
|
38
|
+
- Touched only tests/docs/formatting? → `test`/`docs`/`style` (don't touch code logic).
|
|
39
|
+
|
|
40
|
+
## Scope (optional, preferred)
|
|
41
|
+
The affected area/module: `auth`, `api`, `backend`, `db`, `frontend`, `session`, `agent`, etc.
|
|
42
|
+
One word, consistent with the project's module name.
|
|
43
|
+
|
|
44
|
+
## Summary line
|
|
45
|
+
- **In the project's established language** (English by default for open source), imperative/summary mood, start lowercase, NO period at the end, ≤ ~72 characters.
|
|
46
|
+
- Say **what it does**, not how; avoid vague words ("fix", "update", "wip").
|
|
47
|
+
✅ `feat(auth): one-time code TTL + brute-force limit`
|
|
48
|
+
❌ `fix: bug` · ❌ `update` · ❌ `changes`
|
|
49
|
+
|
|
50
|
+
## Body (optional — recommended for meaningful changes)
|
|
51
|
+
After a blank line: the **WHY** (motivation) + notable consequences/tradeoffs. Wrap at ~72 characters.
|
|
52
|
+
Leave context for the future reader who opens git-blame — the diff already shows the "what"; you write the "why".
|
|
53
|
+
|
|
54
|
+
## Footer (optional)
|
|
55
|
+
- `BREAKING CHANGE: <description>` — a backward-incompatible breaking change (triggers SemVer MAJOR, `release` skill).
|
|
56
|
+
- `Refs: #<issue>` / `Closes #<issue>`.
|
|
57
|
+
|
|
58
|
+
## Atomic commit — splitting a mixed diff
|
|
59
|
+
If a diff contains several logical changes, **split it**; don't cram it into one commit:
|
|
60
|
+
```bash
|
|
61
|
+
git add -p # pick hunk by hunk; stage related changes separately
|
|
62
|
+
git add <specific/file>
|
|
63
|
+
```
|
|
64
|
+
Each commit focused on a single topic; "feat + fix + refactor" doesn't belong in one commit.
|
|
65
|
+
|
|
66
|
+
## Good / bad
|
|
67
|
+
|
|
68
|
+
Worked good-vs-bad commit examples: **`references/examples.md`**.
|
|
69
|
+
|
|
70
|
+
## Rules
|
|
71
|
+
- **Atomic:** one logical change = one commit.
|
|
72
|
+
- **No commit without DoD:** don't propose a message until `/simplify` + tests green + (if SonarQube is used) `sonarqube-check` 0/0/0/0 pass.
|
|
73
|
+
- If there is no staged diff, warn; ask the user about the `git add` scope with explicit options.
|
|
74
|
+
- Don't run `git commit` silently; propose the message, **wait for approval**.
|
|
75
|
+
|
|
76
|
+
## Prohibitions (absolute — see CLAUDE.md §4)
|
|
77
|
+
- **No AI trace:** no co-author trailer, auto-generation footer, or robot emoji in the subject/body;
|
|
78
|
+
words naming an AI assistant, model, or coding tool, and the `.claude` name, do not appear in the message.
|
|
79
|
+
- **No vendor name:** the third-party template/skeleton name and any "vendor copy / cleanup" disclosure are not written in the message (§4.2).
|
|
80
|
+
- **Human, natural language:** the message is natural, technical, and in the project's established language (English by default for open source).
|
|
81
|
+
- **Approval:** commit only when the user says "commit"; "done" is not approval (§4.4).
|
|
82
|
+
- **Destructive:** amend / reset / force / `--no-verify` only on an explicit request; the hook is not skipped (§4.5).
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Good / bad commit examples
|
|
2
|
+
|
|
3
|
+
| ✅ Good | ❌ Bad |
|
|
4
|
+
|---|---|
|
|
5
|
+
| `fix(db): return 404 instead of 403 on IDOR (prevent entity leak)` | `fix: db issue` |
|
|
6
|
+
| `refactor(api): consolidate query handlers into one contract` | `refactor stuff` |
|
|
7
|
+
| `feat(session): session-health line + threshold rule` | `feat: added new stuff` |
|
|
8
|
+
| `revert: "feat(auth): code TTL"` (sha) | `reverted it` |
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: confidence-check
|
|
3
|
+
description: |
|
|
4
|
+
Readiness gate BEFORE writing implementation code: does this already exist, does it fit the project's
|
|
5
|
+
architecture, is the API claim actually checked, is there a working reference, is the root cause known.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Confidence Check — earn the right to start
|
|
9
|
+
|
|
10
|
+
<!-- routing-eval reads the next line; why it sits in the body: AGENT_TEMPLATE.md -->
|
|
11
|
+
Trigger phrases: "confidence check", "ready to implement", "before I start", "am I sure enough", "readiness"
|
|
12
|
+
|
|
13
|
+
## When
|
|
14
|
+
Right before implementation code gets written for anything beyond a one-line change, and *after* the scope is
|
|
15
|
+
clear ([[spec-planning]] / planner). Every other gate in Crewforth fires at the end — review, DoD, the commit
|
|
16
|
+
approval. Those catch bad code. None of them catch **good code that should never have been written**: the
|
|
17
|
+
duplicate of a helper that already exists, the pattern that fights the project's architecture, the call built
|
|
18
|
+
against an API that behaves differently than remembered. That waste is invisible to a reviewer, because what
|
|
19
|
+
they see is a clean diff.
|
|
20
|
+
|
|
21
|
+
## The six checks
|
|
22
|
+
Each is answered with **evidence**, not with a feeling. Name what you ran or read.
|
|
23
|
+
|
|
24
|
+
| # | Check | How it is actually answered |
|
|
25
|
+
|---|---|---|
|
|
26
|
+
| 1 | **Does it already exist?** | Grep/Glob the codebase for the behaviour *and* its likely other names. A near-duplicate counts. |
|
|
27
|
+
| 2 | **Does it fit this project?** | Read `CLAUDE.md` + the relevant project skill. Same stack, same pattern, no new dependency smuggled in. |
|
|
28
|
+
| 3 | **Is the external claim verified?** | The API / library / config behaviour you are relying on: read the real docs or the installed source. Recalled API shapes are the single most common wrong assumption. |
|
|
29
|
+
| 4 | **Is there a working reference?** | An existing call site in this repo, or a known-good implementation. "It should work like this" is not one. |
|
|
30
|
+
| 5 | **Is the root cause known?** | For a fix: the *cause*, not the symptom. Unknown → this is a [[systematic-debugging]] task, not an implementation task. |
|
|
31
|
+
| 6 | **Can it be PROVEN when it is done — with what is running right now?** | Name the thing that will show it works — the suite, a migration applied to a real database, a request against a running service — and confirm it is reachable *before* starting, not after. One command. Measured: an agent spent 44 minutes and 167k tokens producing a migration, then found the database daemon was down and returned unverified. A precondition discovered at the end costs the whole run. |
|
|
32
|
+
|
|
33
|
+
## The verdict is not a score
|
|
34
|
+
The tempting form is a weighted score with a threshold. It is theatre: with six checks and any sane bar, a
|
|
35
|
+
single failure sinks it anyway, so the weights only decorate a decision that was already binary. So: **any "no"
|
|
36
|
+
is a stop.** Say which check failed and do the one thing that answers it — search, read the doc, find the
|
|
37
|
+
reference, debug the cause — then start. If the user wants to proceed with a known gap, that is their call to
|
|
38
|
+
make explicitly, and it gets written down as an assumption, not swallowed.
|
|
39
|
+
|
|
40
|
+
Checks 3–6 do not apply to every task (a pure refactor has no external claim and no bug; a change the suite alone
|
|
41
|
+
proves needs nothing brought up). Mark those **n/a**
|
|
42
|
+
with a reason — n/a is a judgement you are stating, not a check you are skipping.
|
|
43
|
+
|
|
44
|
+
An ambiguity you cannot resolve is not a failed check — it is a `[NEEDS CLARIFICATION: …]` marker
|
|
45
|
+
([[spec-planning]]) carried into the plan. Guessing it and passing check 2 is the failure mode this gate exists
|
|
46
|
+
to catch.
|
|
47
|
+
|
|
48
|
+
## A bypassed gate leaves a record
|
|
49
|
+
Gates get bypassed, legitimately: the user accepts a known gap, a DoD item is deferred, scope is trimmed under
|
|
50
|
+
time pressure. What must not happen is the bypass being *spoken and forgotten* — three weeks later nobody can
|
|
51
|
+
say whether a rule was weighed and overridden or simply missed, and those two are indistinguishable from the
|
|
52
|
+
code. That gap is the missing half of "rule → gate": Crewforth enforces the rule at the tool level, and this line is
|
|
53
|
+
the record of a human deliberately stepping past it.
|
|
54
|
+
|
|
55
|
+
So when a gate is knowingly bypassed, write one line where the decision lives — the ADR for anything lasting
|
|
56
|
+
([[adr]]), otherwise the plan's assumptions section:
|
|
57
|
+
|
|
58
|
+
`BYPASSED <gate> — <why> — asked by <who> — revisit: <condition or date>`
|
|
59
|
+
|
|
60
|
+
The `revisit` field is what separates a decision from a leak: a bypass with no condition attached is permanent
|
|
61
|
+
by default, and nobody chose that. Never write this on the model's own authority — a bypass is the user's call,
|
|
62
|
+
so the line records *their* decision, and its absence means the gate was not bypassed at all.
|
|
63
|
+
|
|
64
|
+
## Output
|
|
65
|
+
Six lines, one per check: `✅ <what was run/read>` or `❌ <what is missing>` or `n/a — <why>`. Then either
|
|
66
|
+
"starting" or the single action that unblocks it. Keep it to the main thread; it is a handful of lines, not a
|
|
67
|
+
document.
|
|
68
|
+
|
|
69
|
+
## Fix the deciding rule before you see the options
|
|
70
|
+
When this check ends in a choice — which approach, which library, which of three designs — write down what would
|
|
71
|
+
make an option **win**, and what would **disqualify** one, *before* generating or evaluating any. A criterion
|
|
72
|
+
chosen after the options exist is a criterion shaped by them: it will quietly favour the one already preferred,
|
|
73
|
+
and nothing in the output will show that it did.
|
|
74
|
+
|
|
75
|
+
Write the **kill criterion** in the same breath: what would make you abandon the whole approach. An option set
|
|
76
|
+
with no losing condition is a preference wearing an analysis.
|
|
77
|
+
|
|
78
|
+
> Honest boundary: this one is discipline, not a gate. Nothing can check whether the rule was written before the
|
|
79
|
+
> options or backfilled after them — the value is that the user can see the rule stated first and argue with it,
|
|
80
|
+
> which is impossible when the criterion never leaves your head. Treat it as cheap insurance, not as proof.
|
|
81
|
+
|
|
82
|
+
## DoD (this skill's contribution)
|
|
83
|
+
- Every check is answered with a named command, file, or document — never with a recollection.
|
|
84
|
+
- Any "no" was resolved before implementation started, or is recorded as a user-accepted assumption.
|
|
85
|
+
- Check 1 was answered by an actual search, not by "I don't think we have one".
|
|
86
|
+
- A fix with an unknown cause went to [[systematic-debugging]] instead of being implemented on a guess.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: crew-board
|
|
3
|
+
description: Experimental: team board — claim an item, hand it over, complete it.
|
|
4
|
+
argument-hint: "[claim <id> | done <id> | drop <id> | add <id> <title> | init | sync]"
|
|
5
|
+
disable-model-invocation: true
|
|
6
|
+
metadata:
|
|
7
|
+
kind: command
|
|
8
|
+
experimental: true
|
|
9
|
+
---
|
|
10
|
+
# /crew-board
|
|
11
|
+
Argument: $ARGUMENTS
|
|
12
|
+
|
|
13
|
+
Apply the `teamboard` skill. The engine is `bash .claude/hooks/board.sh`; never hand-edit the board.
|
|
14
|
+
|
|
15
|
+
**Never make the user learn the syntax.** They should be able to run `/crew-board` and answer questions from
|
|
16
|
+
there; `claim 3` and `done 3` are yours to type, not theirs. Every step below ends in a question with explicit
|
|
17
|
+
options, not an instruction to go and type something.
|
|
18
|
+
|
|
19
|
+
- **no argument** → `board.sh status`, plus `board.sh decisions` when the session-start line says decisions are
|
|
20
|
+
unread. Report: who holds what and for how long, what is claimable, what is blocked by which item, any STALE
|
|
21
|
+
claim, and any unread team decision. Then **ask which item to take, as options** (the claimable ones, each
|
|
22
|
+
labelled with its title and why it is a sensible next pick, plus "just looking"). On their answer, claim it —
|
|
23
|
+
do not tell them to run a claim command. If nothing is claimable, say what would unblock what, and stop.
|
|
24
|
+
- **`claim <id>`** → `board.sh claim <id>`. A refusal is an answer, not an error: name who holds it and offer the
|
|
25
|
+
claimable alternatives. Never work around a refusal. On success it prints the **connected work** — what each
|
|
26
|
+
dependency actually delivered, and which items are waiting on this one. Read that back to the user before
|
|
27
|
+
writing anything; it is the context the previous person had and you do not.
|
|
28
|
+
- **`done <id>`** → ask for what shipped (commit/PR), then `board.sh done <id> "<note>"`, tell the user which
|
|
29
|
+
items this unblocked, and **immediately offer the next item as options** — closing one and picking the next is
|
|
30
|
+
one movement, not two commands to remember.
|
|
31
|
+
- **`decide "<what>"`** → `board.sh decide`. Anything that changes how OTHER work must be done — a contract, a
|
|
32
|
+
rejected approach, a constraint discovered the hard way — goes here the moment it is settled, while the reason
|
|
33
|
+
is still in the session. It reaches every teammate's next session opening; a decision that stays in this chat
|
|
34
|
+
reaches nobody. Write what was decided, why, and what it means for other items; name the items it affects.
|
|
35
|
+
- **`decisions`** → list them, or read one. Read these before planning anything.
|
|
36
|
+
- **`drop <id>`** → write the handover note FIRST — exactly where it stands, which files, and why the discarded
|
|
37
|
+
approach was discarded — then `board.sh drop <id> "<note>"`. The engine refuses an empty note.
|
|
38
|
+
- **`add <id> <title> [deps]`** → add items. From `docs/PLAN.md`, carry each task's dependency edges across.
|
|
39
|
+
- **no board in this repo yet** → do not tell the user to run `init`; that is the syntax they should never have to
|
|
40
|
+
learn. Say plainly what a board is for (a teammate's in-progress work is invisible without one) and **ask, with
|
|
41
|
+
options**: set one up on this repo's own remote · set one up in a separate repository (they give the URL — for a
|
|
42
|
+
board shared across repos, or people who cannot push to the code) · not now, this is solo work. On "not now",
|
|
43
|
+
drop it and do not raise it again unprompted. On a yes, run `init` yourself, then offer to fill it from
|
|
44
|
+
`docs/PLAN.md` if one exists, or ask for the items. Report what the server accepted (custom ref namespace or the
|
|
45
|
+
orphan-branch fallback) in one line — the user should know where their board lives without having to ask.
|
|
46
|
+
- **`init`** → the same thing when asked for directly. `init --remote <url>` puts the board in a separate
|
|
47
|
+
repository. Run by ONE person, once — everyone else configures nothing and the board reaches them on its own.
|
|
48
|
+
If a board already exists this fetches it rather than creating a second.
|
|
49
|
+
- **`sync`** → fetch and re-read; use it when the board looks stale or a gate message disagrees with reality.
|
|
50
|
+
- **`off` / `on`** → release every board gate for this repo (`off --global` for all of them) and put them back.
|
|
51
|
+
The board is untouched either way. A repo that never ran `init` has no gates to begin with — never imply the
|
|
52
|
+
user must turn something off to work alone.
|
|
53
|
+
|
|
54
|
+
Before writing any code for an item, confirm this user holds it. Commits are gated: `[#<id>]` for a held item,
|
|
55
|
+
`[chore]` otherwise. Strip secrets from anything written to the board — it is pushed to the whole team.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: crew-brainstorm
|
|
3
|
+
description: Diverge before planning — turn a fuzzy ask into scoped options and a chosen direction.
|
|
4
|
+
argument-hint: "[fuzzy idea / problem to explore]"
|
|
5
|
+
disable-model-invocation: true
|
|
6
|
+
metadata:
|
|
7
|
+
kind: command
|
|
8
|
+
---
|
|
9
|
+
# /crew-brainstorm
|
|
10
|
+
Argument: $ARGUMENTS
|
|
11
|
+
|
|
12
|
+
Delegate to the @agent-crew-planner agent applying the **brainstorm** skill. For an under-defined ask:
|
|
13
|
+
1. Restate the real goal separately from the requested solution.
|
|
14
|
+
2. Generate **2–4 genuinely different** directions (include a cheap/minimal one); give each its trade-off.
|
|
15
|
+
3. Surface assumptions + open questions; mark which are blocking.
|
|
16
|
+
4. Ask the user to choose WITH **explicit numbered options**; log the rejected directions + why.
|
|
17
|
+
|
|
18
|
+
Write a long exploration to `docs/DISCOVERY.md`; return the option headings + the chosen direction (token-budget).
|
|
19
|
+
Do NOT write code — this is discovery. Once a direction is chosen, hand off to `/crew-plan` (spec-planning).
|