specrails-core 3.8.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/specrails-core.js +23 -1
- package/bin/tui-installer.mjs +80 -38
- package/commands/enrich.md +21 -23
- package/docs/installation.md +0 -3
- package/install.sh +158 -45
- package/package.json +4 -2
- package/templates/agents/sr-developer.md +27 -4
- package/templates/agents/sr-reviewer.md +19 -4
- package/templates/claude-md/CLAUDE-quickstart.md +0 -4
- package/templates/commands/specrails/enrich.md +21 -23
- package/templates/commands/specrails/implement.md +114 -18
- package/templates/commands/specrails/propose-spec.md +2 -0
- package/templates/settings/integration-contract.json +0 -2
- package/templates/skills/sr-implement/SKILL.md +114 -18
- package/.claude/skills/openspec-apply-change/SKILL.md +0 -156
- package/.claude/skills/openspec-archive-change/SKILL.md +0 -114
- package/.claude/skills/openspec-bulk-archive-change/SKILL.md +0 -246
- package/.claude/skills/openspec-continue-change/SKILL.md +0 -118
- package/.claude/skills/openspec-explore/SKILL.md +0 -290
- package/.claude/skills/openspec-ff-change/SKILL.md +0 -101
- package/.claude/skills/openspec-new-change/SKILL.md +0 -74
- package/.claude/skills/openspec-onboard/SKILL.md +0 -529
- package/.claude/skills/openspec-sync-specs/SKILL.md +0 -138
- package/.claude/skills/openspec-verify-change/SKILL.md +0 -168
- package/prompts/analyze-codebase.md +0 -87
- package/prompts/generate-personas.md +0 -61
- package/prompts/infer-conventions.md +0 -72
- package/templates/commands/specrails/setup.md +0 -1533
package/install.sh
CHANGED
|
@@ -127,7 +127,8 @@ if [[ -n "$CUSTOM_ROOT_DIR" ]]; then
|
|
|
127
127
|
fi
|
|
128
128
|
|
|
129
129
|
# Detect if running from within the specrails source repo itself
|
|
130
|
-
|
|
130
|
+
# Note: REPO_ROOT must be non-empty for the glob match — when empty, * matches everything.
|
|
131
|
+
if [[ -z "$CUSTOM_ROOT_DIR" && -n "$REPO_ROOT" && -f "$SCRIPT_DIR/install.sh" && -d "$SCRIPT_DIR/templates" && "$SCRIPT_DIR" == "$REPO_ROOT"* ]]; then
|
|
131
132
|
# We're inside the specrails source — ask for target repo
|
|
132
133
|
echo ""
|
|
133
134
|
echo -e "${YELLOW}⚠${NC} You're running the installer from inside the specrails source repo."
|
|
@@ -144,11 +145,24 @@ if [[ -z "$CUSTOM_ROOT_DIR" && -f "$SCRIPT_DIR/install.sh" && -d "$SCRIPT_DIR/te
|
|
|
144
145
|
echo "Error: path does not exist or is not accessible: $TARGET_PATH" >&2
|
|
145
146
|
exit 1
|
|
146
147
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
148
|
+
fi
|
|
149
|
+
|
|
150
|
+
# Auto-init git if the target directory is not a git repository
|
|
151
|
+
if [[ -z "$REPO_ROOT" || ! -d "$REPO_ROOT/.git" ]]; then
|
|
152
|
+
# Resolve REPO_ROOT to cwd if still empty (no git found anywhere)
|
|
153
|
+
if [[ -z "$REPO_ROOT" ]]; then
|
|
154
|
+
REPO_ROOT="$(pwd)"
|
|
155
|
+
fi
|
|
156
|
+
if [[ "$AUTO_YES" == true ]]; then
|
|
157
|
+
git -C "$REPO_ROOT" init -q 2>/dev/null
|
|
158
|
+
else
|
|
159
|
+
echo ""
|
|
160
|
+
echo -e "${YELLOW}⚠${NC} ${REPO_ROOT} is not a git repository."
|
|
161
|
+
read -p " Initialize git? (y/n): " INIT_GIT || INIT_GIT="n"
|
|
162
|
+
if [[ "$INIT_GIT" == "y" || "$INIT_GIT" == "Y" ]]; then
|
|
163
|
+
git -C "$REPO_ROOT" init -q 2>/dev/null
|
|
164
|
+
else
|
|
165
|
+
echo " Aborted. specrails requires a git repository."
|
|
152
166
|
exit 0
|
|
153
167
|
fi
|
|
154
168
|
fi
|
|
@@ -229,9 +243,9 @@ print_header
|
|
|
229
243
|
|
|
230
244
|
step "Phase 1: Checking prerequisites"
|
|
231
245
|
|
|
232
|
-
# 1.1 Git repository
|
|
246
|
+
# 1.1 Git repository (should be resolved by now — early init or --root-dir)
|
|
233
247
|
if [[ -z "$REPO_ROOT" ]]; then
|
|
234
|
-
fail "
|
|
248
|
+
fail "Could not determine target directory."
|
|
235
249
|
echo " Usage: install.sh [--root-dir <path>]"
|
|
236
250
|
exit 1
|
|
237
251
|
fi
|
|
@@ -502,6 +516,16 @@ else
|
|
|
502
516
|
fi
|
|
503
517
|
|
|
504
518
|
# 1.5 OpenSpec CLI
|
|
519
|
+
# Read pinned version from package.json (specrails.openspecVersion field)
|
|
520
|
+
_openspec_pkg_version=""
|
|
521
|
+
if [[ -f "$SCRIPT_DIR/package.json" ]]; then
|
|
522
|
+
_openspec_pkg_version=$(python3 -c "import json; d=json.load(open('$SCRIPT_DIR/package.json')); print(d.get('specrails',{}).get('openspecVersion',''))" 2>/dev/null || true)
|
|
523
|
+
fi
|
|
524
|
+
_openspec_install_spec="@openspec/cli"
|
|
525
|
+
if [[ -n "$_openspec_pkg_version" ]]; then
|
|
526
|
+
_openspec_install_spec="@openspec/cli@${_openspec_pkg_version}"
|
|
527
|
+
fi
|
|
528
|
+
|
|
505
529
|
if command -v openspec &> /dev/null; then
|
|
506
530
|
OPENSPEC_VERSION=$(openspec --version 2>/dev/null || echo "unknown")
|
|
507
531
|
ok "OpenSpec CLI: $OPENSPEC_VERSION"
|
|
@@ -510,17 +534,21 @@ elif [ -f "$REPO_ROOT/node_modules/.bin/openspec" ]; then
|
|
|
510
534
|
ok "OpenSpec CLI: found in node_modules"
|
|
511
535
|
HAS_OPENSPEC=true
|
|
512
536
|
else
|
|
513
|
-
warn "OpenSpec CLI not found."
|
|
514
537
|
if [ "$HAS_NPM" = true ]; then
|
|
515
|
-
|
|
538
|
+
# Auto-install in --yes mode; ask otherwise
|
|
539
|
+
if [ "$AUTO_YES" = true ]; then
|
|
540
|
+
INSTALL_OPENSPEC="y"
|
|
541
|
+
else
|
|
542
|
+
read -p " OpenSpec CLI not found. Install ${_openspec_install_spec}? (y/n): " INSTALL_OPENSPEC || INSTALL_OPENSPEC="n"
|
|
543
|
+
fi
|
|
516
544
|
if [ "$INSTALL_OPENSPEC" = "y" ] || [ "$INSTALL_OPENSPEC" = "Y" ]; then
|
|
517
|
-
info "Installing
|
|
518
|
-
npm install -g
|
|
519
|
-
ok "OpenSpec CLI installed"
|
|
545
|
+
info "Installing ${_openspec_install_spec}..."
|
|
546
|
+
npm install -g "${_openspec_install_spec}" 2>/dev/null && {
|
|
547
|
+
ok "OpenSpec CLI installed ($(openspec --version 2>/dev/null || echo "${_openspec_pkg_version}"))"
|
|
520
548
|
HAS_OPENSPEC=true
|
|
521
549
|
} || {
|
|
522
550
|
warn "Global install failed. Trying local..."
|
|
523
|
-
cd "$REPO_ROOT" && npm install
|
|
551
|
+
cd "$REPO_ROOT" && npm install "${_openspec_install_spec}" 2>/dev/null && {
|
|
524
552
|
ok "OpenSpec CLI installed locally"
|
|
525
553
|
HAS_OPENSPEC=true
|
|
526
554
|
} || {
|
|
@@ -633,7 +661,7 @@ fi
|
|
|
633
661
|
step "Phase 3: Installing specrails artifacts"
|
|
634
662
|
|
|
635
663
|
# Create directory structure
|
|
636
|
-
mkdir -p "$REPO_ROOT
|
|
664
|
+
mkdir -p "$REPO_ROOT/$SPECRAILS_DIR"
|
|
637
665
|
if [[ "$CLI_PROVIDER" == "codex" ]]; then
|
|
638
666
|
# Codex: install as Agent Skills (Codex doesn't support .codex/commands/)
|
|
639
667
|
mkdir -p "$REPO_ROOT/.agents/skills/enrich"
|
|
@@ -648,8 +676,15 @@ mkdir -p "$REPO_ROOT/.specrails/setup-templates/rules"
|
|
|
648
676
|
mkdir -p "$REPO_ROOT/.specrails/setup-templates/personas"
|
|
649
677
|
mkdir -p "$REPO_ROOT/.specrails/setup-templates/claude-md"
|
|
650
678
|
mkdir -p "$REPO_ROOT/.specrails/setup-templates/settings"
|
|
651
|
-
|
|
652
|
-
|
|
679
|
+
|
|
680
|
+
# Ensure .gitignore excludes local runtime artifacts
|
|
681
|
+
_gitignore="${REPO_ROOT}/.gitignore"
|
|
682
|
+
_gitignore_entries=(".claude/agent-memory/" ".specrails/")
|
|
683
|
+
for _entry in "${_gitignore_entries[@]}"; do
|
|
684
|
+
if ! grep -qF "$_entry" "$_gitignore" 2>/dev/null; then
|
|
685
|
+
echo "$_entry" >> "$_gitignore"
|
|
686
|
+
fi
|
|
687
|
+
done
|
|
653
688
|
|
|
654
689
|
# Copy the /specrails:enrich and /specrails:doctor commands (or skills for Codex)
|
|
655
690
|
if [[ "$CLI_PROVIDER" == "codex" ]]; then
|
|
@@ -722,9 +757,6 @@ models:
|
|
|
722
757
|
preset: balanced
|
|
723
758
|
defaults: { model: sonnet }
|
|
724
759
|
overrides: {}
|
|
725
|
-
quick_context:
|
|
726
|
-
product_description: ""
|
|
727
|
-
target_users: ""
|
|
728
760
|
agent_teams: ${_ic_agent_teams}
|
|
729
761
|
YAML
|
|
730
762
|
ok "Written .specrails/install-config.yaml (defaults)"
|
|
@@ -744,11 +776,19 @@ if [[ "$FROM_CONFIG" == true ]]; then
|
|
|
744
776
|
# Parse selected agents from inline YAML list: selected: [sr-architect, sr-developer, ...]
|
|
745
777
|
_selected_raw=$(grep '^ selected:' "$_cfg_to_read" | sed 's/.*\[//;s/\].*//;s/,/ /g' || true)
|
|
746
778
|
if [[ -n "$_selected_raw" ]]; then
|
|
779
|
+
# Core agents are always kept — the pipeline depends on them
|
|
780
|
+
_core_agents="sr-architect sr-developer sr-reviewer sr-merge-resolver"
|
|
747
781
|
_agents_dir="${REPO_ROOT}/.specrails/setup-templates/agents"
|
|
748
782
|
_removed=0
|
|
749
783
|
for _agent_file in "$_agents_dir/"*.md; do
|
|
750
784
|
[[ -f "$_agent_file" ]] || continue
|
|
751
785
|
_agent_name="$(basename "$_agent_file" .md)"
|
|
786
|
+
|
|
787
|
+
# Never remove core agents
|
|
788
|
+
if echo " $_core_agents " | grep -q " ${_agent_name} "; then
|
|
789
|
+
continue
|
|
790
|
+
fi
|
|
791
|
+
|
|
752
792
|
_in_selected=false
|
|
753
793
|
for _sel in $_selected_raw; do
|
|
754
794
|
# Strip whitespace/commas from parsed token
|
|
@@ -851,11 +891,6 @@ if [ ! -f "${REPO_ROOT}/$SPECRAILS_DIR/security-exemptions.yaml" ]; then
|
|
|
851
891
|
ok "Created $SPECRAILS_DIR/security-exemptions.yaml"
|
|
852
892
|
fi
|
|
853
893
|
|
|
854
|
-
# Copy prompts
|
|
855
|
-
if [ -d "$SCRIPT_DIR/prompts" ] && [ "$(ls -A "$SCRIPT_DIR/prompts" 2>/dev/null)" ]; then
|
|
856
|
-
cp -r "$SCRIPT_DIR/prompts/"* "$REPO_ROOT/.specrails/setup-templates/prompts/"
|
|
857
|
-
ok "Installed prompts"
|
|
858
|
-
fi
|
|
859
894
|
|
|
860
895
|
# ─────────────────────────────────────────────
|
|
861
896
|
# Phase 3c: Quick-tier direct placement
|
|
@@ -869,15 +904,6 @@ if [[ "$TIER" == "quick" ]]; then
|
|
|
869
904
|
|
|
870
905
|
_templates="${REPO_ROOT}/.specrails/setup-templates"
|
|
871
906
|
_project_name="$(basename "$REPO_ROOT")"
|
|
872
|
-
_quick_product_desc=""
|
|
873
|
-
_quick_target_users=""
|
|
874
|
-
|
|
875
|
-
# Read quick_context from install-config.yaml if available
|
|
876
|
-
_qc_file="${CONFIG_PATH:-${REPO_ROOT}/.specrails/install-config.yaml}"
|
|
877
|
-
if [[ -f "$_qc_file" ]]; then
|
|
878
|
-
_quick_product_desc=$(grep '^\s*product_description:' "$_qc_file" 2>/dev/null | head -1 | sed 's/.*product_description:[[:space:]]*//' | sed 's/^"//;s/"$//' || true)
|
|
879
|
-
_quick_target_users=$(grep '^\s*target_users:' "$_qc_file" 2>/dev/null | head -1 | sed 's/.*target_users:[[:space:]]*//' | sed 's/^"//;s/"$//' || true)
|
|
880
|
-
fi
|
|
881
907
|
|
|
882
908
|
# VPC/persona-dependent agents are excluded from Quick tier (require enrichment)
|
|
883
909
|
_quick_excluded_agents="sr-product-manager sr-product-analyst"
|
|
@@ -903,8 +929,6 @@ if [[ "$TIER" == "quick" ]]; then
|
|
|
903
929
|
# Substitute known placeholders
|
|
904
930
|
sed -i.bak \
|
|
905
931
|
-e "s|{{PROJECT_NAME}}|${_project_name}|g" \
|
|
906
|
-
-e "s|{{PROJECT_DESCRIPTION}}|${_quick_product_desc}|g" \
|
|
907
|
-
-e "s|{{TARGET_USERS}}|${_quick_target_users}|g" \
|
|
908
932
|
-e "s|{{MEMORY_PATH}}|.claude/agent-memory/${_name}/|g" \
|
|
909
933
|
-e "s|{{SECURITY_EXEMPTIONS_PATH}}|${SPECRAILS_DIR}/security-exemptions.yaml|g" \
|
|
910
934
|
-e "s|{{PERSONA_DIR}}|${SPECRAILS_DIR}/agents/personas/|g" \
|
|
@@ -916,6 +940,11 @@ if [[ "$TIER" == "quick" ]]; then
|
|
|
916
940
|
# Create agent memory directory
|
|
917
941
|
mkdir -p "${REPO_ROOT}/.claude/agent-memory/${_name}"
|
|
918
942
|
|
|
943
|
+
# Agents that write explanation records need the shared explanations dir
|
|
944
|
+
if [[ "$_name" == "sr-architect" || "$_name" == "sr-reviewer" ]]; then
|
|
945
|
+
mkdir -p "${REPO_ROOT}/.claude/agent-memory/explanations"
|
|
946
|
+
fi
|
|
947
|
+
|
|
919
948
|
(( _agent_count++ )) || true
|
|
920
949
|
done
|
|
921
950
|
if (( _agent_skipped > 0 )); then
|
|
@@ -925,8 +954,38 @@ if [[ "$TIER" == "quick" ]]; then
|
|
|
925
954
|
fi
|
|
926
955
|
fi
|
|
927
956
|
|
|
928
|
-
#
|
|
929
|
-
|
|
957
|
+
# Dynamic command exclusion based on installed agents.
|
|
958
|
+
# Each command maps to the agent(s) it depends on — if the agent
|
|
959
|
+
# wasn't installed, the command is excluded automatically.
|
|
960
|
+
#
|
|
961
|
+
# Dependency map (command → required agent):
|
|
962
|
+
# auto-propose-backlog-specs → sr-product-manager
|
|
963
|
+
# get-backlog-specs → sr-product-analyst
|
|
964
|
+
# vpc-drift → sr-product-manager, sr-product-analyst
|
|
965
|
+
# merge-resolve → sr-merge-resolver
|
|
966
|
+
# team-debug, team-review → AGENT_TEAMS flag
|
|
967
|
+
_quick_excluded_cmds=""
|
|
968
|
+
_installed_agents_dir="${REPO_ROOT}/${SPECRAILS_DIR}/agents"
|
|
969
|
+
|
|
970
|
+
# Agent-dependent commands
|
|
971
|
+
if ! ls "$_installed_agents_dir/sr-product-manager.md" &>/dev/null; then
|
|
972
|
+
_quick_excluded_cmds="$_quick_excluded_cmds auto-propose-backlog-specs vpc-drift"
|
|
973
|
+
fi
|
|
974
|
+
if ! ls "$_installed_agents_dir/sr-product-analyst.md" &>/dev/null; then
|
|
975
|
+
_quick_excluded_cmds="$_quick_excluded_cmds get-backlog-specs"
|
|
976
|
+
# vpc-drift needs both product agents
|
|
977
|
+
if ! echo " $_quick_excluded_cmds " | grep -q " vpc-drift "; then
|
|
978
|
+
_quick_excluded_cmds="$_quick_excluded_cmds vpc-drift"
|
|
979
|
+
fi
|
|
980
|
+
fi
|
|
981
|
+
if ! ls "$_installed_agents_dir/sr-merge-resolver.md" &>/dev/null; then
|
|
982
|
+
_quick_excluded_cmds="$_quick_excluded_cmds merge-resolve"
|
|
983
|
+
fi
|
|
984
|
+
|
|
985
|
+
# Agent Teams commands (flag-dependent, not agent-dependent)
|
|
986
|
+
if [[ "$AGENT_TEAMS" != "true" ]]; then
|
|
987
|
+
_quick_excluded_cmds="$_quick_excluded_cmds team-debug team-review"
|
|
988
|
+
fi
|
|
930
989
|
|
|
931
990
|
# --- Commands ---
|
|
932
991
|
if [[ -d "$_templates/commands/specrails" ]]; then
|
|
@@ -936,7 +995,7 @@ if [[ "$TIER" == "quick" ]]; then
|
|
|
936
995
|
[[ -f "$_src" ]] || continue
|
|
937
996
|
_cmd_name="$(basename "$_src" .md)"
|
|
938
997
|
|
|
939
|
-
# Skip
|
|
998
|
+
# Skip commands whose required agents are not installed
|
|
940
999
|
if echo " $_quick_excluded_cmds " | grep -q " ${_cmd_name} "; then
|
|
941
1000
|
continue
|
|
942
1001
|
fi
|
|
@@ -945,8 +1004,6 @@ if [[ "$TIER" == "quick" ]]; then
|
|
|
945
1004
|
cp "$_src" "$_dest"
|
|
946
1005
|
sed -i.bak \
|
|
947
1006
|
-e "s|{{PROJECT_NAME}}|${_project_name}|g" \
|
|
948
|
-
-e "s|{{PROJECT_DESCRIPTION}}|${_quick_product_desc}|g" \
|
|
949
|
-
-e "s|{{TARGET_USERS}}|${_quick_target_users}|g" \
|
|
950
1007
|
-e "s|{{MEMORY_PATH}}|.claude/agent-memory/|g" \
|
|
951
1008
|
-e "s|{{PERSONA_DIR}}|${SPECRAILS_DIR}/agents/personas/|g" \
|
|
952
1009
|
-e "s|{{SECURITY_EXEMPTIONS_PATH}}|${SPECRAILS_DIR}/security-exemptions.yaml|g" \
|
|
@@ -979,11 +1036,61 @@ if [[ "$TIER" == "quick" ]]; then
|
|
|
979
1036
|
ok "Installed integration-contract.json"
|
|
980
1037
|
fi
|
|
981
1038
|
|
|
1039
|
+
# --- Backlog config (default: local provider) ---
|
|
1040
|
+
_backlog_cfg="${REPO_ROOT}/.specrails/backlog-config.json"
|
|
1041
|
+
if [[ ! -f "$_backlog_cfg" ]]; then
|
|
1042
|
+
mkdir -p "${REPO_ROOT}/.specrails"
|
|
1043
|
+
cat > "$_backlog_cfg" <<'BCEOF'
|
|
1044
|
+
{
|
|
1045
|
+
"provider": "local",
|
|
1046
|
+
"write_access": true,
|
|
1047
|
+
"git_auto": true
|
|
1048
|
+
}
|
|
1049
|
+
BCEOF
|
|
1050
|
+
ok "Created .specrails/backlog-config.json (provider: local, git_auto: true)"
|
|
1051
|
+
fi
|
|
1052
|
+
|
|
1053
|
+
# --- Local tickets store ---
|
|
1054
|
+
_tickets_file="${REPO_ROOT}/.specrails/local-tickets.json"
|
|
1055
|
+
if [[ ! -f "$_tickets_file" ]]; then
|
|
1056
|
+
_now="$(date -u +"%Y-%m-%dT%H:%M:%S.000Z")"
|
|
1057
|
+
cat > "$_tickets_file" <<LTEOF
|
|
1058
|
+
{
|
|
1059
|
+
"schema_version": "1.0",
|
|
1060
|
+
"revision": 0,
|
|
1061
|
+
"last_updated": "${_now}",
|
|
1062
|
+
"next_id": 1,
|
|
1063
|
+
"tickets": {}
|
|
1064
|
+
}
|
|
1065
|
+
LTEOF
|
|
1066
|
+
ok "Created .specrails/local-tickets.json"
|
|
1067
|
+
fi
|
|
1068
|
+
|
|
982
1069
|
# --- Skills (OpenSpec) ---
|
|
1070
|
+
# Dynamic skill exclusion based on installed agents (mirrors command logic).
|
|
1071
|
+
# Dependency map (skill → required agent):
|
|
1072
|
+
# sr-auto-propose-backlog-specs → sr-product-manager
|
|
1073
|
+
# sr-get-backlog-specs → sr-product-analyst
|
|
1074
|
+
_quick_excluded_skills=""
|
|
1075
|
+
if ! ls "$_installed_agents_dir/sr-product-manager.md" &>/dev/null; then
|
|
1076
|
+
_quick_excluded_skills="$_quick_excluded_skills sr-auto-propose-backlog-specs"
|
|
1077
|
+
fi
|
|
1078
|
+
if ! ls "$_installed_agents_dir/sr-product-analyst.md" &>/dev/null; then
|
|
1079
|
+
_quick_excluded_skills="$_quick_excluded_skills sr-get-backlog-specs"
|
|
1080
|
+
fi
|
|
983
1081
|
if [[ -d "$_templates/skills" ]]; then
|
|
984
1082
|
mkdir -p "${REPO_ROOT}/${SPECRAILS_DIR}/skills"
|
|
985
|
-
|
|
986
|
-
|
|
1083
|
+
_skill_count=0
|
|
1084
|
+
for _skill_dir in "$_templates/skills/"*/; do
|
|
1085
|
+
[[ -d "$_skill_dir" ]] || continue
|
|
1086
|
+
_skill_name="$(basename "$_skill_dir")"
|
|
1087
|
+
if echo " $_quick_excluded_skills " | grep -q " ${_skill_name} "; then
|
|
1088
|
+
continue
|
|
1089
|
+
fi
|
|
1090
|
+
cp -r "$_skill_dir" "${REPO_ROOT}/${SPECRAILS_DIR}/skills/${_skill_name}"
|
|
1091
|
+
(( _skill_count++ )) || true
|
|
1092
|
+
done
|
|
1093
|
+
ok "Installed ${_skill_count} skill(s) to ${SPECRAILS_DIR}/skills/"
|
|
987
1094
|
fi
|
|
988
1095
|
|
|
989
1096
|
if [[ "$HUB_JSON" == true ]]; then
|
|
@@ -993,8 +1100,12 @@ fi
|
|
|
993
1100
|
|
|
994
1101
|
# Initialize OpenSpec if available and not already initialized
|
|
995
1102
|
if [ "$HAS_OPENSPEC" = true ] && [ ! -d "$REPO_ROOT/openspec" ]; then
|
|
996
|
-
|
|
997
|
-
|
|
1103
|
+
# Map specrails provider to openspec tool name
|
|
1104
|
+
_openspec_tool="claude"
|
|
1105
|
+
[[ "$CLI_PROVIDER" == "codex" ]] && _openspec_tool="codex"
|
|
1106
|
+
|
|
1107
|
+
info "Initializing OpenSpec (--tools ${_openspec_tool} --force)..."
|
|
1108
|
+
cd "$REPO_ROOT" && openspec init --tools "${_openspec_tool}" --force 2>/dev/null && {
|
|
998
1109
|
ok "OpenSpec initialized"
|
|
999
1110
|
} || {
|
|
1000
1111
|
warn "OpenSpec init failed — you can run 'openspec init' manually later"
|
|
@@ -1033,6 +1144,8 @@ if [[ "$TIER" == "quick" ]]; then
|
|
|
1033
1144
|
echo " Installed:"
|
|
1034
1145
|
echo " ${_installed_agents} agent(s) → ${SPECRAILS_DIR}/agents/"
|
|
1035
1146
|
echo " ${_installed_commands} command(s) → ${SPECRAILS_DIR}/commands/specrails/"
|
|
1147
|
+
echo " .specrails/backlog-config.json (provider: local)"
|
|
1148
|
+
echo " .specrails/local-tickets.json"
|
|
1036
1149
|
echo " .specrails/specrails-version"
|
|
1037
1150
|
echo " .specrails/specrails-manifest.json"
|
|
1038
1151
|
echo ""
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "specrails-core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "AI agent workflow system for Claude Code — installs 12 specialized agents, orchestration commands, and persona-driven product discovery into any repository",
|
|
5
5
|
"bin": {
|
|
6
6
|
"specrails-core": "bin/specrails-core.js"
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
"install.sh",
|
|
11
11
|
"update.sh",
|
|
12
12
|
"templates/",
|
|
13
|
-
"prompts/",
|
|
14
13
|
".claude/skills/",
|
|
15
14
|
"commands/",
|
|
16
15
|
"docs/",
|
|
@@ -53,6 +52,9 @@
|
|
|
53
52
|
"test": "bash tests/run-all.sh",
|
|
54
53
|
"test:coverage": "bash tests/run-coverage.sh"
|
|
55
54
|
},
|
|
55
|
+
"specrails": {
|
|
56
|
+
"openspecVersion": "1.2.0"
|
|
57
|
+
},
|
|
56
58
|
"dependencies": {
|
|
57
59
|
"@inquirer/prompts": "^7.0.0"
|
|
58
60
|
},
|
|
@@ -49,7 +49,9 @@ When an OpenSpec change is being applied, you:
|
|
|
49
49
|
4. **Implement the changes** with surgical precision across all affected layers
|
|
50
50
|
5. **Ensure consistency** with the existing codebase style, patterns, and architecture
|
|
51
51
|
|
|
52
|
-
## Workflow Protocol
|
|
52
|
+
## Workflow Protocol — Strict TDD
|
|
53
|
+
|
|
54
|
+
You MUST follow Test-Driven Development. This is non-negotiable. The cycle is: **Red → Green → Refactor**. Never write production code without a failing test first.
|
|
53
55
|
|
|
54
56
|
### Phase 1: Understand
|
|
55
57
|
- Read the OpenSpec change spec thoroughly
|
|
@@ -65,9 +67,25 @@ When an OpenSpec change is being applied, you:
|
|
|
65
67
|
- Plan the dependency graph — what depends on what
|
|
66
68
|
- Determine the implementation order
|
|
67
69
|
- Identify edge cases and error handling requirements
|
|
70
|
+
- **Plan the test strategy**: for each piece of functionality, decide what tests to write and at what level (unit, integration, E2E)
|
|
71
|
+
|
|
72
|
+
### Phase 3: Implement (TDD cycle)
|
|
73
|
+
|
|
74
|
+
**For each unit of functionality, follow this exact cycle:**
|
|
75
|
+
|
|
76
|
+
1. **RED** — Write a failing test that describes the expected behavior. Run the test. Confirm it fails for the right reason.
|
|
77
|
+
2. **GREEN** — Write the minimum production code to make the test pass. Run the test. Confirm it passes.
|
|
78
|
+
3. **REFACTOR** — Clean up the code while keeping all tests green. Run all tests after refactoring.
|
|
79
|
+
|
|
80
|
+
**TDD rules:**
|
|
81
|
+
- Never write production code without a corresponding test
|
|
82
|
+
- Write tests BEFORE the production code, not after
|
|
83
|
+
- Each test should test one specific behavior
|
|
84
|
+
- Tests must be deterministic and isolated
|
|
85
|
+
- Cover the happy path, edge cases, and error cases
|
|
86
|
+
- If the project has an existing test framework, use it. If not, set one up before writing any production code.
|
|
68
87
|
|
|
69
|
-
|
|
70
|
-
- Follow the project architecture strictly:
|
|
88
|
+
Follow the project architecture strictly:
|
|
71
89
|
```
|
|
72
90
|
{{ARCHITECTURE_DIAGRAM}}
|
|
73
91
|
```
|
|
@@ -82,12 +100,17 @@ When an OpenSpec change is being applied, you:
|
|
|
82
100
|
- Consistent formatting and style
|
|
83
101
|
|
|
84
102
|
### Phase 4: Verify
|
|
103
|
+
|
|
104
|
+
**All tests MUST pass before you hand off to the reviewer. This is a hard gate — do not proceed if any test fails.**
|
|
105
|
+
|
|
106
|
+
- Run the **full CI-equivalent verification suite** (see below)
|
|
107
|
+
- If any test fails, fix the issue and re-run ALL tests
|
|
108
|
+
- Repeat until all tests pass — there is no maximum number of attempts
|
|
85
109
|
- Review each file for adherence to conventions
|
|
86
110
|
- Ensure all imports are correct and no circular dependencies exist
|
|
87
111
|
- Verify type annotations are complete
|
|
88
112
|
- Check that error handling is comprehensive and consistent
|
|
89
113
|
- Validate that the implementation matches the spec exactly
|
|
90
|
-
- Run the **full CI-equivalent verification suite** (see below)
|
|
91
114
|
|
|
92
115
|
## CI-Equivalent Verification Suite
|
|
93
116
|
|
|
@@ -36,10 +36,12 @@ Leave empty to review all areas with equal weight.
|
|
|
36
36
|
## Your Mission
|
|
37
37
|
|
|
38
38
|
You are the last line of defense between developer output and a PR. You:
|
|
39
|
-
1.
|
|
40
|
-
2.
|
|
41
|
-
3.
|
|
42
|
-
4.
|
|
39
|
+
1. **Verify TDD compliance** — every piece of production code must have corresponding tests
|
|
40
|
+
2. **Verify spec completeness** — every requirement from the architect's spec must be implemented
|
|
41
|
+
3. Run every check that CI runs — in the exact same way
|
|
42
|
+
4. Fix any failures you find (up to 3 attempts per issue)
|
|
43
|
+
5. Verify code quality and consistency across all changes
|
|
44
|
+
6. Report what you found and fixed
|
|
43
45
|
|
|
44
46
|
## CI/CD Pipeline Equivalence
|
|
45
47
|
|
|
@@ -74,6 +76,19 @@ SECURITY_REVIEW_REPORT:
|
|
|
74
76
|
|
|
75
77
|
After running CI checks, also review for:
|
|
76
78
|
|
|
79
|
+
### TDD Compliance (mandatory)
|
|
80
|
+
- **Every new function/method** has at least one test covering its primary behavior
|
|
81
|
+
- **Every bug fix** has a regression test that would fail without the fix
|
|
82
|
+
- **Edge cases and error paths** have dedicated tests, not just the happy path
|
|
83
|
+
- If any production code lacks tests, **this is a blocking issue** — either write the missing tests yourself or reject the review with clear instructions on what tests are needed
|
|
84
|
+
- Check test quality: tests should assert on behavior, not implementation details
|
|
85
|
+
|
|
86
|
+
### Spec Completeness (mandatory)
|
|
87
|
+
- Read the OpenSpec change spec in `openspec/changes/<name>/`
|
|
88
|
+
- **Every requirement listed in the spec must have a corresponding implementation** — cross-reference each spec item against the code changes
|
|
89
|
+
- If any spec requirement is missing or only partially implemented, **this is a blocking issue** — flag exactly which requirements are not fulfilled
|
|
90
|
+
- If the developer made assumptions about ambiguous spec items, verify they are reasonable
|
|
91
|
+
|
|
77
92
|
### Code Quality
|
|
78
93
|
{{CODE_QUALITY_CHECKLIST}}
|
|
79
94
|
|
|
@@ -52,8 +52,6 @@ Parse the YAML and extract:
|
|
|
52
52
|
- `config.models.preset` — `balanced`, `budget`, or `max` (see Model Presets below)
|
|
53
53
|
- `config.models.defaults.model` — default model override (overrides preset)
|
|
54
54
|
- `config.models.overrides` — per-agent model overrides (highest priority)
|
|
55
|
-
- `config.quick_context.product_description` — product description seed
|
|
56
|
-
- `config.quick_context.target_users` — target users seed
|
|
57
55
|
- `config.agent_teams` — boolean; whether to install team-review/team-debug commands
|
|
58
56
|
|
|
59
57
|
Store all values in variables prefixed `FC_`.
|
|
@@ -78,21 +76,19 @@ Set `SPECRAILS_DIR` and `CLI_PROVIDER` from resolved provider.
|
|
|
78
76
|
### FC3: If tier is `quick` — run Quick Mode with config context
|
|
79
77
|
|
|
80
78
|
If `FC_tier == "quick"`:
|
|
81
|
-
- Set `QS_PROJECT_DESCRIPTION = FC_quick_context.product_description`
|
|
82
|
-
- Set `QS_TARGET_USERS = FC_quick_context.target_users`
|
|
83
79
|
- Set `FC_AGENTS_SELECTED` as the list of agents to generate (instead of defaults)
|
|
84
|
-
- Execute Quick Mode (QS1–QS4)
|
|
80
|
+
- Execute Quick Mode (QS1–QS4), generating all `FC_AGENTS_SELECTED` agents (not just defaults)
|
|
85
81
|
- Then stop.
|
|
86
82
|
|
|
87
83
|
### FC4: If tier is `full` — run automated full wizard
|
|
88
84
|
|
|
89
85
|
**Phase 1 (Silent):** Run the full Phase 1 analysis (1.1–1.4) without any user prompts. Store all detected values internally.
|
|
90
86
|
|
|
91
|
-
**Phase 2 (
|
|
92
|
-
-
|
|
93
|
-
-
|
|
94
|
-
- Use
|
|
95
|
-
- Do not ask the user any questions — infer
|
|
87
|
+
**Phase 2 (AI-Inferred VPC Discovery):** Run VPC persona generation from codebase analysis:
|
|
88
|
+
- Analyze the codebase (README, package.json, source code, configs) to infer what the product does and who it serves
|
|
89
|
+
- Generate `PROJECT_DESCRIPTION` (2–3 sentence summary) and `TARGET_USERS` from analysis
|
|
90
|
+
- Use these inferred values to generate full VPC personas (3 primary, 3 secondary)
|
|
91
|
+
- Do not ask the user any questions — infer everything from codebase analysis
|
|
96
92
|
|
|
97
93
|
**Phase 3 (Silent):** Run Phase 3 normally without user prompts.
|
|
98
94
|
|
|
@@ -422,20 +418,26 @@ Update `.specrails/specrails-manifest.json` to reflect the new checksums for all
|
|
|
422
418
|
|
|
423
419
|
When `--quick` or `--lite` is passed, run this streamlined 3-question setup. Do NOT run Phase 1–5. When QS4 is complete, stop.
|
|
424
420
|
|
|
425
|
-
### QS1:
|
|
421
|
+
### QS1: Infer context and ask git access
|
|
426
422
|
|
|
427
|
-
|
|
423
|
+
**Step 1 — AI inference (silent):** Analyze the codebase to infer:
|
|
424
|
+
- `QS_PROJECT_DESCRIPTION` — a 2–3 sentence summary of what this project does (from README, package.json, source code, configs)
|
|
425
|
+
- `QS_TARGET_USERS` — who the target users are (from docs, UI copy, API design, domain language)
|
|
428
426
|
|
|
429
|
-
|
|
427
|
+
**Step 2 — Ask one question:**
|
|
430
428
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
429
|
+
Display the following prompt EXACTLY ONCE:
|
|
430
|
+
|
|
431
|
+
Welcome to specrails! Let's get your AI agent team set up.
|
|
432
|
+
|
|
433
|
+
I've analyzed your codebase:
|
|
434
|
+
- **Project:** {QS_PROJECT_DESCRIPTION}
|
|
435
|
+
- **Target users:** {QS_TARGET_USERS}
|
|
436
|
+
|
|
437
|
+
1. Git access for agents — read-only or read-write?
|
|
434
438
|
(read-only = agents can read and suggest; read-write = agents can commit)
|
|
435
439
|
|
|
436
|
-
Store the
|
|
437
|
-
- `QS_PROJECT_DESCRIPTION` — answer to question 1
|
|
438
|
-
- `QS_TARGET_USERS` — answer to question 2
|
|
440
|
+
Store the answer as:
|
|
439
441
|
- `QS_GIT_ACCESS` — "read-only" or "read-write" (normalize if user types "ro", "rw", "readonly", etc.)
|
|
440
442
|
|
|
441
443
|
### QS2: Apply opinionated defaults
|
|
@@ -497,8 +499,6 @@ Read `.specrails/setup-templates/claude-md/CLAUDE-quickstart.md` (or fall back t
|
|
|
497
499
|
|
|
498
500
|
Replace placeholders:
|
|
499
501
|
- `{{PROJECT_NAME}}` → derive from directory name or README.md first heading
|
|
500
|
-
- `{{PROJECT_DESCRIPTION}}` → `QS_PROJECT_DESCRIPTION`
|
|
501
|
-
- `{{TARGET_USERS}}` → `QS_TARGET_USERS`
|
|
502
502
|
- `{{GIT_ACCESS}}` → `QS_GIT_ACCESS`
|
|
503
503
|
|
|
504
504
|
Write to `CLAUDE.md` in the repo root. If `CLAUDE.md` already exists, ask:
|
|
@@ -515,8 +515,6 @@ If `.specrails/agents.yaml` exists, read it and apply model resolution (per-agen
|
|
|
515
515
|
|
|
516
516
|
Fill placeholders with best-effort values from the limited context available:
|
|
517
517
|
- `{{PROJECT_NAME}}` → directory name or README first heading
|
|
518
|
-
- `{{PROJECT_DESCRIPTION}}` → `QS_PROJECT_DESCRIPTION`
|
|
519
|
-
- `{{TARGET_USERS}}` → `QS_TARGET_USERS`
|
|
520
518
|
- `{{GIT_ACCESS}}` → `QS_GIT_ACCESS`
|
|
521
519
|
- `{{ARCHITECTURE_DIAGRAM}}` → "(Quick Mode — run `/specrails:enrich` for full architecture analysis)"
|
|
522
520
|
- `{{TECH_EXPERTISE}}` → "(Quick Mode — run `/specrails:enrich` for codebase-specific expertise)"
|